Skip to content

Commit 9fa896f

Browse files
Balazs Benicststellar
Balazs Benics
authored andcommitted
[scan-build] Fix deadlock at failures in libears/ear.c
We experienced some deadlocks when we used multiple threads for logging using `scan-builds` intercept-build tool when we used multiple threads by e.g. logging `make -j16` ``` (gdb) bt #0 0x00007f2bb3aff110 in __lll_lock_wait () from /lib/x86_64-linux-gnu/libpthread.so.0 #1 0x00007f2bb3af70a3 in pthread_mutex_lock () from /lib/x86_64-linux-gnu/libpthread.so.0 #2 0x00007f2bb3d152e4 in ?? () #3 0x00007ffcc5f0cc80 in ?? () #4 0x00007f2bb3d2bf5b in ?? () from /lib64/ld-linux-x86-64.so.2 #5 0x00007f2bb3b5da27 in ?? () from /lib/x86_64-linux-gnu/libc.so.6 #6 0x00007f2bb3b5dbe0 in exit () from /lib/x86_64-linux-gnu/libc.so.6 #7 0x00007f2bb3d144ee in ?? () #8 0x746e692f706d742f in ?? () #9 0x692d747065637265 in ?? () #10 0x2f653631326b3034 in ?? () #11 0x646d632e35353532 in ?? () #12 0x0000000000000000 in ?? () ``` I think the gcc's exit call caused the injected `libear.so` to be unloaded by the `ld`, which in turn called the `void on_unload() __attribute__((destructor))`. That tried to acquire an already locked mutex which was left locked in the `bear_report_call()` call, that probably encountered some error and returned early when it forgot to unlock the mutex. All of these are speculation since from the backtrace I could not verify if frames 2 and 3 are in fact corresponding to the `libear.so` module. But I think it's a fairly safe bet. So, hereby I'm releasing the held mutex on *all paths*, even if some failure happens. PS: I would use lock_guards, but it's C. Reviewed-by: NoQ Differential Revision: https://reviews.llvm.org/D118439 (cherry picked from commit d919d02)
1 parent b9f51fa commit 9fa896f

File tree

1 file changed

+4
-0
lines changed
  • clang/tools/scan-build-py/lib/libear

1 file changed

+4
-0
lines changed

clang/tools/scan-build-py/lib/libear/ear.c

+4
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,7 @@ static void bear_report_call(char const *fun, char const *const argv[]) {
411411
const char *cwd = getcwd(NULL, 0);
412412
if (0 == cwd) {
413413
perror("bear: getcwd");
414+
pthread_mutex_unlock(&mutex);
414415
exit(EXIT_FAILURE);
415416
}
416417
char const *const out_dir = initial_env[0];
@@ -419,11 +420,13 @@ static void bear_report_call(char const *fun, char const *const argv[]) {
419420
if (-1 ==
420421
snprintf(filename, path_max_length, "%s/%d.cmd", out_dir, getpid())) {
421422
perror("bear: snprintf");
423+
pthread_mutex_unlock(&mutex);
422424
exit(EXIT_FAILURE);
423425
}
424426
FILE *fd = fopen(filename, "a+");
425427
if (0 == fd) {
426428
perror("bear: fopen");
429+
pthread_mutex_unlock(&mutex);
427430
exit(EXIT_FAILURE);
428431
}
429432
fprintf(fd, "%d%c", getpid(), RS);
@@ -437,6 +440,7 @@ static void bear_report_call(char const *fun, char const *const argv[]) {
437440
fprintf(fd, "%c", GS);
438441
if (fclose(fd)) {
439442
perror("bear: fclose");
443+
pthread_mutex_unlock(&mutex);
440444
exit(EXIT_FAILURE);
441445
}
442446
free((void *)cwd);

0 commit comments

Comments
 (0)