public inbox for cygwin@cygwin.com
 help / color / mirror / Atom feed
* write big buffer to connected socket, then close socket hangs cygwin
@ 2008-07-15 15:36 kalle ko
  2008-07-15 17:09 ` Corinna Vinschen
  0 siblings, 1 reply; 2+ messages in thread
From: kalle ko @ 2008-07-15 15:36 UTC (permalink / raw)
  To: cygwin

[-- Attachment #1: Type: text/plain, Size: 364 bytes --]

Latest updated cygwin (just updated to make sure), Windows Vista SP1.

This will hang cygwin 1.5.25-cr-0x5f1:
1. Create a connected socket
2. Send a big enough buffer (> 0x4238 bytes)
3. Close the socket

It will hang in the close() function. Only way is to kill it with
taskmanager or close the cygwin window. Source code is attached.
$ gcc bug.c -o bug && ./bug

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: bug.c --]
[-- Type: text/x-csrc; name=bug.c, Size: 1642 bytes --]

#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>

int setNonBlock(int sock)
{
	if (fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, 0) | O_NONBLOCK) == -1)
	{
		perror("set non-block");
		exit(1);
	}
	return 1;
}

int main()
{
	int sock1, sock2, socklisten;
	struct sockaddr_in sa;
	socklen_t saLen;
	/* Anything > 0x4238 will hang cygwin. Tested Vista SP1, cygwin1.dll
	   file version 1005.25.0.0, product version 1.5.25-cr-0x5f1
	   CYGWIN_NT-6.0 bbqpc 1.5.25(0.156/4/2) 2008-06-12 19:34 i686 Cygwin
	*/
	char buf[0x4238 + 1];

	memset(&sa, 0, sizeof(sa));
	sa.sin_family = AF_INET;
	sa.sin_port = htons(1234);
	sa.sin_addr.s_addr = htonl(0x7F000001);
	saLen = sizeof(sa);
	if ((socklisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1 ||
		!setNonBlock(socklisten) ||
		bind(socklisten, (struct sockaddr*)&sa, sizeof(sa)) == -1 ||
		listen(socklisten, 5) == -1 ||
		getsockname(socklisten, (struct sockaddr*)&sa, &saLen) == -1 ||
		(sock1 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1 ||
		!setNonBlock(sock1) ||
		(connect(sock1, (struct sockaddr*)&sa, sizeof(sa)) == -1 && errno != EINPROGRESS))
	{
		perror("socket init");
		exit(1);
	}

	printf("Trying to accept()\n");
	while ((sock2 = accept(socklisten, 0, 0)) == -1)
		/* wait */;

	printf("Sending\n");
	while (send(sock1, buf, sizeof(buf), 0) == -1)
	{
		if (errno != EALREADY)
		{
			perror("send");
			exit(1);
		}
	}

	printf("Closing\n");
	close(sock1);

	printf("OK\n");
	return 0;
}

[-- Attachment #3: Type: text/plain, Size: 218 bytes --]

--
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/

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: write big buffer to connected socket, then close socket hangs  cygwin
  2008-07-15 15:36 write big buffer to connected socket, then close socket hangs cygwin kalle ko
@ 2008-07-15 17:09 ` Corinna Vinschen
  0 siblings, 0 replies; 2+ messages in thread
From: Corinna Vinschen @ 2008-07-15 17:09 UTC (permalink / raw)
  To: cygwin

On Jul 15 17:35, kalle ko wrote:
> Latest updated cygwin (just updated to make sure), Windows Vista SP1.
> 
> This will hang cygwin 1.5.25-cr-0x5f1:
> 1. Create a connected socket
> 2. Send a big enough buffer (> 0x4238 bytes)
> 3. Close the socket
> 
> It will hang in the close() function. Only way is to kill it with
> taskmanager or close the cygwin window. Source code is attached.

Thanks for the testcase.

There's nothing in Cygwin's socket code which would make it dependent on
the buffer size given to the send() function.

Your scenario triggers the auto-linger in Cygwin's socket close()
function, which has been added many years ago to workaround a problem
with WinSock on application exit.  For some reason the linger doesn't
timeout (which it should after about 4 minutes), as soon as the sent
buffer is bigger than this weird 0x4238.  Since Cygwin doesn't handle
anything differently due to size, this looks like a WinSock problem we
just never encountered.

To fix this in your application, you should call shutdown(SHUT_WR)
before calling close().  This seems to be fixed in the next Cygwin
release 1.7 which doesn't linger in close anymore, but due to limited
testing it's still not entirely clear if that's ok now.


Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Project Co-Leader          cygwin AT cygwin DOT com
Red Hat

--
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/

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2008-07-15 17:09 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-07-15 15:36 write big buffer to connected socket, then close socket hangs cygwin kalle ko
2008-07-15 17:09 ` Corinna Vinschen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).