diff --git a/include/haproxy/sock-t.h b/include/haproxy/sock-t.h index 1a49dfa44..b843d444a 100644 --- a/include/haproxy/sock-t.h +++ b/include/haproxy/sock-t.h @@ -27,23 +27,6 @@ #include -#define SOCK_XFER_OPT_FOREIGN 0x000000001 -#define SOCK_XFER_OPT_V6ONLY 0x000000002 -#define SOCK_XFER_OPT_DGRAM 0x000000004 - -/* The list used to transfer sockets between old and new processes */ -struct xfer_sock_list { - int fd; - int options; /* socket options as SOCK_XFER_OPT_* */ - char *iface; - char *namespace; - int if_namelen; - int ns_namelen; - struct xfer_sock_list *prev; - struct xfer_sock_list *next; - struct sockaddr_storage addr; -}; - #endif /* _HAPROXY_SOCK_T_H */ /* diff --git a/include/haproxy/sock.h b/include/haproxy/sock.h index 1a5b68c5a..49dffa918 100644 --- a/include/haproxy/sock.h +++ b/include/haproxy/sock.h @@ -30,8 +30,6 @@ #include #include -extern struct xfer_sock_list *xfer_sock_list; - int sock_create_server_socket(struct connection *conn); void sock_enable(struct receiver *rx); void sock_disable(struct receiver *rx); @@ -40,6 +38,7 @@ int sock_get_src(int fd, struct sockaddr *sa, socklen_t salen, int dir); int sock_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir); int sock_get_old_sockets(const char *unixsocket); int sock_find_compatible_fd(const struct receiver *rx); +void sock_drop_unused_old_sockets(); int sock_accepting_conn(const struct receiver *rx); struct connection *sock_accept_conn(struct listener *l, int *status); void sock_accept_iocb(int fd); diff --git a/src/haproxy.c b/src/haproxy.c index 67ce74ea1..029b492be 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -3054,14 +3054,7 @@ int main(int argc, char **argv) /* Ok, all listeners should now be bound, close any leftover sockets * the previous process gave us, we don't need them anymore */ - while (xfer_sock_list != NULL) { - struct xfer_sock_list *tmpxfer = xfer_sock_list->next; - close(xfer_sock_list->fd); - free(xfer_sock_list->iface); - free(xfer_sock_list->namespace); - free(xfer_sock_list); - xfer_sock_list = tmpxfer; - } + sock_drop_unused_old_sockets(); /* prepare pause/play signals */ signal_register_fct(SIGTTOU, sig_pause, SIGTTOU); diff --git a/src/sock.c b/src/sock.c index 4d1d04e95..f6ab83f55 100644 --- a/src/sock.c +++ b/src/sock.c @@ -36,8 +36,24 @@ #include #include +#define SOCK_XFER_OPT_FOREIGN 0x000000001 +#define SOCK_XFER_OPT_V6ONLY 0x000000002 +#define SOCK_XFER_OPT_DGRAM 0x000000004 + /* the list of remaining sockets transferred from an older process */ -struct xfer_sock_list *xfer_sock_list = NULL; +struct xfer_sock_list { + int fd; + int options; /* socket options as SOCK_XFER_OPT_* */ + char *iface; + char *namespace; + int if_namelen; + int ns_namelen; + struct xfer_sock_list *prev; + struct xfer_sock_list *next; + struct sockaddr_storage addr; +}; + +static struct xfer_sock_list *xfer_sock_list; /* Accept an incoming connection from listener , and return it, as well as @@ -622,6 +638,24 @@ int sock_find_compatible_fd(const struct receiver *rx) return ret; } +/* After all protocols are bound, there may remain some old sockets that have + * been removed between the previous config and the new one. These ones must + * be dropped, otherwise they will remain open and may prevent a service from + * restarting. + */ +void sock_drop_unused_old_sockets() +{ + while (xfer_sock_list != NULL) { + struct xfer_sock_list *tmpxfer = xfer_sock_list->next; + + close(xfer_sock_list->fd); + free(xfer_sock_list->iface); + free(xfer_sock_list->namespace); + free(xfer_sock_list); + xfer_sock_list = tmpxfer; + } +} + /* Tests if the receiver supports accepting connections. Returns positive on * success, 0 if not possible, negative if the socket is non-recoverable. The * rationale behind this is that inherited FDs may be broken and that shared