This is the mail archive of the cygwin@sources.redhat.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Winsock Bug Workaround - closing windows sockets


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]