delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin/2009/11/20/23:04:07

X-Recipient: archive-cygwin AT delorie DOT com
X-SWARE-Spam-Status: No, hits=-1.0 required=5.0 tests=AWL,BAYES_00,SARE_MSGID_LONG40,SPF_PASS
X-Spam-Check-By: sourceware.org
MIME-Version: 1.0
In-Reply-To: <20091120093210.GQ29173@calimero.vinschen.de>
References: <20091119094439 DOT GC29173 AT calimero DOT vinschen DOT de> <f4d6f44b0911191814r4653debfu24cbd4afd956f117 AT mail DOT gmail DOT com> <20091120093210 DOT GQ29173 AT calimero DOT vinschen DOT de>
Date: Sat, 21 Nov 2009 12:03:05 +0800
Message-ID: <f4d6f44b0911202003j71954bf0lf5b6696acdfe7e7d@mail.gmail.com>
Subject: Re: [1.7] Updated: cygwin-1.7.0-65
From: Huang Bambo <bambo DOT huang AT gmail DOT com>
To: cygwin AT cygwin DOT com
X-IsSubscribed: yes
Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm
List-Id: <cygwin.cygwin.com>
List-Unsubscribe: <mailto:cygwin-unsubscribe-archive-cygwin=delorie DOT com AT cygwin DOT com>
List-Subscribe: <mailto:cygwin-subscribe AT cygwin DOT com>
List-Archive: <http://sourceware.org/ml/cygwin/>
List-Post: <mailto:cygwin AT cygwin DOT com>
List-Help: <mailto:cygwin-help AT cygwin DOT com>, <http://sourceware.org/ml/#faqs>
Sender: cygwin-owner AT cygwin DOT com
Mail-Followup-To: cygwin AT cygwin DOT com
Delivered-To: mailing list cygwin AT cygwin DOT com

Sorry for my bad expression. I mean the fd duplicated by fork() will
not be close
by both parent and child.
The following code listen on port 9999, parent process fork a child to
handle the
incoming socket and then close the socket. The child sleep 3 second and clo=
se
the incoming socket. The socket should be closed now but not. And some tools
can show tcp connection state showed there's still one connection from clie=
nt
program (telnet) to the parent process. Client program can't receive any cl=
ose
message  and still waiting for message untile parent process exit.

code
++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <sys/errno.h>


#define MYPORT 9999

int nRunning;

void sig_handler( int nSignal)
{
	nRunning =3D 0;
}

int main( void )
{
	nRunning =3D 1;
	struct sockaddr_in server_addr;
	struct sockaddr_in client_addr; // connector's address information
	socklen_t sin_size;
	int yes=3D1;
	if( signal( SIGINT, sig_handler ) =3D=3D SIG_ERR )
	{
		perror( "signal()" );
		return -1;
	}
	int sock_fd =3D socket( AF_INET, SOCK_STREAM, 0 );
	if ( sock_fd =3D=3D -1 )
	{
		perror( "socket()" );
		return -1;
	}
	if (setsockopt( sock_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) =3D=
=3D -1)
	{
		perror( "setsockopt()" );
		return -1;
	}
	server_addr.sin_family =3D AF_INET;         // host byte order
	server_addr.sin_port =3D htons( MYPORT);     // short, network byte order
	server_addr.sin_addr.s_addr =3D INADDR_ANY; // automatically fill with my =
IP
	memset( server_addr.sin_zero, '\0', sizeof(server_addr.sin_zero));

	if (bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) =
=3D=3D -1)
	{
		perror("bind()");
		return -1;
	}
	if (listen(sock_fd, 5) =3D=3D -1)
	{
		perror("listen");
		return -1;
	}
	printf("listen port %d\n", MYPORT );

	fd_set fdsr;
	int maxsock;
	struct timeval tv;

	sin_size =3D sizeof(client_addr);
	maxsock =3D sock_fd;

	while(nRunning)
	{
		FD_ZERO(&fdsr);
		FD_SET(sock_fd,&fdsr);

		tv.tv_sec =3D 10;
		tv.tv_usec =3D 0;

		int nRet =3D select( maxsock + 1, &fdsr, NULL, NULL, &tv );

		if ( nRet =3D=3D 0 || (nRet < 0 && errno =3D=3D EINTR ))
		{
			// timeout or interrupted by signal
			continue;
		}
		else if ( nRet < 0 )
		{
			perror("select()");
			printf("%d");
			close(sock_fd);
			return -1;
		}
		if ( FD_ISSET( sock_fd, &fdsr))
		{
			int new_fd =3D accept(sock_fd, (struct sockaddr *)&client_addr, &sin_siz=
e);
			if ( new_fd <=3D 0 )
			{
				perror("accept");
				continue;
			}
			else
			{
				printf("Incoming socket %d\n", new_fd);
				pid_t pid =3D fork();
				if ( pid =3D=3D -1 )
				{
					perror("fork()");
					close(new_fd);
					continue;
				}
				else if ( pid =3D=3D 0 )
				{
					//child
					printf("Child %d fork OK.\n", getpid() );
					sleep(3);
					printf("Child %d close client socket %d\n", getpid(), new_fd);
					close(new_fd);
					return 0;
				}
				else
				{
					//parent
					printf("Parent %d close client socket %d\n", getpid(), new_fd);
					close(new_fd);
					continue;
				}
			}
		}
	}
	printf("Parent %d close server socket %d\n", getpid(), sock_fd);
	close(sock_fd);
	return 0;
}


