* fhandler_socket.cc (get_inet_addr): Only test the file for being a

socket after opening it.  Retry if opening failed with sharing
	violation.  Explain why we do this.
	(fhandler_socket::bind): Create file with no sharing allowed.
This commit is contained in:
Corinna Vinschen 2010-04-13 19:56:30 +00:00
parent 2bba259eb7
commit 0ef4bb7c50
2 changed files with 39 additions and 14 deletions

View File

@ -1,3 +1,10 @@
2010-04-13 Corinna Vinschen <corinna@vinschen.de>
* fhandler_socket.cc (get_inet_addr): Only test the file for being a
socket after opening it. Retry if opening failed with sharing
violation. Explain why we do this.
(fhandler_socket::bind): Create file with no sharing allowed.
2010-04-13 John Bowman <bowman@math.ualberta.ca>
* cygheap.cc (cwcsdup): Fix allocation size to accommodate sizeof WCHAR.

View File

@ -38,6 +38,7 @@
#include "cygtls.h"
#include "cygwin/in6.h"
#include "ntdll.h"
#include "miscfuncs.h"
#define ASYNC_MASK (FD_READ|FD_WRITE|FD_OOB|FD_ACCEPT|FD_CONNECT)
#define EVENT_MASK (FD_READ|FD_WRITE|FD_OOB|FD_ACCEPT|FD_CONNECT|FD_CLOSE)
@ -94,21 +95,33 @@ get_inet_addr (const struct sockaddr *in, int inlen,
set_errno (ENOENT);
return 0;
}
if (!pc.issocket ())
/* Do NOT test for the file being a socket file here. The socket file
creation is not an atomic operation, so there is a chance that socket
files which are just in the process of being created are recognized
as non-socket files. To work around this problem we now create the
file with all sharing disabled. If the below NtOpenFile fails
with STATUS_SHARING_VIOLATION we know that the file already exists,
but the creating process isn't finished yet. So we yield and try
again, until we can either open the file successfully, or some error
other than STATUS_SHARING_VIOLATION occurs.
Since we now don't know if the file is actually a socket file, we
perform this check here explicitely. */
pc.get_object_attr (attr, sec_none_nih);
do
{
set_errno (EBADF);
return 0;
}
status = NtOpenFile (&fh, GENERIC_READ | SYNCHRONIZE,
pc.get_object_attr (attr, sec_none_nih), &io,
FILE_SHARE_VALID_FLAGS,
FILE_SYNCHRONOUS_IO_NONALERT
| FILE_OPEN_FOR_BACKUP_INTENT);
if (!NT_SUCCESS (status))
{
__seterrno_from_nt_status (status);
return 0;
status = NtOpenFile (&fh, GENERIC_READ | SYNCHRONIZE, &attr, &io,
FILE_SHARE_VALID_FLAGS,
FILE_SYNCHRONOUS_IO_NONALERT
| FILE_OPEN_FOR_BACKUP_INTENT);
if (status == STATUS_SHARING_VIOLATION)
yield ();
else if (!NT_SUCCESS (status))
{
__seterrno_from_nt_status (status);
return 0;
}
}
while (status == STATUS_SHARING_VIOLATION);
int ret = 0;
char buf[128];
memset (buf, 0, sizeof buf);
@ -119,6 +132,11 @@ get_inet_addr (const struct sockaddr *in, int inlen,
struct sockaddr_in sin;
char ctype;
sin.sin_family = AF_INET;
if (strncmp (buf, SOCKET_COOKIE, strlen (SOCKET_COOKIE)))
{
set_errno (EBADF);
return 0;
}
sscanf (buf + strlen (SOCKET_COOKIE), "%hu %c %08x-%08x-%08x-%08x",
&sin.sin_port,
&ctype,
@ -972,7 +990,7 @@ fhandler_socket::bind (const struct sockaddr *name, int namelen)
status = NtCreateFile (&fh, DELETE | FILE_GENERIC_WRITE,
pc.get_object_attr (attr, sa), &io, NULL, fattr,
FILE_SHARE_VALID_FLAGS, FILE_CREATE,
0, FILE_CREATE,
FILE_NON_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
| FILE_OPEN_FOR_BACKUP_INTENT,