[clang] d919d02 - [scan-build] Fix deadlock at failures in libears/ear.c

Balazs Benics via cfe-commits cfe-commits at lists.llvm.org
Wed Feb 2 03:56:25 PST 2022


Author: Balazs Benics
Date: 2022-02-02T12:55:44+01:00
New Revision: d919d027ba2a41df5d51ce82ae7f2fb64d2cba41

URL: https://github.com/llvm/llvm-project/commit/d919d027ba2a41df5d51ce82ae7f2fb64d2cba41
DIFF: https://github.com/llvm/llvm-project/commit/d919d027ba2a41df5d51ce82ae7f2fb64d2cba41.diff

LOG: [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

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/clang/tools/scan-build-py/lib/libear/ear.c b/clang/tools/scan-build-py/lib/libear/ear.c
index b06ec7ab00040..94cb865bd0cab 100644
--- a/clang/tools/scan-build-py/lib/libear/ear.c
+++ b/clang/tools/scan-build-py/lib/libear/ear.c
@@ -411,6 +411,7 @@ static void bear_report_call(char const *fun, char const *const argv[]) {
   const char *cwd = getcwd(NULL, 0);
   if (0 == cwd) {
     perror("bear: getcwd");
+    pthread_mutex_unlock(&mutex);
     exit(EXIT_FAILURE);
   }
   char const *const out_dir = initial_env[0];
@@ -419,11 +420,13 @@ static void bear_report_call(char const *fun, char const *const argv[]) {
   if (-1 ==
       snprintf(filename, path_max_length, "%s/%d.cmd", out_dir, getpid())) {
     perror("bear: snprintf");
+    pthread_mutex_unlock(&mutex);
     exit(EXIT_FAILURE);
   }
   FILE *fd = fopen(filename, "a+");
   if (0 == fd) {
     perror("bear: fopen");
+    pthread_mutex_unlock(&mutex);
     exit(EXIT_FAILURE);
   }
   fprintf(fd, "%d%c", getpid(), RS);
@@ -437,6 +440,7 @@ static void bear_report_call(char const *fun, char const *const argv[]) {
   fprintf(fd, "%c", GS);
   if (fclose(fd)) {
     perror("bear: fclose");
+    pthread_mutex_unlock(&mutex);
     exit(EXIT_FAILURE);
   }
   free((void *)cwd);


        


More information about the cfe-commits mailing list