[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[Libevent-users] Is evthread_use_pthreads required for isolated evdns event_bases?
Hi there,
I'm developing a multithreaded proxy server (running on Linux 2.6.32;
libevent-2.0.20-stable), where each event_base is isolated to a single
thread.
As I understand, by isolating the event_bases per thread and not calling
evthread_use_pthreads(), I can avoid locking overheads. AFAIK,
evthread_use_pthreads() only needs to be called when multiple threads share
an event_base. If this is incorrect, then please disregard this email.
Otherwise, read on... :)
On one particular site, after about two weaks of heavy load (e.g. 500
req/sec), the evdns.c:transaction_id_pick() gets stuck in an infinite loop
(all threads using evdns get stuck and requests cannot be served).
Via a gdb debug session, I found that transaction_id_pick()'s call to
evutil_secure_rng_get_bytes() always returns the same trans_id. I could
not get any further due to compiler optimizations, so I rebuilt libevent
without optimizations and allowed it to run for another two weeks on the
customers site. Again, evdns.c:transaction_id_pick() got stuck in an
infinite loop.
This time I found that evdns's RC4-ish pseudorandom number generator
arc4random.c:arc4_getbyte() is always returning the same value. Inspecting
further, I found that the prng's permutation table (rs) is in an impossible
state (according to the arc4 logic):
(gdb) p rs
$1 = {i = 212 '\324', j = 102 'f',
s =
"\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\357\
357\357\
357\357\357\357\357\357",
<incomplete sequence \357>}
(gdb) p arc4_count
$2 = 1053737
So, something has trampled the memory.
Looking back through the libevent code, it seems that the prng's locks are
only initialised if evthread_use_pthreads() or
evthread_enable_lock_debuging() is called.
evthread_use_pthreads()
evthread_set_lock_callbacks()
event_global_setup_locks_()
evutil_secure_rng_global_setup_locks_()
arc4rand_lock()
Meanwhile, the arc4 permutation table appears to be shared by all
event_bases.
struct arc4_stream {
unsigned char i;
unsigned char j;
unsigned char s[256];
};
....
static struct arc4_stream rs;
Is this a bug or is evthread_use_pthreads() required for multiple --
isolated -- threads to use evdns?
Cheers.
*Joe
***********************************************************************
To unsubscribe, send an e-mail to majordomo@xxxxxxxxxxxxx with
unsubscribe libevent-users in the body.