From eff23382c2aa80e455398eaf4e5b965b14c0ddcf Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Sun, 27 Apr 2014 14:28:59 -0700 Subject: [PATCH] plugins/{airbrake,alarm_curl,alarm_xmpp}: fix race condition A thread may run immediately after it's created. Trying to pass parameter to thread using uwsgi_thread->data without preventing the thread from accessing it first is a race condition. If the thread accesses uwsgi_thread->data first, uwsgi gets killed by SIGSEGV. This patch creates a new function uwsgi_thread_new_with_data() to assign user provided data to uwsgi_thread->data before the thread is created. --- core/utils.c | 7 ++++++- plugins/airbrake/airbrake_plugin.c | 7 +++---- plugins/alarm_curl/alarm_curl_plugin.c | 7 +++---- plugins/alarm_xmpp/alarm_xmpp_plugin.c | 3 +-- uwsgi.h | 1 + 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/core/utils.c b/core/utils.c index 7bc359e0..c0976a1f 100644 --- a/core/utils.c +++ b/core/utils.c @@ -3752,7 +3752,7 @@ static void *uwsgi_thread_run(void *arg) { return NULL; } -struct uwsgi_thread *uwsgi_thread_new(void (*func) (struct uwsgi_thread *)) { +struct uwsgi_thread *uwsgi_thread_new_with_data(void (*func) (struct uwsgi_thread *), void *data) { struct uwsgi_thread *ut = uwsgi_calloc(sizeof(struct uwsgi_thread)); @@ -3769,6 +3769,7 @@ struct uwsgi_thread *uwsgi_thread_new(void (*func) (struct uwsgi_thread *)) { uwsgi_socket_nb(ut->pipe[1]); ut->func = func; + ut->data = data; pthread_attr_init(&ut->tattr); pthread_attr_setdetachstate(&ut->tattr, PTHREAD_CREATE_DETACHED); @@ -3788,6 +3789,10 @@ error: return NULL; } +struct uwsgi_thread *uwsgi_thread_new(void (*func) (struct uwsgi_thread *)) { + return uwsgi_thread_new_with_data(func, NULL); +} + int uwsgi_kvlist_parse(char *src, size_t len, char list_separator, char kv_separator, ...) { size_t i; va_list ap; diff --git a/plugins/airbrake/airbrake_plugin.c b/plugins/airbrake/airbrake_plugin.c index ee54b72a..69d368c7 100644 --- a/plugins/airbrake/airbrake_plugin.c +++ b/plugins/airbrake/airbrake_plugin.c @@ -271,12 +271,11 @@ static void uwsgi_airbrake_loop(struct uwsgi_thread *ut) { } static void uwsgi_airbrake_init(struct uwsgi_alarm_instance *uai) { - struct uwsgi_thread *ut = uwsgi_thread_new(uwsgi_airbrake_loop); - if (!ut) return; - uai->data_ptr = ut; struct uwsgi_airbrake_config *uacc = uwsgi_calloc(sizeof(struct uwsgi_airbrake_config)); uacc->arg = uai->arg; - ut->data = uacc; + struct uwsgi_thread *ut = uwsgi_thread_new_with_data(uwsgi_airbrake_loop, uacc); + if (!ut) return; + uai->data_ptr = ut; } static void uwsgi_airbrake_func(struct uwsgi_alarm_instance *uai, char *msg, size_t len) { diff --git a/plugins/alarm_curl/alarm_curl_plugin.c b/plugins/alarm_curl/alarm_curl_plugin.c index 6e597a60..52e16076 100644 --- a/plugins/alarm_curl/alarm_curl_plugin.c +++ b/plugins/alarm_curl/alarm_curl_plugin.c @@ -234,12 +234,11 @@ static void uwsgi_alarm_curl_loop(struct uwsgi_thread *ut) { } static void uwsgi_alarm_curl_init(struct uwsgi_alarm_instance *uai) { - struct uwsgi_thread *ut = uwsgi_thread_new(uwsgi_alarm_curl_loop); - if (!ut) return; - uai->data_ptr = ut; struct uwsgi_alarm_curl_config *uacc = uwsgi_calloc(sizeof(struct uwsgi_alarm_curl_config)); uacc->arg = uai->arg; - ut->data = uacc; + struct uwsgi_thread *ut = uwsgi_thread_new_with_data(uwsgi_alarm_curl_loop, uacc); + if (!ut) return; + uai->data_ptr = ut; } // pipe the message into the thread; diff --git a/plugins/alarm_xmpp/alarm_xmpp_plugin.c b/plugins/alarm_xmpp/alarm_xmpp_plugin.c index 595465a8..784a9650 100644 --- a/plugins/alarm_xmpp/alarm_xmpp_plugin.c +++ b/plugins/alarm_xmpp/alarm_xmpp_plugin.c @@ -4,10 +4,9 @@ void uwsgi_alarm_xmpp_loop(struct uwsgi_thread *); static void uwsgi_alarm_xmpp_init(struct uwsgi_alarm_instance *uai) { - struct uwsgi_thread *ut = uwsgi_thread_new(uwsgi_alarm_xmpp_loop); + struct uwsgi_thread *ut = uwsgi_thread_new_with_data(uwsgi_alarm_xmpp_loop, uai->arg); if (!ut) return; uai->data_ptr = ut; - ut->data = uai->arg; } // pipe the message into the thread; diff --git a/uwsgi.h b/uwsgi.h index 48d01a2a..37a87b9d 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -4175,6 +4175,7 @@ struct uwsgi_thread { void (*func) (struct uwsgi_thread *); }; struct uwsgi_thread *uwsgi_thread_new(void (*)(struct uwsgi_thread *)); +struct uwsgi_thread *uwsgi_thread_new_with_data(void (*)(struct uwsgi_thread *), void *data); struct uwsgi_offload_request { // the request socket