* net.cc (SIO_BASE_HANDLE): Define.
(fdsock): If we got an LSP handle, try to create a copy of the base handle instead. Change comment to explain.
This commit is contained in:
parent
b8fe0ec799
commit
a011f95216
|
@ -1,3 +1,9 @@
|
||||||
|
2011-03-29 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* net.cc (SIO_BASE_HANDLE): Define.
|
||||||
|
(fdsock): If we got an LSP handle, try to create a copy of the base
|
||||||
|
handle instead. Change comment to explain.
|
||||||
|
|
||||||
2011-03-29 Corinna Vinschen <corinna@vinschen.de>
|
2011-03-29 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* include/cygwin/version.h: Bump CYGWIN_VERSION_DLL_MINOR to 10.
|
* include/cygwin/version.h: Bump CYGWIN_VERSION_DLL_MINOR to 10.
|
||||||
|
|
|
@ -480,6 +480,10 @@ cygwin_getprotobynumber (int number)
|
||||||
return dup_ent (getprotobynumber (number));
|
return dup_ent (getprotobynumber (number));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef SIO_BASE_HANDLE
|
||||||
|
#define SIO_BASE_HANDLE _WSAIOR(IOC_WS2,34)
|
||||||
|
#endif
|
||||||
|
|
||||||
bool
|
bool
|
||||||
fdsock (cygheap_fdmanip& fd, const device *dev, SOCKET soc)
|
fdsock (cygheap_fdmanip& fd, const device *dev, SOCKET soc)
|
||||||
{
|
{
|
||||||
|
@ -488,50 +492,69 @@ fdsock (cygheap_fdmanip& fd, const device *dev, SOCKET soc)
|
||||||
fd = build_fh_dev (*dev);
|
fd = build_fh_dev (*dev);
|
||||||
if (!fd.isopen ())
|
if (!fd.isopen ())
|
||||||
return false;
|
return false;
|
||||||
fd->set_io_handle ((HANDLE) soc);
|
|
||||||
if (!((fhandler_socket *) fd)->init_events ())
|
|
||||||
return false;
|
|
||||||
fd->set_flags (O_RDWR | O_BINARY);
|
|
||||||
fd->uninterruptible_io (true);
|
|
||||||
debug_printf ("fd %d, name '%s', soc %p", (int) fd, dev->name, soc);
|
|
||||||
|
|
||||||
/* Usually sockets are inheritable IFS objects. Unfortunately some virus
|
/* Usually sockets are inheritable IFS objects. Unfortunately some virus
|
||||||
scanners or other network-oriented software replace normal sockets
|
scanners or other network-oriented software replace normal sockets
|
||||||
with their own kind, which is running through a filter driver.
|
with their own kind, which is running through a filter driver called
|
||||||
|
"layered service provider" (LSP).
|
||||||
|
|
||||||
The result is that these new sockets are not normal kernel objects
|
LSP sockets are not kernel objects. They are typically not marked as
|
||||||
anymore. They are typically not marked as inheritable, nor are they
|
inheritable, nor are they IFS handles. They are in fact not inheritable
|
||||||
IFS handles, as normal OS sockets are. They are in fact not inheritable
|
to child processes, and it does not help to mark them inheritable via
|
||||||
to child processes, and subsequent socket calls in the child process
|
SetHandleInformation. Subsequent socket calls in the child process fail
|
||||||
will fail with error 10038, WSAENOTSOCK. And worse, while DuplicateHandle
|
with error 10038, WSAENOTSOCK.
|
||||||
on these sockets mostly works in the process which created the socket,
|
|
||||||
DuplicateHandle does quite often not work anymore in a child process.
|
|
||||||
It does not help to mark them inheritable via SetHandleInformation.
|
|
||||||
|
|
||||||
The only way to make these sockets usable in child processes is to
|
The only way up to Windows Server 2003 to make these sockets usable in
|
||||||
duplicate them via WSADuplicateSocket/WSASocket calls. This requires
|
child processes is to duplicate them via WSADuplicateSocket/WSASocket
|
||||||
to start the child process in SUSPENDED state so we only do this on
|
calls. This requires to start the child process in SUSPENDED state so
|
||||||
affected systems. If we recognize a non-inheritable socket, or if
|
we only do this on affected systems. If we recognize a non-inheritable
|
||||||
the XP1_IFS_HANDLES flag is not set in a call to WSADuplicateSocket,
|
socket we switch to inheritance/dup via WSADuplicateSocket/WSASocket for
|
||||||
we switch to inheritance/dup via WSADuplicateSocket/WSASocket for
|
that socket.
|
||||||
that socket. */
|
|
||||||
|
Starting with Vista there's another neat way to workaround these annoying
|
||||||
|
LSP sockets. WSAIoctl allows to fetch the underlying base socket, which
|
||||||
|
is a normal, inheritable IFS handle. So we fetch the base socket,
|
||||||
|
duplicate it, and close the original socket. Now we have a standard IFS
|
||||||
|
socket which (hopefully) works as expected. */
|
||||||
DWORD flags;
|
DWORD flags;
|
||||||
#if 0
|
bool fixup = false;
|
||||||
/* Disable checking for IFS handle for now. In theory, checking the fact
|
|
||||||
that the socket handle is not inheritable should be sufficient. */
|
|
||||||
WSAPROTOCOL_INFOW wpi;
|
|
||||||
#endif
|
|
||||||
if (!GetHandleInformation ((HANDLE) soc, &flags)
|
if (!GetHandleInformation ((HANDLE) soc, &flags)
|
||||||
|| !(flags & HANDLE_FLAG_INHERIT))
|
|| !(flags & HANDLE_FLAG_INHERIT))
|
||||||
#if 0
|
{
|
||||||
|| WSADuplicateSocketW (soc, GetCurrentProcessId (), &wpi)
|
int ret;
|
||||||
/* dwProviderReserved contains the actual SOCKET value of the duplicated
|
SOCKET base_soc;
|
||||||
socket. Close it or suffer a handle leak. Worse, one socket for each
|
DWORD bret;
|
||||||
connection remains in CLOSE_WAIT state. */
|
|
||||||
|| (closesocket ((SOCKET) wpi.dwProviderReserved), FALSE)
|
fixup = true;
|
||||||
|| !(wpi.dwServiceFlags1 & XP1_IFS_HANDLES))
|
debug_printf ("LSP handle: %p", soc);
|
||||||
#endif
|
ret = WSAIoctl (soc, SIO_BASE_HANDLE, NULL, 0, (void *) &base_soc,
|
||||||
|
sizeof (base_soc), &bret, NULL, NULL);
|
||||||
|
if (ret)
|
||||||
|
debug_printf ("WSAIoctl: %lu", WSAGetLastError ());
|
||||||
|
else if (base_soc != soc
|
||||||
|
&& GetHandleInformation ((HANDLE) base_soc, &flags)
|
||||||
|
&& (flags & HANDLE_FLAG_INHERIT))
|
||||||
|
{
|
||||||
|
if (!DuplicateHandle (GetCurrentProcess (), (HANDLE) base_soc,
|
||||||
|
GetCurrentProcess (), (PHANDLE) &base_soc,
|
||||||
|
0, TRUE, DUPLICATE_SAME_ACCESS))
|
||||||
|
debug_printf ("DuplicateHandle failed, %E");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
closesocket (soc);
|
||||||
|
soc = base_soc;
|
||||||
|
fixup = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fd->set_io_handle ((HANDLE) soc);
|
||||||
|
if (!((fhandler_socket *) fd)->init_events ())
|
||||||
|
return false;
|
||||||
|
if (fixup)
|
||||||
((fhandler_socket *) fd)->init_fixup_before ();
|
((fhandler_socket *) fd)->init_fixup_before ();
|
||||||
|
fd->set_flags (O_RDWR | O_BINARY);
|
||||||
|
fd->uninterruptible_io (true);
|
||||||
|
debug_printf ("fd %d, name '%s', soc %p", (int) fd, dev->name, soc);
|
||||||
|
|
||||||
/* Raise default buffer sizes (instead of WinSock default 8K).
|
/* Raise default buffer sizes (instead of WinSock default 8K).
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue