From mboxrd@z Thu Jan 1 00:00:00 1970 From: Troy Noble To: "'Keith Seitz'" , Roderick Groesbeek Cc: cygwin@cygwin.com Subject: RE: 1.3.2: Cygwin && UDP && O_NONBLOCK Date: Tue, 14 Aug 2001 12:54:00 -0000 Message-id: <8F23E55D511AD5119A6800D0B76FDDE1CA302A@cpex3.channelpoint.com> X-SW-Source: 2001-08/msg00637.html Roderick, Unless I misunderstood entirely, I think you've found a bug. I got the same blocking behavior you described when testing (after fixing many of the same things that Keith described in his mail). And it does appear to be inconsistent with behavior on Linux for the same program as you noted. Looks like there was a fix for some code related to setting up the non-blocking behavior in fhandler_socket.cc:fctl on Aug 13, 2001 so the flags are set properly now, but the recvfrom appears not to be checking for the non-blocking flag. I updated my src tree from CVS today and tested, and it still exhibits the blocking behavior you describe. The problem appears to be the wait for an event at net.cc:93 which looks like: switch (WSAWaitForMultipleEvents(2, ev, FALSE, WSA_INFINITE, FALSE)) There seem to be at least two ways to fix it, otherwise I'd just submit a patch. But I don't know that I understand the philosopy entirely, so it'd be best to defer to Corinna's better judgement. It seems to me in net.cc:recvfrom one of the following needs to happen: 1. if ((h->get_flags() & O_NONBLOCK_MASK) || !(ovr = wsock_evt.prepare ())) { ... which would cause behavior to revert to Winsock 1.1's recvfrom which appears to do the right thing, at least in my minimal testing. 2. add another check for !(h->get_flags() & O_NONBLOCK_MASK) before calling wait(...) in the overlapped section of code before net.cc:537. 3. I guess a test of the same sort as #2 above might be appropriate inside wait() around line 93 instead. It's not entirely as straightforward detecting when no data is there when using non-blocking sockets with the overlapped calls. Ok, that's technically 3 ways. Troy -----Original Message----- From: Keith Seitz [ mailto:keiths@cygnus.com ] Sent: Tuesday, August 14, 2001 10:34 AM To: Roderick Groesbeek Cc: cygwin@cygwin.com Subject: Re: 1.3.2: Cygwin && UDP && O_NONBLOCK On Tue, 14 Aug 2001, Roderick Groesbeek wrote: > #ifdef __linux__ > #include > #endif > #ifdef __CYGWIN__ > #include > #endif Why not just #include ? > > #include > #include > > > > #define BUFSIZE 1024 > > int main(int argc, char* argv[], char* env[]) > { > int sock; > int ret; > char buf[BUFSIZE]; > struct sockaddr_in me, from; > unsigned int from_len; > > int flags; > > > sock = socket(PF_INET, SOCK_DGRAM, 0); > > if (sock < 0) { > perror("socket"); > exit(1); > } > > flags = fcntl(sock, F_GETFL, 0); > ret = fcntl(sock, F_SETFL, flags & ~O_NONBLOCK); > printf("ret=%d|\n", ret); This fcntl stuff shouldn't really be necessary, but it should do no harm. > bzero((char*) &from, sizeof(from)); Ugh. You mean "bzero (&me, sizeof (me));"? > me.sin_family = AF_INET; > me.sin_addr.s_addr = htonl(INADDR_ANY); > me.sin_port = htons(1025); > ret = bind(sock, (struct sockaddr *) & me, sizeof(me)); > if (ret < 0) { > perror("bind"); > exit(1); > } > while(1) { > int len; > > len = recvfrom(sock, buf, BUFSIZE, 0, (struct sockaddr *) &from, > &from_len); This is not correct. from_len is not initialized (typo?). You MUST set it to "sizeof (from)". This is a "value/result argument". > perror("recvfrom"); > printf("len=%d|\n", len); > } > > return 0; > } FWIW, I tried the following program on my system and had no problems whatsoever, with or without SET_BLOCKING set. #include #include #include #ifdef SET_BLOCKING #include #endif #ifdef __CYGWIN__ typedef unsigned int socklen_t; #endif int main (int argc, char *argv[]) { int ret; char buf[1024]; socklen_t len; struct sockaddr_in my_addr, client_addr; int sock; #ifdef SET_BLOCKING int flags; #endif sock = socket (AF_INET, SOCK_DGRAM, 0); if (sock < 0) { perror ("couldn't create socket"); exit (1); } #ifdef SET_BLOCKING flags = fcntl (sock, F_GETFL, 0); flags &= ~O_NONBLOCK; ret = fcntl (sock, F_SETFL, flags); if (ret < 0) { perror ("couldn't force blocking"); exit (1); } #endif bzero (&my_addr, sizeof (my_addr)); my_addr.sin_family = AF_INET; my_addr.sin_addr.s_addr = htonl (INADDR_ANY); my_addr.sin_port = htons (10025); if (bind (sock, (struct sockaddr *) &my_addr, sizeof (my_addr)) < 0) { perror ("couldn't bind to address"); exit (1); } while (1) { len = sizeof (client_addr); ret = recvfrom (sock, buf, 1024, 0, (struct sockaddr *) &client_addr, &len); printf ("recvfrom returned %d\n", ret); if (ret < 0) { perror ("error getting data from socket"); continue; } /* Do something with the data. Echo it. */ ret = sendto (sock, buf, ret, 0, (struct sockaddr *) &client_addr, len); if (ret < 0) { perror ("error sending data"); continue; } printf ("Sent %d bytes to client at %x\n", ret, client_addr.sin_addr.s_addr); } return 0; } -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Bug reporting: http://cygwin.com/bugs.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/ -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Bug reporting: http://cygwin.com/bugs.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/