Mail Archives: cygwin/2004/04/14/23:17:34
----- Original Message -----
From: "Brian Ford" <ford AT vss DOT fsi DOT com>
To: "Enzo Michelangeli" <em AT em DOT no-ip DOT com>
Cc: <cygwin AT cygwin DOT com>
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:
em AT emnb ~/unsafesocket
$ cc -o unsafesocket unsafesocket.c
em AT emnb ~/unsafesocket
$ ./unsafesocket
usage: ./unsafesocket [n|y]
em AT emnb ~/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"
em AT emnb ~/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"
em AT emnb ~/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"
em AT emnb ~/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/
- Raw text -