summaryrefslogtreecommitdiff
path: root/pflocal
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2015-09-11 02:05:06 +0200
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2015-09-11 02:05:06 +0200
commitdf2b1fb2caed423b22f6d59d22f087100dd1b7d8 (patch)
tree627d005a833c176ca8fa8d40f500d554da59dee9 /pflocal
parent280e26f17906c2c2fb39c33bee797e90f5cf0c40 (diff)
Fix closure of local server sockets
Since bound socks always have a ref for their address, they would never get freed. Thanks Svante Signell for the investigation. * pflocal/sock.h (sock_deref): When `sock' has one ref left and is bound to an address, unbound it, and thus shut it down.
Diffstat (limited to 'pflocal')
-rw-r--r--pflocal/sock.h25
1 files changed, 24 insertions, 1 deletions
diff --git a/pflocal/sock.h b/pflocal/sock.h
index 5800420c..f827c6f2 100644
--- a/pflocal/sock.h
+++ b/pflocal/sock.h
@@ -118,9 +118,32 @@ void _sock_norefs (struct sock *sock);
static inline void __attribute__ ((unused))
sock_deref (struct sock *sock)
{
+ error_t err;
pthread_mutex_lock (&sock->lock);
- if (--sock->refs == 0)
+
+ sock->refs--;
+
+ if (sock->refs == 0)
_sock_norefs (sock);
+ else if (sock->refs == 1 && sock->addr)
+ {
+ /* Last ref is the address, there won't be any more port for this socket,
+ unbind SOCK from its addr, and they will all die. */
+
+ /* Keep another ref while unbinding. */
+ sock->refs++;
+ pthread_mutex_unlock (&sock->lock);
+
+ /* Unbind */
+ err = sock_bind (sock, NULL);
+ assert (!err);
+
+ /* And release the ref, and thus kill SOCK. */
+ pthread_mutex_lock (&sock->lock);
+ sock->refs--;
+ assert(sock->refs == 0);
+ _sock_norefs (sock);
+ }
else
pthread_mutex_unlock (&sock->lock);
}