József, Cyril,

I have a good news. Your diag was right Cyril, the call to EV_FD_CLR()
was the root cause. I could simulate the bug by adding a close(cfd) just
after the accept(). I won't paraphrase my explanation in the attached
commit.

I'm pretty sure it's OK now. The bad news is that we also have to fix 1.4
which is affected too, so it will have to be fixed there too.

Kudos to you Cyril for narrowing the issue down, because I was looking at
more complex error cases and in fact it was unrelated to the tcp-request
rules. Thank you József for the number of tests you ran in production !

Willy

----
commit e9f32dbf5ce28396bcab9c954bf3180f75b0ff53
Author: Willy Tarreau <[email protected]>
Date:   Tue Sep 21 21:14:29 2010 +0200

    [BUG] stream_sock: cleanly disable the listener in case of resource shortage
    
    Jozsef R.Nagy reported a reliability issue on FreeBSD. Sometimes an error
    would be emitted, reporting the inability to switch a socket to non-blocking
    mode and the listener would definitely not accept anything. Cyril Bonté
    narrowed this bug down to the call to EV_FD_CLR(l->fd, DIR_RD).
    
    He was right because this call is wrong. It only disables input events on
    the listening socket, without setting the listener to the LI_LISTEN state,
    so any subsequent call to enable_listener() from maintain_proxies() is
    ignored ! The correct fix consists in calling disable_listener() instead.
    
    It is discutable whether we should keep such error path or just ignore the
    event. The goal in earlier versions was to temporarily disable new activity
    in order to let the system recover while releasing resources.

diff --git a/src/stream_sock.c b/src/stream_sock.c
index d72d0e5..64e3530 100644
--- a/src/stream_sock.c
+++ b/src/stream_sock.c
@@ -1205,7 +1205,7 @@ int stream_sock_accept(int fd)
                if (unlikely(ret < 0)) {
                        /* critical error encountered, generally a resource 
shortage */
                        if (p) {
-                               EV_FD_CLR(fd, DIR_RD);
+                               disable_listener(l);
                                p->state = PR_STIDLE;
                        }
                        jobs--;


Reply via email to