Cygwin: AF_UNIX: store per-socket info in shared memory
Per-socket info in fhandler isn't correctly shared between multiple instances of th same descriptor. Implement a basic shared info which is shared between all instances of a socket. This also requires to move the fhandler_socket status bits into fhandler_socket_wsock since the data is moved to the shared region for AF_UNIX sockets. Also, drop backing file requirement for socketpair server socket. This will be handled differently in recvmsg/sendmsg. Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
parent
c8d96a96ea
commit
725176612d
@ -525,34 +525,6 @@ class fhandler_socket: public fhandler_base
|
|||||||
DWORD &rcvtimeo () { return _rcvtimeo; }
|
DWORD &rcvtimeo () { return _rcvtimeo; }
|
||||||
DWORD &sndtimeo () { return _sndtimeo; }
|
DWORD &sndtimeo () { return _sndtimeo; }
|
||||||
|
|
||||||
protected:
|
|
||||||
struct status_flags
|
|
||||||
{
|
|
||||||
unsigned async_io : 1; /* async I/O */
|
|
||||||
unsigned saw_shutdown_read : 1; /* Socket saw a SHUT_RD */
|
|
||||||
unsigned saw_shutdown_write : 1; /* Socket saw a SHUT_WR */
|
|
||||||
unsigned saw_reuseaddr : 1; /* Socket saw SO_REUSEADDR call */
|
|
||||||
public:
|
|
||||||
status_flags () :
|
|
||||||
async_io (0), saw_shutdown_read (0), saw_shutdown_write (0),
|
|
||||||
saw_reuseaddr (0)
|
|
||||||
{}
|
|
||||||
} status;
|
|
||||||
LONG _connection_state;
|
|
||||||
LONG _binding_state;
|
|
||||||
public:
|
|
||||||
IMPLEMENT_STATUS_FLAG (bool, async_io)
|
|
||||||
IMPLEMENT_STATUS_FLAG (bool, saw_shutdown_read)
|
|
||||||
IMPLEMENT_STATUS_FLAG (bool, saw_shutdown_write)
|
|
||||||
IMPLEMENT_STATUS_FLAG (bool, saw_reuseaddr)
|
|
||||||
|
|
||||||
conn_state connect_state (conn_state val)
|
|
||||||
{ return (conn_state) InterlockedExchange (&_connection_state, val); }
|
|
||||||
conn_state connect_state () const { return (conn_state) _connection_state; }
|
|
||||||
bind_state binding_state (bind_state val)
|
|
||||||
{ return (bind_state) InterlockedExchange (&_binding_state, val); }
|
|
||||||
bind_state binding_state () const { return (bind_state) _binding_state; }
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
fhandler_socket ();
|
fhandler_socket ();
|
||||||
~fhandler_socket ();
|
~fhandler_socket ();
|
||||||
@ -637,6 +609,27 @@ class fhandler_socket_wsock: public fhandler_socket
|
|||||||
int evaluate_events (const long event_mask, long &events, const bool erase);
|
int evaluate_events (const long event_mask, long &events, const bool erase);
|
||||||
const LONG serial_number () const { return wsock_events->serial_number; }
|
const LONG serial_number () const { return wsock_events->serial_number; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
struct status_flags
|
||||||
|
{
|
||||||
|
unsigned async_io : 1; /* async I/O */
|
||||||
|
unsigned saw_shutdown_read : 1; /* Socket saw a SHUT_RD */
|
||||||
|
unsigned saw_shutdown_write : 1; /* Socket saw a SHUT_WR */
|
||||||
|
unsigned saw_reuseaddr : 1; /* Socket saw SO_REUSEADDR call */
|
||||||
|
unsigned connect_state : 3;
|
||||||
|
public:
|
||||||
|
status_flags () :
|
||||||
|
async_io (0), saw_shutdown_read (0), saw_shutdown_write (0),
|
||||||
|
saw_reuseaddr (0), connect_state (unconnected)
|
||||||
|
{}
|
||||||
|
} status;
|
||||||
|
public:
|
||||||
|
IMPLEMENT_STATUS_FLAG (bool, async_io)
|
||||||
|
IMPLEMENT_STATUS_FLAG (bool, saw_shutdown_read)
|
||||||
|
IMPLEMENT_STATUS_FLAG (bool, saw_shutdown_write)
|
||||||
|
IMPLEMENT_STATUS_FLAG (bool, saw_reuseaddr)
|
||||||
|
IMPLEMENT_STATUS_FLAG (conn_state, connect_state)
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct _WSAPROTOCOL_INFOW *prot_info_ptr;
|
struct _WSAPROTOCOL_INFOW *prot_info_ptr;
|
||||||
public:
|
public:
|
||||||
@ -850,23 +843,101 @@ class sun_name_t
|
|||||||
void operator delete (void *p) {cfree (p);}
|
void operator delete (void *p) {cfree (p);}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Internal representation of shutdown states */
|
||||||
|
enum shut_state {
|
||||||
|
_SHUT_READ = 1,
|
||||||
|
_SHUT_WRITE = 2,
|
||||||
|
_SHUT_RW = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
/* For each AF_UNIX socket, we need to maintain socket-wide data,
|
||||||
|
regardless of the number of descriptors. The shmem region gets created
|
||||||
|
in socket, socketpair or accept4 and reopened by dup, fork or exec. */
|
||||||
|
class af_unix_shmem_t
|
||||||
|
{
|
||||||
|
SRWLOCK _bind_lock;
|
||||||
|
SRWLOCK _conn_lock;
|
||||||
|
SRWLOCK _io_lock;
|
||||||
|
LONG _connection_state; /* conn_state */
|
||||||
|
LONG _binding_state; /* bind_state */
|
||||||
|
LONG _shutdown; /* shut_state */
|
||||||
|
LONG _so_error; /* SO_ERROR */
|
||||||
|
LONG _reuseaddr; /* dummy */
|
||||||
|
|
||||||
|
public:
|
||||||
|
af_unix_shmem_t ()
|
||||||
|
: _connection_state (unconnected), _binding_state (unbound),
|
||||||
|
_shutdown (0), _so_error (0)
|
||||||
|
{
|
||||||
|
InitializeSRWLock (&_bind_lock);
|
||||||
|
InitializeSRWLock (&_conn_lock);
|
||||||
|
InitializeSRWLock (&_io_lock);
|
||||||
|
}
|
||||||
|
void bind_lock () { AcquireSRWLockExclusive (&_bind_lock); }
|
||||||
|
void bind_unlock () { ReleaseSRWLockExclusive (&_bind_lock); }
|
||||||
|
void conn_lock () { AcquireSRWLockExclusive (&_conn_lock); }
|
||||||
|
void conn_unlock () { ReleaseSRWLockExclusive (&_conn_lock); }
|
||||||
|
void io_lock () { AcquireSRWLockExclusive (&_io_lock); }
|
||||||
|
void io_unlock () { ReleaseSRWLockExclusive (&_io_lock); }
|
||||||
|
|
||||||
|
conn_state connect_state (conn_state val)
|
||||||
|
{ return (conn_state) InterlockedExchange (&_connection_state, val); }
|
||||||
|
conn_state connect_state () const { return (conn_state) _connection_state; }
|
||||||
|
|
||||||
|
bind_state binding_state (bind_state val)
|
||||||
|
{ return (bind_state) InterlockedExchange (&_binding_state, val); }
|
||||||
|
bind_state binding_state () const { return (bind_state) _binding_state; }
|
||||||
|
|
||||||
|
int shutdown (int shut)
|
||||||
|
{ return (int) InterlockedExchange (&_shutdown, shut); }
|
||||||
|
int shutdown () const { return (int) _shutdown; }
|
||||||
|
|
||||||
|
int so_error (int err)
|
||||||
|
{ return (int) InterlockedExchange (&_so_error, err); }
|
||||||
|
int so_error () const { return _so_error; }
|
||||||
|
|
||||||
|
int reuseaddr (int val)
|
||||||
|
{ return (int) InterlockedExchange (&_reuseaddr, val); }
|
||||||
|
int reuseaddr () const { return _reuseaddr; }
|
||||||
|
};
|
||||||
|
|
||||||
class fhandler_socket_unix : public fhandler_socket
|
class fhandler_socket_unix : public fhandler_socket
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
SRWLOCK conn_lock;
|
HANDLE shmem_handle; /* Shared memory region used to share
|
||||||
SRWLOCK bind_lock;
|
socket-wide state. */
|
||||||
SRWLOCK io_lock;
|
af_unix_shmem_t *shmem;
|
||||||
HANDLE backing_file_handle; /* Either NT symlink or INVALID_HANDLE_VALUE,
|
HANDLE backing_file_handle; /* Either NT symlink or INVALID_HANDLE_VALUE,
|
||||||
if the socket is backed by a file in the
|
if the socket is backed by a file in the
|
||||||
file system (actually a reparse point) */
|
file system (actually a reparse point) */
|
||||||
HANDLE connect_wait_thr;
|
HANDLE connect_wait_thr;
|
||||||
HANDLE cwt_termination_evt;
|
HANDLE cwt_termination_evt;
|
||||||
PVOID cwt_param;
|
PVOID cwt_param;
|
||||||
LONG so_error;
|
|
||||||
sun_name_t *sun_path;
|
sun_name_t *sun_path;
|
||||||
sun_name_t *peer_sun_path;
|
sun_name_t *peer_sun_path;
|
||||||
struct ucred peer_cred;
|
struct ucred peer_cred;
|
||||||
|
|
||||||
|
void bind_lock () { shmem->bind_lock (); }
|
||||||
|
void bind_unlock () { shmem->bind_unlock (); }
|
||||||
|
void conn_lock () { shmem->conn_lock (); }
|
||||||
|
void conn_unlock () { shmem->conn_unlock (); }
|
||||||
|
void io_lock () { shmem->io_lock (); }
|
||||||
|
void io_unlock () { shmem->io_unlock (); }
|
||||||
|
conn_state connect_state (conn_state val)
|
||||||
|
{ return shmem->connect_state (val); }
|
||||||
|
conn_state connect_state () const { return shmem->connect_state (); }
|
||||||
|
bind_state binding_state (bind_state val)
|
||||||
|
{ return shmem->binding_state (val); }
|
||||||
|
bind_state binding_state () const { return shmem->binding_state (); }
|
||||||
|
int saw_shutdown (int shut) { return shmem->shutdown (shut); }
|
||||||
|
int saw_shutdown () const { return shmem->shutdown (); }
|
||||||
|
int so_error (int err) { return shmem->so_error (err); }
|
||||||
|
int so_error () const { return shmem->so_error (); }
|
||||||
|
int reuseaddr (int err) { return shmem->reuseaddr (err); }
|
||||||
|
int reuseaddr () const { return shmem->reuseaddr (); }
|
||||||
|
|
||||||
|
int create_shmem ();
|
||||||
|
int reopen_shmem ();
|
||||||
void gen_pipe_name ();
|
void gen_pipe_name ();
|
||||||
static HANDLE create_abstract_link (const sun_name_t *sun,
|
static HANDLE create_abstract_link (const sun_name_t *sun,
|
||||||
PUNICODE_STRING pipe_name);
|
PUNICODE_STRING pipe_name);
|
||||||
|
@ -31,8 +31,7 @@ fhandler_socket::fhandler_socket () :
|
|||||||
gid (myself->gid),
|
gid (myself->gid),
|
||||||
mode (S_IFSOCK | S_IRWXU | S_IRWXG | S_IRWXO),
|
mode (S_IFSOCK | S_IRWXU | S_IRWXG | S_IRWXO),
|
||||||
_rcvtimeo (INFINITE),
|
_rcvtimeo (INFINITE),
|
||||||
_sndtimeo (INFINITE),
|
_sndtimeo (INFINITE)
|
||||||
status ()
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,6 +201,7 @@ fhandler_socket_wsock::fhandler_socket_wsock () :
|
|||||||
wsock_events (NULL),
|
wsock_events (NULL),
|
||||||
wsock_mtx (NULL),
|
wsock_mtx (NULL),
|
||||||
wsock_evt (NULL),
|
wsock_evt (NULL),
|
||||||
|
status (),
|
||||||
prot_info_ptr (NULL)
|
prot_info_ptr (NULL)
|
||||||
{
|
{
|
||||||
need_fork_fixup (true);
|
need_fork_fixup (true);
|
||||||
|
@ -189,6 +189,60 @@ create_event ()
|
|||||||
return evt;
|
return evt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Called from socket, socketpair, accept4 */
|
||||||
|
int
|
||||||
|
fhandler_socket_unix::create_shmem ()
|
||||||
|
{
|
||||||
|
HANDLE sect;
|
||||||
|
OBJECT_ATTRIBUTES attr;
|
||||||
|
NTSTATUS status;
|
||||||
|
LARGE_INTEGER size = { .QuadPart = sizeof (af_unix_shmem_t) };
|
||||||
|
SIZE_T viewsize = sizeof (af_unix_shmem_t);
|
||||||
|
PVOID addr = NULL;
|
||||||
|
|
||||||
|
InitializeObjectAttributes (&attr, NULL, OBJ_INHERIT, NULL, NULL);
|
||||||
|
status = NtCreateSection (§, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY
|
||||||
|
| SECTION_MAP_READ | SECTION_MAP_WRITE,
|
||||||
|
&attr, &size, PAGE_READWRITE, SEC_COMMIT, NULL);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
{
|
||||||
|
__seterrno_from_nt_status (status);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
status = NtMapViewOfSection (sect, NtCurrentProcess (), &addr, 0, viewsize,
|
||||||
|
NULL, &viewsize, ViewShare, 0, PAGE_READWRITE);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
{
|
||||||
|
NtClose (sect);
|
||||||
|
__seterrno_from_nt_status (status);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
shmem_handle = sect;
|
||||||
|
shmem = (af_unix_shmem_t *) addr;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Called from dup, fixup_after_fork. Expects shmem_handle to be
|
||||||
|
valid. */
|
||||||
|
int
|
||||||
|
fhandler_socket_unix::reopen_shmem ()
|
||||||
|
{
|
||||||
|
NTSTATUS status;
|
||||||
|
SIZE_T viewsize = PAGESIZE;
|
||||||
|
PVOID addr = NULL;
|
||||||
|
|
||||||
|
status = NtMapViewOfSection (shmem_handle, NtCurrentProcess (), &addr, 0,
|
||||||
|
PAGESIZE, NULL, &viewsize, ViewShare, 0,
|
||||||
|
PAGE_READWRITE);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
{
|
||||||
|
__seterrno_from_nt_status (status);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
shmem = (af_unix_shmem_t *) addr;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Character length of pipe name, excluding trailing NUL. */
|
/* Character length of pipe name, excluding trailing NUL. */
|
||||||
#define CYGWIN_PIPE_SOCKET_NAME_LEN 47
|
#define CYGWIN_PIPE_SOCKET_NAME_LEN 47
|
||||||
|
|
||||||
@ -573,23 +627,23 @@ fhandler_socket_unix::send_my_name ()
|
|||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
IO_STATUS_BLOCK io;
|
IO_STATUS_BLOCK io;
|
||||||
|
|
||||||
AcquireSRWLockShared (&bind_lock);
|
bind_lock ();
|
||||||
sun = get_sun_path ();
|
sun = get_sun_path ();
|
||||||
name_len = sun ? sun->un_len : 0;
|
name_len = sun ? sun->un_len : 0;
|
||||||
packet = (af_unix_pkt_hdr_t *) alloca (sizeof *packet + name_len);
|
packet = (af_unix_pkt_hdr_t *) alloca (sizeof *packet + name_len);
|
||||||
if (sun)
|
if (sun)
|
||||||
memcpy (AF_UNIX_PKT_NAME (packet), &sun->un, name_len);
|
memcpy (AF_UNIX_PKT_NAME (packet), &sun->un, name_len);
|
||||||
ReleaseSRWLockShared (&bind_lock);
|
bind_unlock ();
|
||||||
|
|
||||||
packet->init (0, name_len, 0, 0);
|
packet->init (0, name_len, 0, 0);
|
||||||
|
|
||||||
/* The theory: Fire and forget. */
|
/* The theory: Fire and forget. */
|
||||||
AcquireSRWLockExclusive (&io_lock);
|
io_lock ();
|
||||||
set_pipe_non_blocking (true);
|
set_pipe_non_blocking (true);
|
||||||
status = NtWriteFile (get_handle (), NULL, NULL, NULL, &io, packet,
|
status = NtWriteFile (get_handle (), NULL, NULL, NULL, &io, packet,
|
||||||
packet->pckt_len, NULL, NULL);
|
packet->pckt_len, NULL, NULL);
|
||||||
set_pipe_non_blocking (is_nonblocking ());
|
set_pipe_non_blocking (is_nonblocking ());
|
||||||
ReleaseSRWLockExclusive (&io_lock);
|
io_unlock ();
|
||||||
if (!NT_SUCCESS (status))
|
if (!NT_SUCCESS (status))
|
||||||
{
|
{
|
||||||
debug_printf ("Couldn't send my name: NtWriteFile: %y", status);
|
debug_printf ("Couldn't send my name: NtWriteFile: %y", status);
|
||||||
@ -867,7 +921,7 @@ fhandler_socket_unix::wait_pipe (PUNICODE_STRING pipe_name)
|
|||||||
set_errno (EINTR);
|
set_errno (EINTR);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
InterlockedExchange (&so_error, err);
|
so_error (err);
|
||||||
if (err)
|
if (err)
|
||||||
set_errno (err);
|
set_errno (err);
|
||||||
else
|
else
|
||||||
@ -894,10 +948,10 @@ fhandler_socket_unix::connect_pipe (PUNICODE_STRING pipe_name)
|
|||||||
if (!NT_SUCCESS (status))
|
if (!NT_SUCCESS (status))
|
||||||
{
|
{
|
||||||
__seterrno_from_nt_status (status);
|
__seterrno_from_nt_status (status);
|
||||||
InterlockedExchange (&so_error, get_errno ());
|
so_error (get_errno ());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
InterlockedExchange (&so_error, 0);
|
so_error (0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -991,9 +1045,11 @@ fhandler_socket_unix::fixup_after_fork (HANDLE parent)
|
|||||||
fhandler_socket::fixup_after_fork (parent);
|
fhandler_socket::fixup_after_fork (parent);
|
||||||
if (backing_file_handle && backing_file_handle != INVALID_HANDLE_VALUE)
|
if (backing_file_handle && backing_file_handle != INVALID_HANDLE_VALUE)
|
||||||
fork_fixup (parent, backing_file_handle, "backing_file_handle");
|
fork_fixup (parent, backing_file_handle, "backing_file_handle");
|
||||||
InitializeSRWLock (&conn_lock);
|
if (shmem_handle)
|
||||||
InitializeSRWLock (&bind_lock);
|
{
|
||||||
InitializeSRWLock (&io_lock);
|
fork_fixup (parent, shmem_handle, "shmem_handle");
|
||||||
|
reopen_shmem ();
|
||||||
|
}
|
||||||
connect_wait_thr = NULL;
|
connect_wait_thr = NULL;
|
||||||
cwt_termination_evt = NULL;
|
cwt_termination_evt = NULL;
|
||||||
cwt_param = NULL;
|
cwt_param = NULL;
|
||||||
@ -1012,6 +1068,8 @@ fhandler_socket_unix::set_close_on_exec (bool val)
|
|||||||
fhandler_base::set_close_on_exec (val);
|
fhandler_base::set_close_on_exec (val);
|
||||||
if (backing_file_handle && backing_file_handle != INVALID_HANDLE_VALUE)
|
if (backing_file_handle && backing_file_handle != INVALID_HANDLE_VALUE)
|
||||||
set_no_inheritance (backing_file_handle, val);
|
set_no_inheritance (backing_file_handle, val);
|
||||||
|
if (shmem_handle)
|
||||||
|
set_no_inheritance (shmem_handle, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
fhandler_socket_unix::fhandler_socket_unix ()
|
fhandler_socket_unix::fhandler_socket_unix ()
|
||||||
@ -1045,11 +1103,22 @@ fhandler_socket_unix::dup (fhandler_base *child, int flags)
|
|||||||
fhs->close ();
|
fhs->close ();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (!DuplicateHandle (GetCurrentProcess (), shmem_handle,
|
||||||
|
GetCurrentProcess (), &fhs->shmem_handle,
|
||||||
|
0, TRUE, DUPLICATE_SAME_ACCESS))
|
||||||
|
{
|
||||||
|
__seterrno ();
|
||||||
|
fhs->close ();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (reopen_shmem () < 0)
|
||||||
|
{
|
||||||
|
__seterrno ();
|
||||||
|
fhs->close ();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
fhs->set_sun_path (get_sun_path ());
|
fhs->set_sun_path (get_sun_path ());
|
||||||
fhs->set_peer_sun_path (get_peer_sun_path ());
|
fhs->set_peer_sun_path (get_peer_sun_path ());
|
||||||
InitializeSRWLock (&fhs->conn_lock);
|
|
||||||
InitializeSRWLock (&fhs->bind_lock);
|
|
||||||
InitializeSRWLock (&fhs->io_lock);
|
|
||||||
fhs->connect_wait_thr = NULL;
|
fhs->connect_wait_thr = NULL;
|
||||||
fhs->cwt_termination_evt = NULL;
|
fhs->cwt_termination_evt = NULL;
|
||||||
fhs->cwt_param = NULL;
|
fhs->cwt_param = NULL;
|
||||||
@ -1155,10 +1224,10 @@ out:
|
|||||||
PVOID param = InterlockedExchangePointer (&cwt_param, NULL);
|
PVOID param = InterlockedExchangePointer (&cwt_param, NULL);
|
||||||
if (param)
|
if (param)
|
||||||
cfree (param);
|
cfree (param);
|
||||||
AcquireSRWLockExclusive (&conn_lock);
|
conn_lock ();
|
||||||
InterlockedExchange (&so_error, error);
|
so_error (error);
|
||||||
connect_state (error ? connect_failed : connected);
|
connect_state (error ? connect_failed : connected);
|
||||||
ReleaseSRWLockExclusive (&conn_lock);
|
conn_unlock ();
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1175,6 +1244,8 @@ fhandler_socket_unix::socket (int af, int type, int protocol, int flags)
|
|||||||
set_errno (EPROTONOSUPPORT);
|
set_errno (EPROTONOSUPPORT);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (create_shmem () < 0)
|
||||||
|
return -1;
|
||||||
rmem (262144);
|
rmem (262144);
|
||||||
wmem (262144);
|
wmem (262144);
|
||||||
set_addr_family (af);
|
set_addr_family (af);
|
||||||
@ -1225,23 +1296,29 @@ fhandler_socket_unix::socketpair (int af, int type, int protocol, int flags,
|
|||||||
if (!pipe)
|
if (!pipe)
|
||||||
return -1;
|
return -1;
|
||||||
set_io_handle (pipe);
|
set_io_handle (pipe);
|
||||||
backing_file_handle = autobind (&sun);
|
set_sun_path (&sun);
|
||||||
if (!backing_file_handle)
|
fh->set_peer_sun_path (&sun);
|
||||||
|
if (create_shmem () < 0)
|
||||||
{
|
{
|
||||||
NtClose (pipe);
|
NtClose (pipe);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
set_sun_path (&sun);
|
|
||||||
fh->set_peer_sun_path (&sun);
|
|
||||||
binding_state (bound);
|
binding_state (bound);
|
||||||
connect_state (listener);
|
connect_state (listener);
|
||||||
/* connect 2nd socket */
|
/* connect 2nd socket */
|
||||||
if (type != SOCK_DGRAM
|
if (type != SOCK_DGRAM
|
||||||
&& fh->open_pipe (pc.get_nt_native_path (), false) < 0)
|
&& fh->open_pipe (pc.get_nt_native_path (), false) < 0)
|
||||||
{
|
{
|
||||||
|
NtClose (shmem_handle);
|
||||||
NtClose (pipe);
|
NtClose (pipe);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (fh->create_shmem () < 0)
|
||||||
|
{
|
||||||
|
NtClose (fh->get_handle ());
|
||||||
|
NtClose (shmem_handle);
|
||||||
|
NtClose (pipe);
|
||||||
|
}
|
||||||
fh->connect_state (connected);
|
fh->connect_state (connected);
|
||||||
if (flags & SOCK_NONBLOCK)
|
if (flags & SOCK_NONBLOCK)
|
||||||
{
|
{
|
||||||
@ -1271,21 +1348,21 @@ fhandler_socket_unix::bind (const struct sockaddr *name, int namelen)
|
|||||||
set_errno (EINVAL);
|
set_errno (EINVAL);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
AcquireSRWLockExclusive (&bind_lock);
|
bind_lock ();
|
||||||
if (binding_state () == bind_pending)
|
if (binding_state () == bind_pending)
|
||||||
{
|
{
|
||||||
set_errno (EALREADY);
|
set_errno (EALREADY);
|
||||||
ReleaseSRWLockExclusive (&bind_lock);
|
bind_unlock ();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (binding_state () == bound)
|
if (binding_state () == bound)
|
||||||
{
|
{
|
||||||
set_errno (EINVAL);
|
set_errno (EINVAL);
|
||||||
ReleaseSRWLockExclusive (&bind_lock);
|
bind_unlock ();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
binding_state (bind_pending);
|
binding_state (bind_pending);
|
||||||
ReleaseSRWLockExclusive (&bind_lock);
|
bind_unlock ();
|
||||||
gen_pipe_name ();
|
gen_pipe_name ();
|
||||||
if (get_socket_type () == SOCK_DGRAM)
|
if (get_socket_type () == SOCK_DGRAM)
|
||||||
{
|
{
|
||||||
@ -1323,21 +1400,21 @@ fhandler_socket_unix::listen (int backlog)
|
|||||||
set_errno (EOPNOTSUPP);
|
set_errno (EOPNOTSUPP);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
AcquireSRWLockShared (&bind_lock);
|
bind_lock ();
|
||||||
while (binding_state () == bind_pending)
|
while (binding_state () == bind_pending)
|
||||||
yield ();
|
yield ();
|
||||||
if (binding_state () == unbound)
|
if (binding_state () == unbound)
|
||||||
{
|
{
|
||||||
set_errno (EDESTADDRREQ);
|
set_errno (EDESTADDRREQ);
|
||||||
ReleaseSRWLockShared (&bind_lock);
|
bind_unlock ();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ReleaseSRWLockShared (&bind_lock);
|
bind_unlock ();
|
||||||
AcquireSRWLockExclusive (&conn_lock);
|
conn_lock ();
|
||||||
if (connect_state () != unconnected && connect_state () != connect_failed)
|
if (connect_state () != unconnected && connect_state () != connect_failed)
|
||||||
{
|
{
|
||||||
set_errno (connect_state () == listener ? EADDRINUSE : EINVAL);
|
set_errno (connect_state () == listener ? EADDRINUSE : EINVAL);
|
||||||
ReleaseSRWLockExclusive (&conn_lock);
|
conn_unlock ();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
HANDLE pipe = create_pipe (false);
|
HANDLE pipe = create_pipe (false);
|
||||||
@ -1348,7 +1425,7 @@ fhandler_socket_unix::listen (int backlog)
|
|||||||
}
|
}
|
||||||
set_io_handle (pipe);
|
set_io_handle (pipe);
|
||||||
connect_state (listener);
|
connect_state (listener);
|
||||||
ReleaseSRWLockExclusive (&conn_lock);
|
conn_unlock ();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1371,17 +1448,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);
|
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);
|
io_unlock ();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Set new io handle. */
|
/* Set new io handle. */
|
||||||
set_io_handle (new_inst);
|
set_io_handle (new_inst);
|
||||||
ReleaseSRWLockExclusive (&io_lock);
|
io_unlock ();
|
||||||
/* Prepare new file descriptor. */
|
/* Prepare new file descriptor. */
|
||||||
cygheap_fdnew fd;
|
cygheap_fdnew fd;
|
||||||
|
|
||||||
@ -1391,6 +1468,9 @@ fhandler_socket_unix::accept4 (struct sockaddr *peer, int *len, int flags)
|
|||||||
build_fh_dev (dev ());
|
build_fh_dev (dev ());
|
||||||
if (sock)
|
if (sock)
|
||||||
{
|
{
|
||||||
|
if (sock->create_shmem () < 0)
|
||||||
|
goto create_shmem_failed;
|
||||||
|
|
||||||
sock->set_addr_family (get_addr_family ());
|
sock->set_addr_family (get_addr_family ());
|
||||||
sock->set_socket_type (get_socket_type ());
|
sock->set_socket_type (get_socket_type ());
|
||||||
if (flags & SOCK_NONBLOCK)
|
if (flags & SOCK_NONBLOCK)
|
||||||
@ -1433,6 +1513,7 @@ fhandler_socket_unix::accept4 (struct sockaddr *peer, int *len, int flags)
|
|||||||
}
|
}
|
||||||
__endtry
|
__endtry
|
||||||
}
|
}
|
||||||
|
create_shmem_failed:
|
||||||
delete sock;
|
delete sock;
|
||||||
}
|
}
|
||||||
fd.release ();
|
fd.release ();
|
||||||
@ -1455,27 +1536,27 @@ fhandler_socket_unix::connect (const struct sockaddr *name, int namelen)
|
|||||||
UNICODE_STRING pipe_name;
|
UNICODE_STRING pipe_name;
|
||||||
|
|
||||||
/* Test and set connection state. */
|
/* Test and set connection state. */
|
||||||
AcquireSRWLockExclusive (&conn_lock);
|
conn_lock ();
|
||||||
if (connect_state () == connect_pending)
|
if (connect_state () == connect_pending)
|
||||||
{
|
{
|
||||||
set_errno (EALREADY);
|
set_errno (EALREADY);
|
||||||
ReleaseSRWLockExclusive (&conn_lock);
|
conn_unlock ();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (connect_state () == listener)
|
if (connect_state () == listener)
|
||||||
{
|
{
|
||||||
set_errno (EADDRINUSE);
|
set_errno (EADDRINUSE);
|
||||||
ReleaseSRWLockExclusive (&conn_lock);
|
conn_unlock ();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (connect_state () == connected && get_socket_type () != SOCK_DGRAM)
|
if (connect_state () == connected && get_socket_type () != SOCK_DGRAM)
|
||||||
{
|
{
|
||||||
set_errno (EISCONN);
|
set_errno (EISCONN);
|
||||||
ReleaseSRWLockExclusive (&conn_lock);
|
conn_unlock ();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
connect_state (connect_pending);
|
connect_state (connect_pending);
|
||||||
ReleaseSRWLockExclusive (&conn_lock);
|
conn_unlock ();
|
||||||
/* Check validity of name */
|
/* Check validity of name */
|
||||||
if (sun.un_len <= (int) sizeof (sa_family_t))
|
if (sun.un_len <= (int) sizeof (sa_family_t))
|
||||||
{
|
{
|
||||||
@ -1577,6 +1658,12 @@ fhandler_socket_unix::close ()
|
|||||||
PVOID param = InterlockedExchangePointer (&cwt_param, NULL);
|
PVOID param = InterlockedExchangePointer (&cwt_param, NULL);
|
||||||
if (param)
|
if (param)
|
||||||
cfree (param);
|
cfree (param);
|
||||||
|
HANDLE shm = InterlockedExchangePointer (&shmem_handle, NULL);
|
||||||
|
if (shm)
|
||||||
|
NtClose (shm);
|
||||||
|
param = InterlockedExchangePointer ((PVOID *) &shmem, NULL);
|
||||||
|
if (param)
|
||||||
|
NtUnmapViewOfSection (GetCurrentProcess (), param);
|
||||||
if (get_handle ())
|
if (get_handle ())
|
||||||
NtClose (get_handle ());
|
NtClose (get_handle ());
|
||||||
if (backing_file_handle && backing_file_handle != INVALID_HANDLE_VALUE)
|
if (backing_file_handle && backing_file_handle != INVALID_HANDLE_VALUE)
|
||||||
@ -1594,7 +1681,7 @@ fhandler_socket_unix::getpeereid (pid_t *pid, uid_t *euid, gid_t *egid)
|
|||||||
set_errno (EINVAL);
|
set_errno (EINVAL);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
AcquireSRWLockShared (&conn_lock);
|
conn_lock ();
|
||||||
if (connect_state () != connected)
|
if (connect_state () != connected)
|
||||||
set_errno (ENOTCONN);
|
set_errno (ENOTCONN);
|
||||||
else
|
else
|
||||||
@ -1612,7 +1699,7 @@ fhandler_socket_unix::getpeereid (pid_t *pid, uid_t *euid, gid_t *egid)
|
|||||||
__except (EFAULT) {}
|
__except (EFAULT) {}
|
||||||
__endtry
|
__endtry
|
||||||
}
|
}
|
||||||
ReleaseSRWLockShared (&conn_lock);
|
conn_unlock ();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1756,7 +1843,7 @@ fhandler_socket_unix::setsockopt (int level, int optname, const void *optval,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SO_REUSEADDR:
|
case SO_REUSEADDR:
|
||||||
saw_reuseaddr (*(int *) optval);
|
reuseaddr (*(int *) optval);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SO_RCVBUF:
|
case SO_RCVBUF:
|
||||||
@ -1812,7 +1899,7 @@ fhandler_socket_unix::getsockopt (int level, int optname, const void *optval,
|
|||||||
int *e = (int *) optval;
|
int *e = (int *) optval;
|
||||||
LONG err;
|
LONG err;
|
||||||
|
|
||||||
err = InterlockedExchange (&so_error, 0);
|
err = so_error (0);
|
||||||
*e = err;
|
*e = err;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1837,15 +1924,15 @@ fhandler_socket_unix::getsockopt (int level, int optname, const void *optval,
|
|||||||
|
|
||||||
case SO_REUSEADDR:
|
case SO_REUSEADDR:
|
||||||
{
|
{
|
||||||
unsigned int *reuseaddr = (unsigned int *) optval;
|
unsigned int *reuse = (unsigned int *) optval;
|
||||||
|
|
||||||
if (*optlen < (socklen_t) sizeof *reuseaddr)
|
if (*optlen < (socklen_t) sizeof *reuse)
|
||||||
{
|
{
|
||||||
set_errno (EINVAL);
|
set_errno (EINVAL);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
*reuseaddr = saw_reuseaddr();
|
*reuse = reuseaddr ();
|
||||||
*optlen = (socklen_t) sizeof *reuseaddr;
|
*optlen = (socklen_t) sizeof *reuse;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user