Skip to content

Commit 526c0a8

Browse files
peffgitster
authored andcommitted
index-pack: work around LSan threading race with barrier
We sometimes get false positives from our linux-leaks CI job because of a race in LSan itself. The problem is that one thread is still initializing its stack in LSan's code (and allocating memory to do so) while anothe thread calls die(), taking down the whole process and triggering a leak check. The problem is described in more detail in 993d38a (index-pack: spawn threads atomically, 2024-01-05), which tried to fix it by pausing worker threads until all calls to pthread_create() had completed. But that's not enough to fix the problem, because the LSan setup code runs in the threads themselves. So even though pthread_create() has returned, we have no idea if all threads actually finished their setup before letting any of them do real work. We can fix that by using a barrier inside the threads themselves, waiting for all of them to hit the start of their main function before any of them proceed. You can test for the race by running: make SANITIZE=leak THREAD_BARRIER_PTHREAD=YesOnLinux cd t ./t5309-pack-delta-cycles.sh --stress which fails quickly before this patch, and should run indefinitely without it. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 7d0037b commit 526c0a8

File tree

1 file changed

+6
-0
lines changed

1 file changed

+6
-0
lines changed

builtin/index-pack.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,8 @@ static pthread_mutex_t deepest_delta_mutex;
185185

186186
static pthread_key_t key;
187187

188+
static maybe_thread_barrier_t start_barrier;
189+
188190
static inline void lock_mutex(pthread_mutex_t *mutex)
189191
{
190192
if (threads_active)
@@ -209,6 +211,7 @@ static void init_thread(void)
209211
if (show_stat)
210212
pthread_mutex_init(&deepest_delta_mutex, NULL);
211213
pthread_key_create(&key, NULL);
214+
maybe_thread_barrier_init(&start_barrier, NULL, nr_threads);
212215
CALLOC_ARRAY(thread_data, nr_threads);
213216
for (i = 0; i < nr_threads; i++) {
214217
thread_data[i].pack_fd = xopen(curr_pack, O_RDONLY);
@@ -231,6 +234,7 @@ static void cleanup_thread(void)
231234
for (i = 0; i < nr_threads; i++)
232235
close(thread_data[i].pack_fd);
233236
pthread_key_delete(key);
237+
maybe_thread_barrier_destroy(&start_barrier);
234238
free(thread_data);
235239
}
236240

@@ -1100,6 +1104,8 @@ static int compare_ref_delta_entry(const void *a, const void *b)
11001104

11011105
static void *threaded_second_pass(void *data)
11021106
{
1107+
if (threads_active)
1108+
maybe_thread_barrier_wait(&start_barrier);
11031109
if (data)
11041110
set_thread_data(data);
11051111
for (;;) {

0 commit comments

Comments
 (0)