From 7720ea9679e9c0952edee5aaa3bd4d77e4cbbd33 Mon Sep 17 00:00:00 2001 From: Ken Brown Date: Mon, 17 May 2021 17:18:45 -0400 Subject: [PATCH] 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. --- winsup/cygwin/fhandler.h | 6 ++++++ winsup/cygwin/fhandler_socket_unix.cc | 12 ++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index e608551b3..45d622deb 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -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 (); diff --git a/winsup/cygwin/fhandler_socket_unix.cc b/winsup/cygwin/fhandler_socket_unix.cc index 109cad4ba..6071061af 100644 --- a/winsup/cygwin/fhandler_socket_unix.cc +++ b/winsup/cygwin/fhandler_socket_unix.cc @@ -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; }