This is the mail archive of the cygwin 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]
Other format: [Raw text]

Re: [1.7] Updated: cygwin-1.7.0-65


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 close
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 client
program (telnet) to the parent process. Client program can't receive any close
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 = 0;
}

int main( void )
{
	nRunning = 1;
	struct sockaddr_in server_addr;
	struct sockaddr_in client_addr; // connector's address information
	socklen_t sin_size;
	int yes=1;
	if( signal( SIGINT, sig_handler ) == SIG_ERR )
	{
		perror( "signal()" );
		return -1;
	}
	int sock_fd = socket( AF_INET, SOCK_STREAM, 0 );
	if ( sock_fd == -1 )
	{
		perror( "socket()" );
		return -1;
	}
	if (setsockopt( sock_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
	{
		perror( "setsockopt()" );
		return -1;
	}
	server_addr.sin_family = AF_INET;         // host byte order
	server_addr.sin_port = htons( MYPORT);     // short, network byte order
	server_addr.sin_addr.s_addr = 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)) == -1)
	{
		perror("bind()");
		return -1;
	}
	if (listen(sock_fd, 5) == -1)
	{
		perror("listen");
		return -1;
	}
	printf("listen port %d\n", MYPORT );

	fd_set fdsr;
	int maxsock;
	struct timeval tv;

	sin_size = sizeof(client_addr);
	maxsock = sock_fd;

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

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

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

		if ( nRet == 0 || (nRet < 0 && errno == 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 = accept(sock_fd, (struct sockaddr *)&client_addr, &sin_size);
			if ( new_fd <= 0 )
			{
				perror("accept");
				continue;
			}
			else
			{
				printf("Incoming socket %d\n", new_fd);
				pid_t pid = fork();
				if ( pid == -1 )
				{
					perror("fork()");
					close(new_fd);
					continue;
				}
				else if ( pid == 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@cygwin.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. ?I can not reproduce it. ?Here's what happens in -65:
>
> Normally sockets are inheritable system objects. ?They 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. ?These socket providers act like a filter
> driver between the applicaton and the OS sockets. ?From the application
> perspective they are still sockets, but depending on how the filter
> driver is written, they lack certain features. ?One 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. ?In 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. ?Usually
> I have no 3rd party socket providers installed, so my machines use the
> default way for "good" sockets. ?If 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: ?Per MSDN, the "bad" socket method is the
> only blessed one. ?So, *if* onle of these methods is supposed to
> work every time, it's that method.
>
> That's annoying. ?I 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)
> {
> ?WSADATA wsadata;
> ?SOCKET sock_fd;
> ?NTSTATUS status;
> ?OBJECT_HANDLE_ATTRIBUTE_INFORMATION ohai;
> ?ULONG len = 0;
> ?WSAPROTOCOL_INFOA pinf;
> ?int i;
>
> ?WSAStartup ((2<<8) | 2, &wsadata);
> ?sock_fd = socket (AF_INET, SOCK_STREAM, 0);
> ?if (sock_fd < 0)
> ? ?{
> ? ? ?printf ("socket failed: %lu\n", WSAGetLastError ());
> ? ? ?return 1;
> ? ?}
>
> ?status = ZwQueryObject ((HANDLE) sock_fd, ObjectHandleInformation,
> ? ? ? ? ? ? ? ? ? ? ? ? ?&ohai, sizeof ohai, NULL);
> ?if (!NT_SUCCESS (status))
> ? ?printf ("NtQueryObject failed: %p\n", status);
> ?else
> ? ?printf ("Inherit: %d\n", ohai.Inherit);
>
> ?if (WSADuplicateSocketA (sock_fd, GetCurrentProcessId (), &pinf))
> ? ?printf ("WSADuplicateSocket failed: %lu\n", WSAGetLastError ());
> ?else
> ? ?{
> ? ? ?WCHAR path[256];
> ? ? ?INT len = 256;
> ? ? ?INT err;
>
> ? ? ?printf ("dwServiceFlags1: %p\n", pinf.dwServiceFlags1);
> ? ? ?printf ("dwServiceFlags2: %p\n", pinf.dwServiceFlags2);
> ? ? ?printf ("dwServiceFlags3: %p\n", pinf.dwServiceFlags3);
> ? ? ?printf ("dwServiceFlags4: %p\n", pinf.dwServiceFlags4);
> ? ? ?printf ("dwProviderFlags: %p\n", pinf.dwProviderFlags);
> ? ? ?printf ("ProviderId: %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\n",
> ? ? ? ? ? ? ?pinf.ProviderId.Data1, pinf.ProviderId.Data2,
> ? ? ? ? ? ? ?pinf.ProviderId.Data3,
> ? ? ? ? ? ? ?pinf.ProviderId.Data4[0], pinf.ProviderId.Data4[1],
> ? ? ? ? ? ? ?pinf.ProviderId.Data4[2], pinf.ProviderId.Data4[3],
> ? ? ? ? ? ? ?pinf.ProviderId.Data4[4], pinf.ProviderId.Data4[5],
> ? ? ? ? ? ? ?pinf.ProviderId.Data4[6], pinf.ProviderId.Data4[7]);
> ? ? ?printf ("dwCatalogEntryId: %p\n", pinf.dwCatalogEntryId);
> ? ? ?printf ("ProtocolChain: [len: %d]\n", pinf.ProtocolChain.ChainLen);
> ? ? ?for (i = 0; i < pinf.ProtocolChain.ChainLen; ++i)
> ? ? ? ?printf (" ? ?%d: %p\n", pinf.ProtocolChain.ChainEntries[i]);
> ? ? ?printf ("iVersion: %d\n", pinf.iVersion);
> ? ? ?printf ("iAddressFamily: %d\n", pinf.iAddressFamily);
> ? ? ?printf ("iMaxSockAddr: %d\n", pinf.iMaxSockAddr);
> ? ? ?printf ("iMinSockAddr: %d\n", pinf.iMinSockAddr);
> ? ? ?printf ("iSocketType: %d\n", pinf.iSocketType);
> ? ? ?printf ("iProtocol: %d\n", pinf.iProtocol);
> ? ? ?printf ("iProtocolMaxOffset: %d\n", pinf.iProtocolMaxOffset);
> ? ? ?printf ("iNetworkByteOrder: %d\n", pinf.iNetworkByteOrder);
> ? ? ?printf ("iSecurityScheme: %d\n", pinf.iSecurityScheme);
> ? ? ?printf ("dwMessageSize: %lu\n", pinf.dwMessageSize);
> ? ? ?printf ("dwProviderReserved: %lu\n", pinf.dwProviderReserved);
> ? ? ?printf ("szProtocol: %s\n", pinf.szProtocol);
> ? ? ?if (WSCGetProviderPath (&pinf.ProviderId, path, &len, &err))
> ? ? ? ?printf ("WSCGetProviderPath failed: %lu\n", err);
> ? ? ?else
> ? ? ? ?printf ("ProviderPath: %ls\n", path);
> ? ?}
>
> ?closesocket (sock_fd);
> ?WSACleanup ();
> ?return 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 ? ? ? ? ? ? ? ? ?Please, send mails regarding Cygwin to
> Cygwin Project Co-Leader ? ? ? ? ?cygwin AT cygwin DOT com
> Red Hat
>
> --
> 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
>
>

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


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