Bug #2249

1.4.27 segfaults on FreeBSD

Added by mm over 4 years ago. Updated over 4 years ago.

Status:FixedStart date:2010-08-16
Priority:HighDue date:
Assignee:-% Done:

0%

Category:-
Target version:1.4.28
Missing in 1.5.x:No

Description

Lighttpd 1.4.27 using mod_fastcgi segfaults on FreeBSD with the freebsd-kqueue event handler.

I have added the SVN revision 2764 patch.

In the logfile, there are reports:
(mod_fastcgi.c.3397) got a FDEVENT_OUT and didn't know why: 5

After serving a while lighttpd segfaults.
1.4.26 does not have these problems.

I will do more investigation.

Associated revisions

Revision 2765
Added by stbuehler over 4 years ago

Rename fdevent_event_add to _set to reflect what the function does. Fix some handlers.

History

#1 Updated by mm over 4 years ago

The process exits on signal 6 (SIGABRT):
pid 48503 (lighttpd), uid 80: exited on signal 6

#2 Updated by stbuehler over 4 years ago

  • Status changed from New to Need Feedback

Please provide a backtrace, thx.

#3 Updated by bazerka over 4 years ago

I've also come across this issue although it seems quite random and can be hard to reproduce.

2010-08-17 17:04:32: (mod_fastcgi.c.3397) got a FDEVENT_OUT and didn't know why: 5

This is 1.4.27 with r2764 applied.

$ gdb lighttpd
GNU gdb 6.1.1 [FreeBSD]
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "amd64-marcel-freebsd"...
(gdb) handle SIGPIPE pass nostop noprint
Signal        Stop      Print   Pass to program Description
SIGPIPE       No        No      Yes             Broken pipe
(gdb) r -D -f /usr/local/etc/lighttpd.conf
Starting program: /usr/local/sbin/lighttpd -D -f /usr/local/etc/lighttpd.conf
fdevent.c.171: aborted

Program received signal SIGABRT, Aborted.
0x0000000800c3fd2c in kill () from /lib/libc.so.7
(gdb) bt full
#0  0x0000000800c3fd2c in kill () from /lib/libc.so.7
No symbol table info available.
#1  0x0000000800c3ecd3 in abort () from /lib/libc.so.7
No symbol table info available.
#2  0x000000000041f608 in fdevent_get_handler (ev=0x800e03c00, fd=64) at fdevent.c:171
No locals.
#3  0x0000000000409d38 in main (argc=4, argv=0x7fffffffeaa0) at server.c:1447
        handler = 0x8015346a6 <fcgi_handle_fdevent>
        context = (void *) 0x800e74040
        r = HANDLER_FINISHED
        revents = 4
        fd_ndx = 1
        n = 1
        ndx = 26
        min_ts = 1282064682
        srv = (server *) 0x800e02400
        print_config = 0
        test_config = 0
        i_am_root = 1
        o = -1
        num_childs = 0
        pid_fd = -1
        fd = 64
        i = 3
        act = {__sigaction_u = {__sa_handler = 0x406f14 <sigaction_handler>, __sa_sigaction = 0x406f14 <sigaction_handler>}, sa_flags = 64, sa_mask = {__bits = {0, 0, 0, 0}}}
        rlim = {rlim_cur = 9223372036854775807, rlim_max = 9223372036854775807}
(gdb)

#4 Updated by bazerka over 4 years ago

Some additional info from a later occurrence of the segfault:

(gdb) frame 2
#2  0x000000000041f608 in fdevent_get_handler (ev=0x800e03c00, fd=63) at fdevent.c:171
171             if (ev->fdarray[fd] == NULL) SEGFAULT();
(gdb) p *ev
$1 = {srv = 0x800e02400, type = FDEVENT_HANDLER_FREEBSD_KQUEUE, fdarray = 0x800e86000, maxfds = 11096, pollfds = 0x0, size = 0, used = 0, unused = {ptr = 0x0, used = 0, size = 0},
  select_read = {__fds_bits = {0 <repeats 16 times>}}, select_write = {__fds_bits = {0 <repeats 16 times>}}, select_error = {__fds_bits = {0 <repeats 16 times>}}, select_set_read = {
    __fds_bits = {0 <repeats 16 times>}}, select_set_write = {__fds_bits = {0 <repeats 16 times>}}, select_set_error = {__fds_bits = {0 <repeats 16 times>}}, select_max_fd = 0, kq_fd = 12,
  kq_results = 0x800e9c000, reset = 0x42662e <fdevent_freebsd_kqueue_reset>, free = 0x4261c4 <fdevent_freebsd_kqueue_free>, event_add = 0x426306 <fdevent_freebsd_kqueue_event_add>,
  event_del = 0x4261f1 <fdevent_freebsd_kqueue_event_del>, event_get_revent = 0x426550 <fdevent_freebsd_kqueue_event_get_revent>, event_get_fd = 0x4265de <fdevent_freebsd_kqueue_event_get_fd>,
  event_next_fdndx = 0x426606 <fdevent_freebsd_kqueue_event_next_fdndx>, poll = 0x426419 <fdevent_freebsd_kqueue_poll>, fcntl_set = 0}
(gdb) p (fdnode)ev->fdarray[63]
$9 = {handler = 0, ctx = 0x8023029e0, handler_ctx = 0x0, fd = 0}

#5 Updated by stbuehler over 4 years ago

Hm, that one looks really difficult.

My guess is that some fdevent callback handler deleted its fdevent context, but the fd got READ and WRITE event (which kqueue sees as two events), so the second event segfaults.

In that case current svn should fix the problem (i think i restored the old behaviour for _add/_set, so only one event should be active); it would be nice if you could test that.

But i also think it would be nice to make the fdevent code ignore events if the context got deleted in a different callback instead of crashing.
I think the difficult part would be that one callback could remove a context and close the fd, and another callback could get that fd for something else and add a new handler; we need to drop the event for the old fd and should not call the new handler for an event of the old fd.

#6 Updated by mm over 4 years ago

The recent SVN fix seems to solve the problem for now. I have tested it and I am committing it to FreeBSD ports.

#7 Updated by stbuehler over 4 years ago

  • Status changed from Need Feedback to Fixed

Also available in: Atom