From: Willy Tarreau Date: Fri, 7 Jun 2019 12:41:11 +0000 (+0200) Subject: MINOR: threads: serialize threads initialization X-Git-Tag: v2.0-dev7~29 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6ec902a;p=thirdparty%2Fhaproxy.git MINOR: threads: serialize threads initialization There is no point in initializing threads in parallel when we know that it's the moment where some global variables are turned to thread-local ones, and/or that some global variables are updated (like global_now or trash_size). Some FDs might be created/destroyed/reallocated and could be tricky to follow as well (think about epoll_fd for example). Instead of having to be extremely careful about all these, and to trigger false positives in thread sanitizers, let's simply initialize one thread at a time. The init step is very fast so nobody should even notice, and we won't have any more doubts about what might have happened when analysing a dump. See GH issues #111 and #117 for some background on this. --- diff --git a/src/haproxy.c b/src/haproxy.c index 9c93bed33f..2417917c5c 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -2572,6 +2572,15 @@ static void *run_thread_poll_loop(void *data) ti->clock_id = CLOCK_THREAD_CPUTIME_ID; #endif #endif + /* broadcast that we are ready and wait for other threads to start */ + thread_release(); + + /* Now, initialize one thread init at a time. This is better since + * some init code is a bit tricky and may release global resources + * after reallocating them locally. This will also ensure there is + * no race on file descriptors allocation. + */ + thread_isolate(); tv_update_date(-1,-1); @@ -2598,12 +2607,11 @@ static void *run_thread_poll_loop(void *data) } } - /* broadcast that we are ready and wait for other threads to finish - * their initialization. - */ + protocol_enable_all(); + + /* done initializing this thread, wait for others */ thread_release(); - protocol_enable_all(); run_poll_loop(); list_for_each_entry(ptdf, &per_thread_deinit_list, list)