Mail Archives: cygwin/2009/11/20/23:04:07
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 -