BUG/MEDIUM: threads/unix: Fix a deadlock when a listener is temporarily disabled
When a listener is temporarily disabled, we start by locking it and then we call
.pause callback of the underlying protocol (tcp/unix). For TCP listeners, this
is not a problem. But listeners bound on an unix socket are in fact closed
instead. So .pause callback relies on unbind_listener function to do its job.
Unfortunatly, unbind_listener hold the listener's lock and then call an internal
function to unbind it. So, there is a deadlock here. This happens during a
reload. To fix the problemn, the function do_unbind_listener, which is lockless,
is now exported and is called when a listener bound on an unix socket is
temporarily disabled.
This patch must be backported in 1.8.
diff --git a/src/proto_uxst.c b/src/proto_uxst.c
index 0f71738..9fc50df 100644
--- a/src/proto_uxst.c
+++ b/src/proto_uxst.c
@@ -393,7 +393,9 @@
if (((struct sockaddr_un *)&l->addr)->sun_path[0])
return 1;
- unbind_listener(l);
+ /* Listener's lock already held. Call lockless version of
+ * unbind_listener. */
+ do_unbind_listener(l, 1);
return 0;
}