diff --git a/include/haproxy/protocol.h b/include/haproxy/protocol.h index ac331c78d..a752f98d9 100644 --- a/include/haproxy/protocol.h +++ b/include/haproxy/protocol.h @@ -50,6 +50,20 @@ int protocol_bind_all(int verbose); */ int protocol_unbind_all(void); +/* pauses all listeners of all registered protocols. This is typically + * used on SIG_TTOU to release all listening sockets for the time needed to + * try to bind a new process. The listeners enter LI_PAUSED. It returns + * ERR_NONE, with ERR_FATAL on failure. + */ +int protocol_pause_all(void); + +/* resumes all listeners of all registered protocols. This is typically used on + * SIG_TTIN to re-enable listening sockets after a new process failed to bind. + * The listeners switch to LI_READY/LI_FULL. It returns ERR_NONE, with ERR_FATAL + * on failure. + */ +int protocol_resume_all(void); + /* enables all listeners of all registered protocols. This is intended to be * used after a fork() to enable reading on all file descriptors. Returns a * composition of ERR_NONE, ERR_RETRYABLE, ERR_FATAL. diff --git a/src/protocol.c b/src/protocol.c index 48bce766b..54b708332 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -151,6 +151,50 @@ int protocol_unbind_all(void) return err; } +/* pauses all listeners of all registered protocols. This is typically + * used on SIG_TTOU to release all listening sockets for the time needed to + * try to bind a new process. The listeners enter LI_PAUSED. It returns + * ERR_NONE, with ERR_FATAL on failure. + */ +int protocol_pause_all(void) +{ + struct protocol *proto; + struct listener *listener; + int err; + + err = 0; + HA_SPIN_LOCK(PROTO_LOCK, &proto_lock); + list_for_each_entry(proto, &protocols, list) { + list_for_each_entry(listener, &proto->listeners, rx.proto_list) + if (!pause_listener(listener)) + err |= ERR_FATAL; + } + HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock); + return err; +} + +/* resumes all listeners of all registered protocols. This is typically used on + * SIG_TTIN to re-enable listening sockets after a new process failed to bind. + * The listeners switch to LI_READY/LI_FULL. It returns ERR_NONE, with ERR_FATAL + * on failure. + */ +int protocol_resume_all(void) +{ + struct protocol *proto; + struct listener *listener; + int err; + + err = 0; + HA_SPIN_LOCK(PROTO_LOCK, &proto_lock); + list_for_each_entry(proto, &protocols, list) { + list_for_each_entry(listener, &proto->listeners, rx.proto_list) + if (!resume_listener(listener)) + err |= ERR_FATAL; + } + HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock); + return err; +} + /* enables all listeners of all registered protocols. This is intended to be * used after a fork() to enable reading on all file descriptors. Returns a * composition of ERR_NONE, ERR_RETRYABLE, ERR_FATAL.