Winsock closesocket() problem

Jason Tishler jason@tishler.net
Thu Mar 6 14:38:00 GMT 2003


Pierre and I have been working (privately) to solve the exim problem
that I mentioned in the following post:

    http://cygwin.com/ml/cygwin-developers/2003-02/msg00125.html

It appears that under certain conditions Winsock's closesocket() is not
happy closing a socket more than once.  See the attached test case,
sc9.cc, which demonstrates the problem when run under LocalSystem:

    $ sc9
    close(fd2) failed with 108

Note that the problem follows the second close().  If I switch the order
of the close() calls, then dup()-ed socket closes without any errors.
Hence, I don't believe that this problem is directly related to dup().

I have worked around the problem with the attached patch to
fhandler_socket::close().  Is this a reasonable way to solve this
problem?  Or, does anyone have any other suggestions?

BTW, this is YA problem that goes away under strace and gdb, which make
debugging this problem difficult.  Sigh...

Thanks,
Jason

-- 
PGP/GPG Key: http://www.tishler.net/jason/pubkey.asc or key servers
Fingerprint: 7A73 1405 7F2B E669 C19D  8784 1AFD E4CC ECF4 8EF6
-------------- next part --------------
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>

int
main()
{
	int status = 0;

	int fd = socket(AF_INET, SOCK_STREAM, 0);
	if (fd < 0)
	{
		printf("socket() failed with %d\n", errno);
		return 1;
	}

	status = setgid(1009); // mail group = 1009
	if (status < 0)
	{
		printf("setgid() failed with %d\n", errno);
		return 1;
	}

	status = setgroups(0, 0);
	if (status < 0)
	{
		printf("setgroups() failed with %d\n", errno);
		return 1;
	}

	status = setuid(1008); // exim user = 1008
	if (status < 0)
	{
		printf("setgid() failed with %d\n", errno);
		return 1;
	}

	int fd2 = dup(fd);
	if (fd2 < 0)
	{
		printf("dup() failed with %d\n", errno);
		return 1;
	}

	status = close(fd);
	if (status != 0)
	{
		printf("close(fd) failed with %d\n", errno);
		return 1;
	}

	status = close(fd2);
	if (status != 0)
	{
		printf("close(fd2) failed with %d\n", errno);
		return 1;
	}

	return 0;
}
-------------- next part --------------
Index: fhandler_socket.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/fhandler_socket.cc,v
retrieving revision 1.85
diff -u -p -r1.85 fhandler_socket.cc
--- fhandler_socket.cc	4 Mar 2003 16:35:00 -0000	1.85
+++ fhandler_socket.cc	6 Mar 2003 14:17:49 -0000
@@ -1200,6 +1200,14 @@ fhandler_socket::close ()
 
   while ((res = closesocket (get_socket ())) != 0)
     {
+      // Ignore WSAENOTSOCK errors
+      if (WSAGetLastError () == WSAENOTSOCK)
+	{
+	  WSASetLastError (0);
+	  set_winsock_errno ();
+	  res = 0;
+	  break;
+	}
       if (WSAGetLastError () != WSAEWOULDBLOCK)
 	{
 	  set_winsock_errno ();


More information about the Cygwin-developers mailing list