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> <20091120093210 DOT GQ29173 AT calimero DOT vinschen DOT de> Date: Sat, 21 Nov 2009 12:03:05 +0800 Message-ID: Subject: Re: [1.7] Updated: cygwin-1.7.0-65 From: Huang Bambo To: cygwin AT cygwin DOT com Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable X-IsSubscribed: yes Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , 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 #include #include #include #include #include #include #include #include #include #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 : > 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 > #include > #include > #include > #include > #include > > 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