----- Original Message ----- From: "Brian Ford" <[EMAIL PROTECTED]> To: "Enzo Michelangeli" <[EMAIL PROTECTED]> Cc: <[EMAIL PROTECTED]> Sent: Thursday, April 15, 2004 1:05 AM Subject: Re: 1.5.9-1: socket() appears NOT to be thread-safe
> On Wed, 14 Apr 2004, Enzo Michelangeli wrote: > > > While porting to Cygwin the Linux application "sipd" > > (http://www.sxdesign.com/index.php?page=developer&submnu=sipd ), > > which uses pthreads, I noticed that socket() calls issued > > concurrently by several threads often failed, with > > strerror(errno) saying "operation not permitted". Once I > > protected all the calls with mutex locks, such errors > > went away. Is Cygwin's implementation of socket() known to be > > thread-unsafe? > > FWIW, I have seen this symptom as well, primarily on a dual CPU, > Hyperthreaded XP box under 1.5.[8|9]+. In fact, I just confirmed > it still exists in a current CVS build from this morning. > > It seems like a race condition. Running under strace fixes it, > so it has been difficult to isolate. If I have time, I'll try > to look at it again soon. Would you like to work on it together? What I can do for the time being is to provide the testcase that Corinna asked for (attached below). Here are the results: [EMAIL PROTECTED] ~/unsafesocket $ cc -o unsafesocket unsafesocket.c [EMAIL PROTECTED] ~/unsafesocket $ ./unsafesocket usage: ./unsafesocket [n|y] [EMAIL PROTECTED] ~/unsafesocket $ ./unsafesocket n NOT protecting socket() call with mutex: Thread 0: socket() returned 3, strerror(errno)="No error" Thread 1: socket() returned -1, strerror(errno)="Operation not permitted" Thread 2: socket() returned -1, strerror(errno)="Operation not permitted" Thread 3: socket() returned 3, strerror(errno)="No error" [EMAIL PROTECTED] ~/unsafesocket $ ./unsafesocket n NOT protecting socket() call with mutex: Thread 0: socket() returned -1, strerror(errno)="Operation not permitted" Thread 1: socket() returned 3, strerror(errno)="No error" Thread 2: socket() returned -1, strerror(errno)="Operation not permitted" Thread 3: socket() returned -1, strerror(errno)="Operation not permitted" [EMAIL PROTECTED] ~/unsafesocket $ ./unsafesocket y Protecting socket() call with mutex: Thread 0: socket() returned 3, strerror(errno)="No error" Thread 1: socket() returned 4, strerror(errno)="No error" Thread 2: socket() returned 5, strerror(errno)="No error" Thread 3: socket() returned 6, strerror(errno)="No error" [EMAIL PROTECTED] ~/unsafesocket $ By the way, even in case of no error the socket calls return the same value of fd. Is this OK?? Cheers -- Enzo --------- begin unsafesocket.c --------- #include <sys/socket.h> #include <netinet/in.h> #include <errno.h> #include <stdio.h> #include <pthread.h> #define MAXTHREADS 4 static int sync_with_mutex = 0; struct thrdata { int thrnum; pthread_t t; int socket_fd; int socket_errno; } th[MAXTHREADS]; static void *thread_code(void *p); main(int argc, char *argv[]) { int i; if(argc == 1) { printf("usage: %s [n|y]\n", argv[0]); exit(1); } if(argv[1][0] == 'y' || argv[1][0] == 'Y') { printf("Protecting socket() call with mutex:\n"); sync_with_mutex = 1; } else { printf("NOT protecting socket() call with mutex:\n"); sync_with_mutex = 0; } for(i=0; i<MAXTHREADS; i++) { th[i].thrnum = i; pthread_create(&th[i].t, NULL, thread_code, (void *)&(th[i])); } for(i=0; i<MAXTHREADS; i++) { pthread_join(th[i].t, NULL); } for(i=0; i<MAXTHREADS; i++) { printf("Thread %d: socket() returned %d, strerror(errno)=\"%s\"\n", i, th[i].socket_fd, strerror(th[i].socket_errno)); if(th[i].socket_fd > 0) close(th[i].socket_fd); } exit(0); } static void *thread_code(void *p) { struct thrdata *pt = (struct thrdata *)p; int fd; struct sockaddr_in sa; static pthread_mutex_t __mutex = PTHREAD_MUTEX_INITIALIZER; bzero(&(sa), sizeof(sa)); sa.sin_family = AF_INET; sa.sin_addr.s_addr = htonl(INADDR_ANY); sa.sin_port = 1024 + pt->thrnum; if(sync_with_mutex) { pthread_mutex_lock(&__mutex); /* begin critical area */ } fd = socket(AF_INET, SOCK_DGRAM, 0); if(sync_with_mutex) { pthread_mutex_unlock(&__mutex); /* begin critical area */ } /* report results to main thread */ pt->socket_fd = fd; pt->socket_errno = errno; return(NULL); } --------- end unsafesocket.c --------- -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Problem reports: http://cygwin.com/problems.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/