MEDIUM: listeners: make unbind_listener() converge if needed

The ZOMBIE state on listener is a real mess. Listeners passing through
this state have lost their consistency with the proxy AND with the fdtab.
Plus this state is not used for all foreign listeners, only for those
belonging to a proxy that entirely runs on another process, otherwise it
stays in INIT state, which makes the usefulness extremely questionable.
But the real issue is that it's impossible to untangle the receivers
from the proxy state as long as we have this because of deinit()...

So what we do here is to start by making unbind_listener() support being
called more than once. This will permit to call it again to really close
the FD and finish the operations if it's called with an FD that's in a
fake state (such as INIT but with a valid fd).
diff --git a/src/listener.c b/src/listener.c
index 4b21f67..8f54ae2 100644
--- a/src/listener.c
+++ b/src/listener.c
@@ -478,7 +478,8 @@
 }
 
 /* Must be called with the lock held. Depending on <do_close> value, it does
- * what unbind_listener or unbind_listener_no_close should do.
+ * what unbind_listener or unbind_listener_no_close should do. It can also
+ * close a zombie listener's FD when called in early states.
  */
 void do_unbind_listener(struct listener *listener, int do_close)
 {
@@ -490,11 +491,12 @@
 	if (listener->state >= LI_PAUSED) {
 		listener->state = LI_ASSIGNED;
 		fd_stop_both(listener->rx.fd);
-		if (do_close) {
-			fd_delete(listener->rx.fd);
-			listener->rx.flags &= ~RX_F_BOUND;
-			listener->rx.fd = -1;
-		}
+	}
+
+	if (do_close && listener->rx.fd != -1) {
+		fd_delete(listener->rx.fd);
+		listener->rx.flags &= ~RX_F_BOUND;
+		listener->rx.fd = -1;
 	}
 }