mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-04-27 05:18:00 +00:00
BUG/MEDIUM: mworker: does not close inherited FD
At the end of the master initialisation, a call to protocol_unbind_all() was made, in order to close all the FDs. Unfortunately, this function closes the inherited FDs (fd@), upon reload the master wasn't able to reload a configuration with those FDs. The create_listeners() function now store a flag to specify if the fd was inherited or not. Replace the protocol_unbind_all() by mworker_cleanlisteners() + deinit_pollers()
This commit is contained in:
parent
fade49d8fb
commit
75ea0a06b0
@ -83,11 +83,13 @@ int unbind_all_listeners(struct protocol *proto);
|
||||
* range <portl> to <porth>, and possibly attached to fd <fd> (or -1 for auto
|
||||
* allocation). The address family is taken from ss->ss_family. The number of
|
||||
* jobs and listeners is automatically increased by the number of listeners
|
||||
* created. It returns non-zero on success, zero on error with the error message
|
||||
* created. If the <inherited> argument is set to 1, it specifies that the FD
|
||||
* was obtained from a parent process.
|
||||
* It returns non-zero on success, zero on error with the error message
|
||||
* set in <err>.
|
||||
*/
|
||||
int create_listeners(struct bind_conf *bc, const struct sockaddr_storage *ss,
|
||||
int portl, int porth, int fd, char **err);
|
||||
int portl, int porth, int fd, int inherited, char **err);
|
||||
|
||||
/* Delete a listener from its protocol's list of listeners. The listener's
|
||||
* state is automatically updated from LI_ASSIGNED to LI_INIT. The protocol's
|
||||
|
@ -98,6 +98,7 @@ enum li_state {
|
||||
#define LI_O_V6ONLY 0x0400 /* bind to IPv6 only on Linux >= 2.4.21 */
|
||||
#define LI_O_V4V6 0x0800 /* bind to IPv4/IPv6 on Linux >= 2.4.21 */
|
||||
#define LI_O_ACC_CIP 0x1000 /* find the proxied address in the NetScaler Client IP header */
|
||||
#define LI_O_INHERITED 0x2000 /* inherited FD from the parent process (fd@) */
|
||||
|
||||
/* Note: if a listener uses LI_O_UNLIMITED, it is highly recommended that it adds its own
|
||||
* maxconn setting to the global.maxsock value so that its resources are reserved.
|
||||
|
@ -239,6 +239,7 @@ int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf,
|
||||
next = dupstr = strdup(str);
|
||||
|
||||
while (next && *next) {
|
||||
int inherited = 0;
|
||||
struct sockaddr_storage *ss2;
|
||||
int fd = -1;
|
||||
|
||||
@ -277,6 +278,7 @@ int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf,
|
||||
}
|
||||
else if (ss2->ss_family == AF_UNSPEC) {
|
||||
socklen_t addr_len;
|
||||
inherited = 1;
|
||||
|
||||
/* We want to attach to an already bound fd whose number
|
||||
* is in the addr part of ss2 when cast to sockaddr_in.
|
||||
@ -295,7 +297,7 @@ int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf,
|
||||
}
|
||||
|
||||
/* OK the address looks correct */
|
||||
if (!create_listeners(bind_conf, ss2, port, end, fd, err)) {
|
||||
if (!create_listeners(bind_conf, ss2, port, end, fd, inherited, err)) {
|
||||
memprintf(err, "%s for address '%s'.\n", *err, str);
|
||||
goto fail;
|
||||
}
|
||||
|
@ -540,6 +540,33 @@ static void mworker_kill(int sig)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Upon a reload, the master worker needs to close all listeners FDs but the mworker_pipe
|
||||
* fd, and the FD provided by fd@
|
||||
*/
|
||||
static void mworker_cleanlisteners()
|
||||
{
|
||||
struct listener *l, *l_next;
|
||||
struct proxy *curproxy;
|
||||
|
||||
for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
|
||||
|
||||
list_for_each_entry_safe(l, l_next, &curproxy->conf.listeners, by_fe) {
|
||||
/* does not close if the FD is inherited with fd@
|
||||
* from the parent process */
|
||||
if (!(l->options & LI_O_INHERITED)) {
|
||||
close(l->fd);
|
||||
LIST_DEL(&l->by_fe);
|
||||
LIST_DEL(&l->by_bind);
|
||||
free(l->name);
|
||||
free(l->counters);
|
||||
free(l);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* remove a pid forom the olpid array and decrease nb_oldpids
|
||||
* return 1 pid was found otherwise return 0
|
||||
@ -2694,7 +2721,8 @@ int main(int argc, char **argv)
|
||||
|
||||
if (proc == global.nbproc) {
|
||||
if (global.mode & MODE_MWORKER) {
|
||||
protocol_unbind_all();
|
||||
mworker_cleanlisteners();
|
||||
deinit_pollers();
|
||||
mworker_wait();
|
||||
/* should never get there */
|
||||
exit(EXIT_FAILURE);
|
||||
|
@ -372,11 +372,13 @@ int unbind_all_listeners(struct protocol *proto)
|
||||
* range <portl> to <porth>, and possibly attached to fd <fd> (or -1 for auto
|
||||
* allocation). The address family is taken from ss->ss_family. The number of
|
||||
* jobs and listeners is automatically increased by the number of listeners
|
||||
* created. It returns non-zero on success, zero on error with the error message
|
||||
* created. If the <inherited> argument is set to 1, it specifies that the FD
|
||||
* was obtained from a parent process.
|
||||
* It returns non-zero on success, zero on error with the error message
|
||||
* set in <err>.
|
||||
*/
|
||||
int create_listeners(struct bind_conf *bc, const struct sockaddr_storage *ss,
|
||||
int portl, int porth, int fd, char **err)
|
||||
int portl, int porth, int fd, int inherited, char **err)
|
||||
{
|
||||
struct protocol *proto = protocol_by_family(ss->ss_family);
|
||||
struct listener *l;
|
||||
@ -404,6 +406,9 @@ int create_listeners(struct bind_conf *bc, const struct sockaddr_storage *ss,
|
||||
|
||||
proto->add(l, port);
|
||||
|
||||
if (inherited)
|
||||
l->options |= LI_O_INHERITED;
|
||||
|
||||
HA_SPIN_INIT(&l->lock);
|
||||
HA_ATOMIC_ADD(&jobs, 1);
|
||||
HA_ATOMIC_ADD(&listeners, 1);
|
||||
|
Loading…
Reference in New Issue
Block a user