Cygwin: AF_UNIX: fix accept behaviour
* Use correct cygwait/WFSO invocation to not die on cancel and signals uncontrolled. * Manage io handles under io_lock. * Copy peer address to user space under SEH to avoid a resource leak. Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
parent
cde2648c22
commit
855e5d7e14
|
@ -901,6 +901,7 @@ fhandler_socket_unix::listen_pipe ()
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
IO_STATUS_BLOCK io;
|
IO_STATUS_BLOCK io;
|
||||||
HANDLE evt = NULL;
|
HANDLE evt = NULL;
|
||||||
|
DWORD waitret = WAIT_OBJECT_0;
|
||||||
|
|
||||||
io.Status = STATUS_PENDING;
|
io.Status = STATUS_PENDING;
|
||||||
if (!is_nonblocking () && !(evt = create_event ()))
|
if (!is_nonblocking () && !(evt = create_event ()))
|
||||||
|
@ -909,12 +910,18 @@ fhandler_socket_unix::listen_pipe ()
|
||||||
FSCTL_PIPE_LISTEN, NULL, 0, NULL, 0);
|
FSCTL_PIPE_LISTEN, NULL, 0, NULL, 0);
|
||||||
if (status == STATUS_PENDING)
|
if (status == STATUS_PENDING)
|
||||||
{
|
{
|
||||||
if (cygwait (evt ?: get_handle ()) == WAIT_OBJECT_0)
|
waitret = cygwait (evt ?: get_handle (), cw_infinite,
|
||||||
|
cw_cancel | cw_sig_eintr);
|
||||||
|
if (waitret == WAIT_OBJECT_0)
|
||||||
status = io.Status;
|
status = io.Status;
|
||||||
}
|
}
|
||||||
if (evt)
|
if (evt)
|
||||||
NtClose (evt);
|
NtClose (evt);
|
||||||
if (status == STATUS_PIPE_LISTENING)
|
if (waitret == WAIT_CANCELED)
|
||||||
|
pthread::static_cancel_self ();
|
||||||
|
else if (waitret == WAIT_SIGNALED)
|
||||||
|
set_errno (EINTR);
|
||||||
|
else if (status == STATUS_PIPE_LISTENING)
|
||||||
set_errno (EAGAIN);
|
set_errno (EAGAIN);
|
||||||
else if (status != STATUS_PIPE_CONNECTED)
|
else if (status != STATUS_PIPE_CONNECTED)
|
||||||
__seterrno_from_nt_status (status);
|
__seterrno_from_nt_status (status);
|
||||||
|
@ -929,7 +936,9 @@ fhandler_socket_unix::disconnect_pipe (HANDLE ph)
|
||||||
|
|
||||||
status = NtFsControlFile (ph, NULL, NULL, NULL, &io, FSCTL_PIPE_DISCONNECT,
|
status = NtFsControlFile (ph, NULL, NULL, NULL, &io, FSCTL_PIPE_DISCONNECT,
|
||||||
NULL, 0, NULL, 0);
|
NULL, 0, NULL, 0);
|
||||||
if (status == STATUS_PENDING && cygwait (ph) == WAIT_OBJECT_0)
|
/* Short-lived. Don't use cygwait. We don't want to be interrupted. */
|
||||||
|
if (status == STATUS_PENDING
|
||||||
|
&& WaitForSingleObject (ph, INFINITE) == WAIT_OBJECT_0)
|
||||||
status = io.Status;
|
status = io.Status;
|
||||||
if (!NT_SUCCESS (status))
|
if (!NT_SUCCESS (status))
|
||||||
{
|
{
|
||||||
|
@ -1290,13 +1299,17 @@ fhandler_socket_unix::accept4 (struct sockaddr *peer, int *len, int flags)
|
||||||
/* Our handle is now connected with a client. This handle is used
|
/* Our handle is now connected with a client. This handle is used
|
||||||
for the accepted socket. Our handle has to be replaced with a
|
for the accepted socket. Our handle has to be replaced with a
|
||||||
new instance handle for the next accept. */
|
new instance handle for the next accept. */
|
||||||
|
AcquireSRWLockExclusive (&io_lock);
|
||||||
HANDLE accepted = get_handle ();
|
HANDLE accepted = get_handle ();
|
||||||
HANDLE new_inst = create_pipe_instance ();
|
HANDLE new_inst = create_pipe_instance ();
|
||||||
int error = ENOBUFS;
|
int error = ENOBUFS;
|
||||||
if (new_inst)
|
if (!new_inst)
|
||||||
|
ReleaseSRWLockExclusive (&io_lock);
|
||||||
|
else
|
||||||
{
|
{
|
||||||
/* Set new io handle. */
|
/* Set new io handle. */
|
||||||
set_io_handle (new_inst);
|
set_io_handle (new_inst);
|
||||||
|
ReleaseSRWLockExclusive (&io_lock);
|
||||||
/* Prepare new file descriptor. */
|
/* Prepare new file descriptor. */
|
||||||
cygheap_fdnew fd;
|
cygheap_fdnew fd;
|
||||||
|
|
||||||
|
@ -1322,13 +1335,16 @@ fhandler_socket_unix::accept4 (struct sockaddr *peer, int *len, int flags)
|
||||||
sock->set_sun_path (get_sun_path ());
|
sock->set_sun_path (get_sun_path ());
|
||||||
error = sock->recv_peer_name ();
|
error = sock->recv_peer_name ();
|
||||||
if (error == 0)
|
if (error == 0)
|
||||||
|
{
|
||||||
|
__try
|
||||||
{
|
{
|
||||||
if (peer)
|
if (peer)
|
||||||
{
|
{
|
||||||
sun_name_t *sun = sock->get_peer_sun_path ();
|
sun_name_t *sun = sock->get_peer_sun_path ();
|
||||||
if (sun)
|
if (sun)
|
||||||
{
|
{
|
||||||
memcpy (peer, &sun->un, MIN (*len, sun->un_len));
|
memcpy (peer, &sun->un,
|
||||||
|
MIN (*len, sun->un_len));
|
||||||
*len = sun->un_len;
|
*len = sun->un_len;
|
||||||
}
|
}
|
||||||
else if (len)
|
else if (len)
|
||||||
|
@ -1339,6 +1355,12 @@ fhandler_socket_unix::accept4 (struct sockaddr *peer, int *len, int flags)
|
||||||
set_std_handle (fd);
|
set_std_handle (fd);
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
__except (NO_ERROR)
|
||||||
|
{
|
||||||
|
error = EFAULT;
|
||||||
|
}
|
||||||
|
__endtry
|
||||||
|
}
|
||||||
delete sock;
|
delete sock;
|
||||||
}
|
}
|
||||||
fd.release ();
|
fd.release ();
|
||||||
|
|
Loading…
Reference in New Issue