theRockLiu / thread-sanitizer

Automatically exported from code.google.com/p/thread-sanitizer
0 stars 0 forks source link

sigsuspend does not work under TSan #23

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Repro by Julien Tinnes, 
https://code.google.com/p/chromium/issues/detail?id=258655

$ cat sig.cc 

#include <assert.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

static bool signal_handler_ran = false;

void do_nothing_signal_handler(int signum) {
  write(2, "BBBBBBB\n", 8);
  signal_handler_ran = true;
}

int main() {
  int kSignalToTest = SIGSYS;
  assert(SIG_ERR != signal(kSignalToTest, do_nothing_signal_handler));
  sigset_t empty_set;
  assert(0 == sigemptyset(&empty_set));
  sigset_t one_signal = empty_set;
  assert(0 == sigaddset(&one_signal, kSignalToTest));
  sigset_t old_set;
  assert(0 == sigprocmask(SIG_BLOCK, &one_signal, &old_set));
  raise(kSignalToTest);
  assert(!signal_handler_ran);
  sigset_t all_but_one;
  assert(0 == sigfillset(&all_but_one));
  assert(0 == sigdelset(&all_but_one, kSignalToTest));
  sigsuspend(&all_but_one);
  assert(signal_handler_ran);

  // Restore the original set.
  assert (0 == sigprocmask(SIG_SETMASK, &old_set, NULL));
}
$ bin/clang++ sig.cc   -o sig
$ ./sig 
BBBBBBB
$ bin/clang++ sig.cc -fsanitize=thread  -o sig -g
$ ./sig 
==================
WARNING: ThreadSanitizer: signal-unsafe call inside of a signal (pid=11791)
    #0 write /usr/local/google/asan/llvm/projects/compiler-rt/lib/tsan/../sanitizer_common/sanitizer_common_interceptors.inc:232 (exe+0x000000018344)
    #1 do_nothing_signal_handler(int) /usr/local/google/asan/llvm/llvm_cmake_build/sig.cc:9 (exe+0x000000063d43)
    #2 __tsan::ProcessPendingSignals(__tsan::ThreadState*) /usr/local/google/asan/llvm/projects/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc:1877 (exe+0x00000000d2d4)
    #3 __libc_start_main /build/buildd/eglibc-2.15/csu/libc-start.c:226 (libc.so.6+0x00000002176c)

SUMMARY: ThreadSanitizer: signal-unsafe call inside of a signal 
/usr/local/google/asan/llvm/llvm_cmake_build/sig.cc:9 
do_nothing_signal_handler(int)
==================
BBBBBBB
sig: sig.cc:28: int main(): Assertion `signal_handler_ran' failed.
Aborted (core dumped)

Original issue reported on code.google.com by gli...@google.com on 10 Jul 2013 at 10:15

GoogleCodeExporter commented 9 years ago

Original comment by gli...@chromium.org on 10 Jul 2013 at 10:16

GoogleCodeExporter commented 9 years ago
Not the main bug (which is that sigsuspend doesn't work properly), but in this 
output, it also looks like it's mistakenly flagging "write" as not being async 
signal safe.

Which would be a big problem for Chromium.

Original comment by jln@chromium.org on 11 Jul 2013 at 11:12

GoogleCodeExporter commented 9 years ago
Er, this program actually prints something, which means that 
do_nothing_signal_handler() is being called. Doesn't this mean sigsuspend() 
actually works?

// I still don't understand why signal_handler_ran is 0 after the return from 
the handler.

Original comment by gli...@google.com on 12 Jul 2013 at 12:03

GoogleCodeExporter commented 9 years ago
Should be fixed by:
http://llvm.org/viewvc/llvm-project?view=revision&revision=186400

Original comment by dvyu...@google.com on 16 Jul 2013 at 11:47

GoogleCodeExporter commented 9 years ago
> Er, this program actually prints something, which means that 
do_nothing_signal_handler() is being called.

I guess it's called some time later.

> WARNING: ThreadSanitizer: signal-unsafe call inside of a signal (pid=11791)

I can not reproduce this.

> Which would be a big problem for Chromium.

I will fix it, if I can reproduce it. I do not understand how it happens.

Original comment by dvyu...@google.com on 16 Jul 2013 at 11:52

GoogleCodeExporter commented 9 years ago
Excellent, thanks a lot!

Original comment by jln@chromium.org on 17 Jul 2013 at 5:57