Mailing-List: contact cygwin-help AT sourceware DOT cygnus DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT sources DOT redhat DOT com Delivered-To: mailing list cygwin AT sources DOT redhat DOT com Message-ID: <001801c07b31$d72a4720$904bb4ca@private> From: "David McNab" To: Subject: Winsock Bug Workaround - closing windows sockets Date: Wed, 10 Jan 2001 10:19:14 -0800 MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit X-Priority: 3 X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook Express 5.00.2919.6700 X-MimeOLE: Produced By Microsoft MimeOLE V5.00.2919.6700 Hi all, This might be really old news to all you old hands out there. But I'm sure some may benefit from this. I had been struggling with a problem regarding closing of sockets in Cygwin. The problem came up as I was testing the Cygwin/Win32 port of a Unix-based caching proxy called WWWOFFLE (http://www.gedanken.demon.co.uk/wwwoffle/). Under Cygwin 1.1.4, it worked reasonably ok. But under Cygwin 1.1.7, something weird was happening. Whenever the program sent a requested page back to the http client (Internet Explorer in this case), then closed the socket, the client would complain that the "connection to the server was reset". On setting up an http client test harness, I noticed something strange: When fetching a web page directly, or through any other proxy, the final read() call on the socket would return 0, which was the client's "cue" that all the page had been read, and the transaction was done. But when fetching a page through the Cygwin-built proxy, the final read() call on the socket was returning -1, in other words, an error. On further investigation, it appears that there is a bug in Winsock - the Windows 95/98/NT sockets implementation (on which cygwin's socket drivers are now built). The following C code demonstrates a very simple workaround to this bug. With this workaround in place, WWWOFFLE's Cygwin build is now working perfectly under Win32. Cheers David McNab #ifdef __CYGWIN__ int client_sock_flags; struct linger lingeropt; /* flush out the client socket - set it to blocking, then write to it */ client_sock_flags=fcntl(client,F_GETFL,0); if(client_sock_flags!=-1) /* enable blocking */ fcntl(client,F_SETFL,client_sock_flags & ~O_NONBLOCK); /* sent it a byte - guaranteed to block - ensure delivery of prior data */ /* yeah - this is a bit paranoid - try without this at first */ /* write(client, "\n", 1); */ /* this is the guts of the workaround for Winsock close bug */ shutdown(client, 1); /* enable lingering */ lingeropt.l_onoff = 1; lingeropt.l_linger = 15; setsockopt(client, SOL_SOCKET, SO_LINGER, &lingeropt, sizeof(lingeropt)); #endif /* Winsock bug averted - now we're safe to close the socket */ close(client); -- Want to unsubscribe from this list? Check out: http://cygwin.com/ml/#unsubscribe-simple