From owner-freebsd-hackers Mon Aug 13 9: 5:10 2001 Delivered-To: freebsd-hackers@freebsd.org Received: from enterprise.spock.org (cm-24-29-85-81.nycap.rr.com [24.29.85.81]) by hub.freebsd.org (Postfix) with ESMTP id 8E0E337B40B for ; Mon, 13 Aug 2001 09:05:01 -0700 (PDT) (envelope-from jon@enterprise.spock.org) Received: (from jon@localhost) by enterprise.spock.org serial EF600Q3T-B7F8823f7DG4tC64342F7T for hackers@freebsd.org; Mon, 13 Aug 2001 12:04:55 -0400 (EDT) (envelope-from jon)$ Date: Mon, 13 Aug 2001 12:04:55 -0400 From: Jonathan Chen To: hackers@freebsd.org Subject: pthreads and poll() Message-ID: <20010813120455.A63309@enterprise.spock.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: telnet/1.1x Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG Yesterday marked my first attempt at mixing poll() with pthreads. Needless to say, things did not work out the way I wanted them to. So, I began the task of finding out the behaviors of various OSes to see if my code would run fine on them. For your reference and amusement, my results and test code is included below. I think that waking only one thread up is the correct behavior, or is there something that toggles which behavior I want? Perhaps someone with access to the POSIX standard would care to confirm what the Right Thing is? Perhaps that someone would then proceed to fix all the incorrect implementations... or am I asking too much? :) Looks like I'm going to have to swear off mixing poll() with pthreads for at least two years if I want my code to be portable... Aside: I thought that linuxthreads == Linux's implementation of pthreads? Now why do they behave differently? -Jon FreeBSD4/5 OpenBSD Linux IRIX AIX Solaris8 sys lth 2.8 2.4.1 6.5 4.3 5.8 poll/tcpaccept N Y N N Y N Y poll/udp N Y N Y * N Y poll/file N Y N Y * N Y Legend: FreeBSD tested with system pthread (sys), linuxthreads (lth) and GNU pth (pth). poll/tcpaccept - poll() before accept() of a tcp socket poll/udp - poll() before recv() of a udp socket poll/file - poll() before read() of a named fifo socket Y: only 1 thread wakes up. N: all threads wake up. *: IRIX's behavior seems to be nondeterministic. Perhaps IRIX has some AI to detect the best behavior... Nah... #include #include #include #include #include #include #include #include #include #include #include #ifdef _THREAD_SAFE # include #endif struct pollfd pfd; void* testcode(void* arg) { int ret; struct sockaddr_in addr; int len; char buf[1024]; fprintf(stderr,"thread %d: polling...\n", (int)arg); ret = poll(&pfd, 1, -1); if (ret != 1) fprintf(stderr,"thread %d: bad poll return %d\n", (int)arg, ret); fprintf(stderr,"thread %d: reading...\n", (int)arg); #if defined(TEST_TCP) len = sizeof(struct sockaddr_in); ret = accept(pfd.fd, (struct sockaddr*)&addr, &len); #elif defined(TEST_UDP) ret = recv(pfd.fd, buf, 1024, 0); #elif defined(TEST_READ) ret = read(pfd.fd, buf, 1024); #endif if (ret <= 0) fprintf(stderr,"thread %d: broken return %d %d %s\n", (int)arg, ret, errno, strerror(errno)); fprintf(stderr,"thread %d: exit\n", (int)arg); return 0; } int main(int argc, char* argv[]) { int tmp; #ifdef _THREAD_SAFE pthread_t threads[3]; #endif struct sockaddr_in addr; int len; srandom(time(NULL)); bzero(&addr, sizeof(struct sockaddr_in)); addr.sin_family=AF_INET; len=sizeof(struct sockaddr_in); addr.sin_port=htons(random()%10000+1024); pfd.events = POLLIN; #if defined(TEST_TCP) pfd.fd = socket(PF_INET, SOCK_STREAM, 0); bind(pfd.fd, (struct sockaddr*)&addr, len); listen(pfd.fd, 1); fprintf(stderr,"TCP listening on port %d\n", ntohs(addr.sin_port)); #elif defined(TEST_UDP) pfd.fd = socket(PF_INET, SOCK_DGRAM, 0); bind(pfd.fd, (struct sockaddr*)&addr, len); fprintf(stderr,"UDP listening on port %d\n", ntohs(addr.sin_port)); #elif defined(TEST_READ) pfd.fd = open("/tmp/testfile", O_RDONLY); fprintf(stderr,"File polling on /tmp/testfile\n", 94); #else assert(0); #endif tmp = fcntl(pfd.fd, F_SETFL, O_NONBLOCK); if (tmp != 0) fprintf(stderr, "fcntl returns %d %d %s\n", tmp, errno, strerror(errno)); #ifdef _THREAD_SAFE for (tmp = 0; tmp < 2; tmp++) { pthread_create(&(threads[tmp]), NULL, testcode, (void*)tmp); } #endif testcode((void*)-1); #ifdef _THREAD_SAFE for (tmp = 0; tmp < 2; tmp++) { pthread_join(threads[tmp], NULL); } #endif exit(0); } To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message