On 9 February 2013 11:06, Willy Tarreau <w...@1wt.eu> wrote:

> Hi,
>
> On Sat, Feb 09, 2013 at 10:44:04AM +0100, Marc-Antoine Perennou wrote:
> > I just made a simple test, running a webserver serving a big file
> locally,
> > using haproxy,
> > my wrapper and systemd service. I started a download and during this
> > download,
> > reloaded haproxy. I using nbproc = 2.
> > What happened ?
> > When I started haproxy, I ended up with a wrapper launching a child
> > launching itself
> > two children, we'll call them ha1, ha11 and ha12. Then when I reloaded,
> the
> > wrapper
> > launched a new child which launched two new children, ha2, ha21 and ha22.
> > ha11 and thus ha1 were still there until the download had finished, ha12
> > got to zombie state.
>
> Then if ha1 was still there, I don't understand how it did not prevent the
> new process from binding to the port. Could you please check ha1 is still
> bound to the port once the process runs ? That's what I don't understand.
>
> > ha2, ha21 and ha22 successfully have shown up and take all new
> connections.
> > Once the download has finished, ha11 exited, ha12 too (waitpid making it
> > leave the zombie state)
> > and then ha11, leaving us with only ha2, ha21 and ha22.
> > I think this is the expected behaviour, so there don't seem to be any bug
> > here.
>
> Yes it's the expected behaviour, but I don't understand *why* it works, so
> it is very possible that we're having a bug somewhere else making this work
> as a side effect.
>
> > For the EINTR stuff, I'm not sure at all, not really familiar with it,
> so I
> > will give it a look
>
> Typically I would replace :
>
>      waitpid(pid, NULL, 0);
>
> with
>
>      while (waitpid(pid, NULL, 0) == -1 && errno == EINTR);
>
> For instance, when your process receives SIGTTOU/SIGTTIN upon a failed
> attempt of a new process to start, the old one very likely skips a few
> children (one per signal).
>
> If it can help you, here's how to test for the worst case :
>
>   - have a running process with a simple configuration bound to one port :
>
>     listen foo
>          bind :8000
>
>   - then have a second configuration which will not work due to a double
>     bind on the same port, and another bind on the first port :
>
>     listen foo
>          bind :8000
>
>     listen fail1
>          bind :8001
>
>     listen fail2
>          bind :8001
>
>   - when the first one is running, try to start the second one. It will
>     fail to bind to :8000, will send a SIGTTOU to process 1 and try again.
>     Then it will fail to bind :8001 without knowing it's not because of #1,
>     so it will wait a bit, believing it's #1 which has not yet released it,
>     and then it will abort, sending SIGTTIN to #1 to inform it that it
> gives
>     up and that #1 must continue its job as if nothing happened.
>
>   - process 1 should then just remain unaffected. And restarting #1 with
>     the fail2 listener commented out should work as expected.
>
> Best regards,
> Willy
>
>
Maybe this can help you understand why it works:

Before the download:
haproxy   6090 root    4u     IPv4              53819      0t0     TCP
*:http (LISTEN)
haproxy   6092 root    4u     IPv4              53819      0t0     TCP
*:http (LISTEN)
haproxy   6093 root    4u     IPv4              53819      0t0     TCP
*:http (LISTEN)

During the download:
haproxy   6090 root    4u     IPv4              53819      0t0     TCP
*:http (LISTEN)
haproxy   6092 root    4u     IPv4              53819      0t0     TCP
*:http (LISTEN)
haproxy   6093 root    1u     IPv4              57972      0t0     TCP
Lou.local:http->Lou.local:40395 (ESTABLISHED)
haproxy   6093 root    4u     IPv4              53819      0t0     TCP
*:http (LISTEN)

During the download, after the reload:
haproxy   6093 root    1u     IPv4              57972      0t0     TCP
Lou.local:http->Lou.local:40395 (ESTABLISHED)
haproxy   6239 root    4u     IPv4              54622      0t0     TCP
*:http (LISTEN)
haproxy   6240 root    4u     IPv4              54622      0t0     TCP
*:http (LISTEN)
haproxy   6241 root    4u     IPv4              54622      0t0     TCP
*:http (LISTEN)

After the download:
haproxy   6239 root    4u     IPv4              54622      0t0     TCP
*:http (LISTEN)
haproxy   6240 root    4u     IPv4              54622      0t0     TCP
*:http (LISTEN)
haproxy   6241 root    4u     IPv4              54622      0t0     TCP
*:http (LISTEN)

Reply via email to