[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
pthreads, stack buffers, read and recv on OpenBSD 3.1
Hi,
I have a tcp sockets based client server application
that fails to work on OpenBSD 3.1. It is using
posix threads and I suspect that this is where the
problem lies. I have created a very cut down version
of the program to reproduce the problem - it is at the
foot of this e-mail.
The original program was written on SunOS 5.8 and
successfully ported to recent versions of IRIX, AIX,
Linux and HP-UX - it works fine on all of these.
Attached are two programs - a very simple client and
server and a make file to build them. The server built
without using threads "tserv" works fine when "tclient" is run
but the version built with pthreads returns "Bad address"
(EFAULT) on recv (or read) when "tclient" is run.
However, it is sensitive to the stack allocated buffer size.
If the buffer size is 73000 bytes and read size is 64000
it fails (EFAULT) but, strangley, it succeeds if the buffer
size is bigger (100000 bytes) and read size 73000.
Many thanks to anyone who takes a look at this.
Andy Fripp
client code: (tclient.c)
--------------------------------------------------------
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#define MYBUFSIZ 64000
void sendTest(int sockFd)
{
char buffer[MYBUFSIZ];
int sb;
sb = send(sockFd,buffer,MYBUFSIZ,0);
if (sb==-1) perror("send");
else printf("send ok\n");
}
int main(int argc, char *argv[])
{
int cfd;
struct sockaddr_in sa;
if ((cfd = socket(AF_INET, SOCK_STREAM, 0))==-1) return -1;
sa.sin_family = AF_INET;
sa.sin_port = htons(5100);
sa.sin_addr.s_addr = inet_addr("127.0.0.1");
if (connect(cfd,
(struct sockaddr*)&sa,
sizeof(struct sockaddr_in)) == -1) return -1;
if (cfd!=-1) {
sendTest(cfd);
close(cfd);
}
return 0;
}
--------------------------------------------------------
server code: (tserver.c)
--------------------------------------------------------
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#ifdef USE_THREADS
#include <pthread.h>
#endif
#include <unistd.h>
#include <stdio.h>
/* BIGBUFSIZ READSIZ */
/* 64000 64000 - ok */
/* 73000 64000 - get Bad address */
/* 100000 73000 - ok */
#define BIGBUFSIZ 73000
#define READSIZ 64000
void *recvTest(void *aPtr)
{
char buffer[BIGBUFSIZ];
int rb;
int conFd = *(int*)aPtr;
rb = recv(conFd,buffer,READSIZ,0);
if (rb==-1) perror("recv");
else printf("recv %d bytes ok\n",rb);
close(conFd);
}
int main(int argc, char *argv[])
{
int lfd,cfd,enable;
struct sockaddr_in sa;
struct sockaddr_in remoteAddress;
socklen_t lenAddress = sizeof(remoteAddress);
if ((lfd = socket(AF_INET, SOCK_STREAM, 0))==-1) return -1;
if ( setsockopt(lfd,
SOL_SOCKET,
SO_REUSEADDR,
&enable,
sizeof(int)) == -1 ) return -1;
sa.sin_family = AF_INET;
sa.sin_port = htons(5100);
sa.sin_addr.s_addr = INADDR_ANY;
if ( bind(lfd,
(struct sockaddr *)&sa,
sizeof(struct sockaddr_in)) == -1) return -1;
if (listen(lfd,1)==-1) return -1;
while (1) {
cfd = accept(lfd,
(struct sockaddr *) &remoteAddress,
&lenAddress);
if (cfd!=-1) {
#ifdef USE_THREADS
pthread_t newThreadId;
void *ret;
printf("new thread\n");
pthread_create(&newThreadId,NULL,recvTest,&cfd);
#else
recvTest(&cfd);
#endif
}
}
return 0;
}
--------------------------------------------------------
makefile:
--------------------------------------------------------
CC=gcc
all: tclient tserv tservth
tclient: tclient.c
$(CC) tclient.c -o tclient
tserv: tserv.c
$(CC) tserv.c -o tserv
tservth: tserv.c
$(CC) tserv.c -o tservth -pthread -DUSE_THREADS
--------------------------------------------------------
uname -a output:
--------------------------------------------------------
OpenBSD sol 3.1 GENERIC#59 i386
--------------------------------------------------------
dmesg output
--------------------------------------------------------
OpenBSD 3.1 (GENERIC) #59: Sat Apr 13 15:28:52 MDT 2002
deraadt@i386.openbsd.org:/usr/src/sys/arch/i386/compile/GENERIC
cpu0: Intel Pentium III (Coppermine) ("GenuineIntel" 686-class) 993 MHz
cpu0:
FPU,V86,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SYS,MTRR,PGE,MCA,CMOV,PAT,PSE36,MMX,
FXSR,SIMD
real mem = 267960320 (261680K)
avail mem = 242671616 (236984K)
using 3296 buffers containing 13500416 bytes (13184K) of memory
mainbus0 (root)
bios0 at mainbus0: AT/286+(00) BIOS, date 05/25/01, BIOS32 rev. 0 @ 0xffe90
pcibios0 at bios0: rev. 2.1 @ 0xf0000/0x10000
pcibios0: PCI IRQ Routing Table rev. 1.0 @ 0xfc270/160 (8 entries)
pcibios0: no compatible PCI ICU found: ICU vendor 0x1166 product 0x0200
pcibios0: Warning, unable to fix up PCI interrupt routing
pcibios0: PCI bus #0 is the last bus
bios0: ROM list: 0xc0000/0x8000 0xc8000/0x6000 0xec000/0x4000!
pci0 at mainbus0 bus 0: configuration mode 1 (no bios)
pchb0 at pci0 dev 0 function 0 "ServerWorks CNB20HE Host" rev 0x23
pchb1 at pci0 dev 0 function 1 "ServerWorks CNB20HE Host" rev 0x01
pci1 at pchb1 bus 2
ppb0 at pci1 dev 2 function 0 "Intel i960 RM PCI-PCI" rev 0x02
pci2 at ppb0 bus 3
ahc1 at pci2 dev 4 function 0 "Adaptec AIC-7899 U160" rev 0x01: irq 10
ahc1: Wide Channel A, SCSI Id=7, 16/255 SCBs
scsibus0 at ahc1: 16 targets
ahc1: target 0 using 16bit transfers
ahc1: target 0 synchronous at 40.0MHz, offset = 0x7f
ahc1: target 0 using tagged queuing
sd0 at scsibus0 targ 0 lun 0: <QUANTUM, ATLAS10K3_18_SCA, 120G> SCSI3
0/direct fixed
sd0: 17366MB, 31022 cyl, 2 head, 573 sec, 512 bytes/sec, 35566478 sec total
ahc1: target 6 using 8bit transfers
ahc1: target 6 using asynchronous transfers
uk0 at scsibus0 targ 6 lun 0: <DELL, 1x4 U2W SCSI BP, 1.30> SCSI2
3/processor fixed
uk0: unknown device
ahc2 at pci2 dev 4 function 1 "Adaptec AIC-7899 U160" rev 0x01: irq 5
ahc2: Wide Channel A, SCSI Id=7, 16/255 SCBs
scsibus1 at ahc2: 16 targets
ahc2: target 6 using 16bit transfers
ahc2: target 6 synchronous at 40.0MHz, offset = 0x20
st0 at scsibus1 targ 6 lun 0: <ARCHIVE, Python 06408-XXX, 8160> SCSI3
1/sequential removable
st0: drive empty
fxp0 at pci1 dev 4 function 0 "Intel 82557" rev 0x08: irq 5, address
00:06:5b:3c:79:ec
inphy0 at fxp0 phy 1: i82555 10/100 media interface, rev. 4
pchb2 at pci0 dev 0 function 2 "ServerWorks I/O Bridge" rev 0x01
pchb3 at pci0 dev 0 function 3 "ServerWorks I/O Bridge" rev 0x01
pci3 at pchb3 bus 1
bge0 at pci3 dev 8 function 0 "Broadcom BCM5700" rev 0x12: irq 10: Ethernet
address: 00:06:5b:3c:79:ed
brgphy0 at bge0 phy 1: BCM5401 1000baseTX PHY, rev. 3
vga1 at pci0 dev 14 function 0 "ATI Rage XL" rev 0x27
wsdisplay0 at vga1: console (80x25, vt100 emulation)
wsdisplay0: screen 1-5 added (80x25, vt100 emulation)
pcib0 at pci0 dev 15 function 0 "ServerWorks ROSB4 SouthBridge" rev 0x50
pciide0 at pci0 dev 15 function 1 "ServerWorks IDE" rev 0x00: DMA
(unsupported), channel 0 configured to compatibility, channel 1 configured
to compatibility
atapiscsi0 at pciide0 channel 0 drive 0
scsibus2 at atapiscsi0: 2 targets
cd0 at scsibus2 targ 0 lun 0: <SAMSUNG, CD-ROM SN-124, q009> SCSI0 5/cdrom
removable
pciide0: channel 1 ignored (not responding; disabled or no drives?)
isa0 at pcib0
isadma0 at isa0
pckbc0 at isa0 port 0x60/5
pckbd0 at pckbc0 (kbd slot)
pckbc0: using irq 1 for kbd slot
wskbd0 at pckbd0: console keyboard, using wsdisplay0
pms0 at pckbc0 (aux slot)
pckbc0: using irq 12 for aux slot
wsmouse0 at pms0 mux 0
pcppi0 at isa0 port 0x61
midi0 at pcppi0: <PC speaker>
sysbeep0 at pcppi0
lpt0 at isa0 port 0x378/4 irq 7
npx0 at isa0 port 0xf0/16: using exception 16
pccom0 at isa0 port 0x3f8/8 irq 4: ns16550a, 16 byte fifo
pccom1 at isa0 port 0x2f8/8 irq 3: ns16550a, 16 byte fifo
fdc0 at isa0 port 0x3f0/6 irq 6 drq 2
fd0 at fdc0 drive 0: 1.44MB 80 cyl, 2 head, 18 sec
biomask 4460 netmask 4460 ttymask 54e2
pctr: 686-class user-level performance counters enabled
mtrr: Pentium Pro MTRR support
dkcsum: sd0 matched BIOS disk 80
root on sd0a
rootdev=0x400 rrootdev=0xd00 rawdev=0xd02
--------------------------------------------------------