Bug 478305

Summary: libevent borked, upstream's event-test.c doesn't run correctly
Product: [Fedora] Fedora Reporter: Evan Klitzke <evan>
Component: libeventAssignee: Steve Dickson <steved>
Status: CLOSED NOTABUG QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: high Docs Contact:
Priority: low    
Version: 10CC: steved
Target Milestone: ---   
Target Release: ---   
Hardware: x86_64   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2008-12-31 18:53:22 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Attachments:
Description Flags
shows what event_set is doing none

Description Evan Klitzke 2008-12-27 18:08:11 UTC
So the background behind this, first. I was trying to build my own memcached (which links against libevent), and I couldn't get it working. Curiously, the memcached packaged for Fedora works (i.e. the packaged memcached works, but when I try to compile it myself it doesn't work).

The symptom that I see is that if I start up the memcached I compile (from latest upstream stable release), when I connect to memcached, memcached never gets the connection event. So if I tcpdump a session, there's a successful TCP handshake between the client and the memcached server. But strace'ing the memcached process shows that it's just looping on epoll_wait and never actually received a connection event (also doesn't receive data I send it). Again, the memcached packaged for Fedora works and I don't really know why.

So after much poking around I thought maybe libevent is broken. It turns out that there is a test program on the libevent website, at http://monkey.org/~provos/libevent/event-test.c . What this program is supposed to do is create a file called event.fifo and then print out "Write data to event.fifo". It then blocks, and if you write data to the fifo the event-test program prints out some message like:

fifo_read called with fd: 3, event: 2, arg: 0xbf813f08
Read: 1

I was able to confirm this behavior on two other machines I have (also the source is really small, it's pretty apparent that that's the intended behavior). However, if I compile this on my FC10 computer, the test program doesn't work at all. Instead it just prints out "Write data to event.fifo" and then immediately exits.

Here's the version of everything I'm running:

uname -a:
Linux gemini 2.6.27.9-159.fc10.x86_64 #1 SMP Tue Dec 16 14:47:52 EST 2008 x86_64 x86_64 x86_64 GNU/Linux

libevent is version 1.4.5 release 1.fc10 (x86_64 arch).

The test libevent program was compiled as:
gcc -o event-test event-test.c -levent

evan@gemini:~$ ldd event-test 
	linux-vdso.so.1 =>  (0x00007fff5f1ff000)
	libevent-1.4.so.2 => /usr/lib64/libevent-1.4.so.2 (0x0000003486600000)
	libc.so.6 => /lib64/libc.so.6 (0x0000003479000000)
	libnsl.so.1 => /lib64/libnsl.so.1 (0x0000003482200000)
	librt.so.1 => /lib64/librt.so.1 (0x000000347ac00000)
	libresolv.so.2 => /lib64/libresolv.so.2 (0x0000003483a00000)
	/lib64/ld-linux-x86-64.so.2 (0x0000003478c00000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003479c00000)

Comment 1 Evan Klitzke 2008-12-28 02:20:09 UTC
FWIW, I downloaded and compiled the 1.4.9 tarball (the latest stable release). When linking against that, event-test exhibits the correct behavior.

Comment 2 Evan Klitzke 2008-12-28 20:51:53 UTC
Now I'm not so sure the problem is with libevent. When I built the new libevent yesterday things were working for a while, and now they're not again. The event-test.c program exhibits the same incorrect behavior as when linked to FC10's libevent as it does when linked against the 1.4.9 libevent that I built myself (i.e. it exits immediately).

I'm going to poke around with libevent and see if I can come up with a better test case exhibiting the problem, but I don't have a lot of ideas...

Comment 3 Evan Klitzke 2008-12-29 08:41:52 UTC
Created attachment 327916 [details]
shows what event_set is doing

OK, so I looked at this as much as I know how to, and here's what I've been able to find.

When I strace the programs I built with libevent (memcached and the event-test.c file) I found that after calling libevent's event_add, there was no call to epoll_ctl. This is consistent with the brokenness I see in memcached. I'm not able to connect to memcached because it's looping with epoll_wait on an epoll fd that isn't monitoring anything with it. I think it's also consistent with event-test.c exiting instead of blocking, because I guess that the epoll_add isn't really adding the fd to be monitored, so the libevent event loop has nothing to do. This makes event_dispatch return immediately.

So event_add isn't really adding the fd to be monitored. The question is, why is that? I think maybe I'm crazy or something but it looks like after returning from event_set the event struct that is passed in isn't initialized correctly? I'm kind of confused about this myself. If you run the attached C file (i.e. gcc -g -o evtest -levent evtest.c) I would expect it to print ev->ev_flags = 0x80 and ev->ev_events = 0x1 at the end, but it doesn't. This is curious to me because if I am understanding everything correctly, it looks like ev->ev_events and ev->ev_flags are correct inside of the event_set program when I run everything through gdb. IOW I might be misunderstanding things, but to me it looks like inside of event_set the struct members are correct, and then when it returns they got corrupted somehow.

Also, if you make ev not a local non-pointer allocated on the stack, and instead pass &ev to event_set you get a different result. But I'm not really a C programmer, I could be totally confused about the event_set part of the problem.

Here's what I'm seeing:

evtest.c, attached version:
EV_READ = 0x1
EV_RITE = 0x2
EV_SIGNAL = 0x400
EVLIST_INSERTED = 0x2
EVLIST_ACTIVE = 0x8
EVLIST_INIT = 0x80
ev->ev_flags = 0x0
ev->ev_events = 0x0

evtest.c, struct event ev declared local/on the stack:
EV_READ = 0x1
EV_RITE = 0x2
EV_SIGNAL = 0x400
EVLIST_INSERTED = 0x2
EVLIST_ACTIVE = 0x8
EVLIST_INIT = 0x80
ev->ev_flags = 0x7fff
ev->ev_events = 0x0

I think at this point it would be helpful if someone with better C knowledge took a look at this.

Comment 4 Evan Klitzke 2008-12-31 18:53:22 UTC
err I think this one was just PEBCAK