2009/11/20 Corinna Vinschen <corinna-cygwin AT cygwin DOT com>:
> On Nov 20 10:14, Huang Bambo wrote:
>> I think there maybe some bug with new "socket duplication" function.
>> While I use ssh to connect remote cygwin, with previous version of
>> cygwin, after type exit command, shell will close and sshd will close
>> the connection forwardly but with 65 version connection will not close
>> by sshd untile I type "net stop sshd" to stop sshd service.
>
> That's weird. =A0I can not reproduce it. =A0Here's what happens in -65:
>
> Normally sockets are inheritable system objects. =A0They can be duplicated
> via DuplicateHandle and they can be inherited to child processes in
> calls to CreateProcess.
> Some applications install a so-called socket provider which is added to
> the Windows socket stack. =A0These socket providers act like a filter
> driver between the applicaton and the OS sockets. =A0From the application
> perspective they are still sockets, but depending on how the filter
> driver is written, they lack certain features. =A0One of them is the
> abilty to be duplicated via DuplicateHandle and to be inherited to child
> processes.
>
> If that's the case we need to duplicate sockets using a complicated
> mechanism using one call in the parent process (WSADuplicateSocket) and
> one call in the child process (WSASocket).
> So what Cygwin now does is trying to figure out if the just created
> socket is a "good", inheritable socket, or a "bad", non-inheritable
> socket. =A0In the first case, the usual duplication is used, in the
> second case, WSADuplicateSocket/WSASocket is used.
>
> When testing ssh connections, I have no problems either way. =A0Usually
> I have no 3rd party socket providers installed, so my machines use the
> default way for "good" sockets. =A0If I enforce the usage of the code for
> "bad" sockets, it still works fine and the connection is closed
> immediately on exit.
>
> Your description of the problem implies that it worked fine for you
> so far, as long as Cygwin 1.7 was only using the "good" socket method.
> When using -65, Cygwin tries to figure out what kind of socket your
> socket is and apparently finds it to be a "bad" socket so it uses the
> matching socket duplication technique.
>
> The bad joke here is this: =A0Per MSDN, the "bad" socket method is the
> only blessed one. =A0So, *if* onle of these methods is supposed to
> work every time, it's that method.
>
> That's annoying. =A0I hate to say that in this case, but could you
> please check for potential BLODAs per this list:
> http://cygwin.com/1.7/faq/faq.using.html#faq.using.bloda
>
> And, for a start, can you please run the below testcase and paste the
> output into your reply?
>
> $ cat > dup-sock.c << EOF
> #include <stdio.h>
> #include <windows.h>
> #include <winsock2.h>
> #include <ws2spi.h>
> #include <ddk/ntapi.h>
> #include <ddk/ntifs.h>
>
> int
> main (int argc, char **argv)
> {
> =A0WSADATA wsadata;
> =A0SOCKET sock_fd;
> =A0NTSTATUS status;
> =A0OBJECT_HANDLE_ATTRIBUTE_INFORMATION ohai;
> =A0ULONG len =3D 0;
> =A0WSAPROTOCOL_INFOA pinf;
> =A0int i;
>
> =A0WSAStartup ((2<<8) | 2, &wsadata);
> =A0sock_fd =3D socket (AF_INET, SOCK_STREAM, 0);
> =A0if (sock_fd < 0)
> =A0 =A0{
> =A0 =A0 =A0printf ("socket failed: %lu\n", WSAGetLastError ());
> =A0 =A0 =A0return 1;
> =A0 =A0}
>
> =A0status =3D ZwQueryObject ((HANDLE) sock_fd, ObjectHandleInformation,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0&ohai, sizeof ohai, NU=
LL);
> =A0if (!NT_SUCCESS (status))
> =A0 =A0printf ("NtQueryObject failed: %p\n", status);
> =A0else
> =A0 =A0printf ("Inherit: %d\n", ohai.Inherit);
>
> =A0if (WSADuplicateSocketA (sock_fd, GetCurrentProcessId (), &pinf))
> =A0 =A0printf ("WSADuplicateSocket failed: %lu\n", WSAGetLastError ());
> =A0else
> =A0 =A0{
> =A0 =A0 =A0WCHAR path[256];
> =A0 =A0 =A0INT len =3D 256;
> =A0 =A0 =A0INT err;
>
> =A0 =A0 =A0printf ("dwServiceFlags1: %p\n", pinf.dwServiceFlags1);
> =A0 =A0 =A0printf ("dwServiceFlags2: %p\n", pinf.dwServiceFlags2);
> =A0 =A0 =A0printf ("dwServiceFlags3: %p\n", pinf.dwServiceFlags3);
> =A0 =A0 =A0printf ("dwServiceFlags4: %p\n", pinf.dwServiceFlags4);
> =A0 =A0 =A0printf ("dwProviderFlags: %p\n", pinf.dwProviderFlags);
> =A0 =A0 =A0printf ("ProviderId: %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%=
02X%02X\n",
> =A0 =A0 =A0 =A0 =A0 =A0 =A0pinf.ProviderId.Data1, pinf.ProviderId.Data2,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0pinf.ProviderId.Data3,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0pinf.ProviderId.Data4[0], pinf.ProviderId.Data=
4[1],
> =A0 =A0 =A0 =A0 =A0 =A0 =A0pinf.ProviderId.Data4[2], pinf.ProviderId.Data=
4[3],
> =A0 =A0 =A0 =A0 =A0 =A0 =A0pinf.ProviderId.Data4[4], pinf.ProviderId.Data=
4[5],
> =A0 =A0 =A0 =A0 =A0 =A0 =A0pinf.ProviderId.Data4[6], pinf.ProviderId.Data=
4[7]);
> =A0 =A0 =A0printf ("dwCatalogEntryId: %p\n", pinf.dwCatalogEntryId);
> =A0 =A0 =A0printf ("ProtocolChain: [len: %d]\n", pinf.ProtocolChain.Chain=
Len);
> =A0 =A0 =A0for (i =3D 0; i < pinf.ProtocolChain.ChainLen; ++i)
> =A0 =A0 =A0 =A0printf (" =A0 =A0%d: %p\n", pinf.ProtocolChain.ChainEntrie=
s[i]);
> =A0 =A0 =A0printf ("iVersion: %d\n", pinf.iVersion);
> =A0 =A0 =A0printf ("iAddressFamily: %d\n", pinf.iAddressFamily);
> =A0 =A0 =A0printf ("iMaxSockAddr: %d\n", pinf.iMaxSockAddr);
> =A0 =A0 =A0printf ("iMinSockAddr: %d\n", pinf.iMinSockAddr);
> =A0 =A0 =A0printf ("iSocketType: %d\n", pinf.iSocketType);
> =A0 =A0 =A0printf ("iProtocol: %d\n", pinf.iProtocol);
> =A0 =A0 =A0printf ("iProtocolMaxOffset: %d\n", pinf.iProtocolMaxOffset);
> =A0 =A0 =A0printf ("iNetworkByteOrder: %d\n", pinf.iNetworkByteOrder);
> =A0 =A0 =A0printf ("iSecurityScheme: %d\n", pinf.iSecurityScheme);
> =A0 =A0 =A0printf ("dwMessageSize: %lu\n", pinf.dwMessageSize);
> =A0 =A0 =A0printf ("dwProviderReserved: %lu\n", pinf.dwProviderReserved);
> =A0 =A0 =A0printf ("szProtocol: %s\n", pinf.szProtocol);
> =A0 =A0 =A0if (WSCGetProviderPath (&pinf.ProviderId, path, &len, &err))
> =A0 =A0 =A0 =A0printf ("WSCGetProviderPath failed: %lu\n", err);
> =A0 =A0 =A0else
> =A0 =A0 =A0 =A0printf ("ProviderPath: %ls\n", path);
> =A0 =A0}
>
> =A0closesocket (sock_fd);
> =A0WSACleanup ();
> =A0return 0;
> }
> EOF
> $ gcc-3 -mno-cygwin -g -o dup-sock dup-sock.c
> $ ./dup-sock
> [... output to be pasted ...]
>
> And, please attach your cygcheck -s -v -r output per
> http://cygwin.com/problems.html
>
>
> Thanks,
> Corinna
>
> --
> Corinna Vinschen =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0Please, send mails re=
garding Cygwin to
> Cygwin Project Co-Leader =A0 =A0 =A0 =A0 =A0cygwin AT cygwin DOT com
> Red Hat
>
> --
> Problem reports: =A0 =A0 =A0 http://cygwin.com/problems.html
> FAQ: =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 http://cygwin.com/faq/
> Documentation: =A0 =A0 =A0 =A0 http://cygwin.com/docs.html
> Unsubscribe info: =A0 =A0 =A0http://cygwin.com/ml/#unsubscribe-simple
>
>

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019