From 43d92a6dab058914f6d2e83dd1b3ba7e337fa8b4 Mon Sep 17 00:00:00 2001 From: James Synge Date: Mon, 7 Aug 2017 11:06:28 -0400 Subject: [PATCH] Fix race in access to ev_res from event loop with event_active() Detected using ThreadSanitizer, resolved by capturing the value of ev_res in a local variable while the event is locked, then passing that captured variable to the callback. TSAN report: I0728 14:35:09.822118 WARNING: ThreadSanitizer: data race (pid=815501) I0728 14:35:09.822186 Write of size 2 at 0x7b2c00001bf2 by thread T80 (mutexes: write M1110835549570434736): I0728 14:35:09.822248 #0 event_active_nolock_ libevent/event.c:2893:14 (0a2b90577e830d775300664df77d0b91+0x1fdab28) I0728 14:35:09.822316 #1 event_active libevent/event.c:2858:2 (0a2b90577e830d775300664df77d0b91+0x1fdd10e) I0728 14:35:09.822379 #2 Envoy::Event::TimerImpl::enableTimer(std::chrono::duration > const&) envoy/source/common/event/timer_impl.cc:24:5 (0a2b90577e830d775300664df77d0b91+0x459fa0) ... I0728 14:35:09.824146 Previous read of size 2 at 0x7b2c00001bf2 by main thread: I0728 14:35:09.824232 #0 event_process_active_single_queue libevent/event.c:1646:33 (0a2b90577e830d775300664df77d0b91+0x1fdf83d) I0728 14:35:09.824350 #1 event_process_active libevent/event.c (0a2b90577e830d775300664df77d0b91+0x1fd9ad8) I0728 14:35:09.824445 #2 event_base_loop libevent/event.c:1961 (0a2b90577e830d775300664df77d0b91+0x1fd9ad8) I0728 14:35:09.824550 #3 Envoy::Event::DispatcherImpl::run(Envoy::Event::Dispatcher::RunType) envoy/source/common/event/dispatcher_impl.cc:166:3 (0a2b90577e830d775300664df77d0b91+0x4576d9) ... Fixes: #543 (pull-request) (cherry picked from commit 27934f0b39991172dcfdad23faea9874dd386f10) --- event.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/event.c b/event.c index d2768793..98b1bc4a 100644 --- a/event.c +++ b/event.c @@ -1641,10 +1641,12 @@ event_process_active_single_queue(struct event_base *base, break; case EV_CLOSURE_EVENT: { void (*evcb_callback)(evutil_socket_t, short, void *); + short res; EVUTIL_ASSERT(ev != NULL); evcb_callback = *ev->ev_callback; + res = ev->ev_res; EVBASE_RELEASE_LOCK(base, th_base_lock); - evcb_callback(ev->ev_fd, ev->ev_res, ev->ev_arg); + evcb_callback(ev->ev_fd, res, ev->ev_arg); } break; case EV_CLOSURE_CB_SELF: { -- 2.40.0