Cygwin: AF_UNIX: keep a reference count of open descriptors

Add a data member _ndesc to the af_unix_shmem_t class, along with
methods to increment and decrement it.

Increment it during socket/fork/exec/dup, and decrement it during
close.  When the last descriptor is closed, call shutdown (SHUT_RDWR)
and unlink the socket's message queue.

The shutdown call will make the socket's peer see EPIPE if it tries to
write.
This commit is contained in:
Ken Brown 2021-05-17 17:18:45 -04:00
parent 6172419ed2
commit 7720ea9679
2 changed files with 14 additions and 4 deletions

View File

@ -956,6 +956,7 @@ class af_unix_shmem_t
LONG _so_passcred; /* SO_PASSCRED */
LONG _reuseaddr; /* dummy */
int _type; /* socket type */
LONG _ndesc; /* number of open descriptors */
sun_name_t _sun_path;
sun_name_t _peer_sun_path;
struct ucred _sock_cred; /* filled at listen time */
@ -997,6 +998,9 @@ class af_unix_shmem_t
void set_socket_type (int val) { _type = val; }
int get_socket_type () const { return _type; }
LONG inc_ndesc () { return InterlockedIncrement (&_ndesc); }
LONG dec_ndesc () { return InterlockedDecrement (&_ndesc); }
void sun_path (struct sockaddr_un *un, __socklen_t unlen)
{ _sun_path.set (un, unlen); }
void peer_sun_path (struct sockaddr_un *un, __socklen_t unlen)
@ -1076,6 +1080,8 @@ class fhandler_socket_unix : public fhandler_socket
int reuseaddr () const { return shmem->reuseaddr (); }
void set_socket_type (int val) { shmem->set_socket_type (val); }
int get_socket_type () const { return shmem->get_socket_type (); }
LONG inc_ndesc () { return shmem->inc_ndesc (); }
LONG dec_ndesc () { return shmem->dec_ndesc (); }
int create_shmem ();
int reopen_shmem ();

View File

@ -1122,6 +1122,7 @@ fhandler_socket_unix::fixup_helper ()
connect_wait_thr = NULL;
cwt_termination_evt = NULL;
cwt_param = NULL;
inc_ndesc ();
}
/* ========================== public methods ========================= */
@ -1209,6 +1210,7 @@ fhandler_socket_unix::dup (fhandler_base *child, int flags)
fhs->connect_wait_thr = NULL;
fhs->cwt_termination_evt = NULL;
fhs->cwt_param = NULL;
inc_ndesc ();
return 0;
}
@ -1285,6 +1287,7 @@ fhandler_socket_unix::socket (int af, int type, int protocol, int flags)
set_handle (NULL);
set_unique_id ();
set_ino (get_unique_id ());
inc_ndesc ();
return 0;
}
@ -1753,10 +1756,11 @@ fhandler_socket_unix::close ()
ret = mq_close (get_mqd_in ());
if (get_mqd_out () != (mqd_t) -1)
ret |= mq_close (get_mqd_out ());
/* FIXME: Maybe we should keep a reference count on the mqueues and
unlink it after the last one is close. OTOH, this will become
unnecessary if the mqueue implementation is changed to use
Windows shared memory. */
if (dec_ndesc () <= 0)
{
shutdown (SHUT_RDWR);
mq_unlink (get_mqueue_name ());
}
return ret;
}