diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2015-09-11 02:05:06 +0200 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2015-09-11 02:05:06 +0200 |
commit | df2b1fb2caed423b22f6d59d22f087100dd1b7d8 (patch) | |
tree | 627d005a833c176ca8fa8d40f500d554da59dee9 /pflocal/sock.h | |
parent | 280e26f17906c2c2fb39c33bee797e90f5cf0c40 (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/sock.h')
-rw-r--r-- | pflocal/sock.h | 25 |
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); } |