| 414 | |
| 415 | |
| 416 | Status StackTraceCollector::TriggerAsync(int64_t tid, StackTrace* stack) { |
| 417 | CHECK(!sig_data_ && tid_ == 0) << "TriggerAsync() must not be called more than once per instance"; |
| 418 | |
| 419 | // Ensure that our signal handler is installed. |
| 420 | { |
| 421 | base::SpinLockHolder h(&g_signal_handler_lock); |
| 422 | if (!InitSignalHandlerUnlocked(g_stack_trace_signum)) { |
| 423 | return Status::NotSupported("unable to take thread stack: signal handler unavailable"); |
| 424 | } |
| 425 | } |
| 426 | // Ensure that libunwind is primed for use before we send any signals. Otherwise |
| 427 | // we can hit a deadlock with the following stack: |
| 428 | // GoogleOnceInit() [waits on the 'once' to finish, but will never finish] |
| 429 | // StackTrace::Collect() |
| 430 | // <signal handler> |
| 431 | // PrimeLibUnwind |
| 432 | // GoogleOnceInit() [not yet initted, so starts initializing] |
| 433 | // StackTrace::Collect() |
| 434 | GoogleOnceInit(&g_prime_libunwind_once, &PrimeLibunwind); |
| 435 | |
| 436 | std::unique_ptr<SignalData> data(new SignalData()); |
| 437 | // Set the target TID in our communication structure, so if we end up with any |
| 438 | // delayed signal reaching some other thread, it will know to ignore it. |
| 439 | data->queued_to_tid = tid; |
| 440 | data->stack = CHECK_NOTNULL(stack); |
| 441 | |
| 442 | // We use the raw syscall here instead of kill() to ensure that we don't accidentally |
| 443 | // send a signal to some other process in the case that the thread has exited and |
| 444 | // the TID been recycled. |
| 445 | siginfo_t info; |
| 446 | memset(&info, 0, sizeof(info)); |
| 447 | info.si_signo = g_stack_trace_signum; |
| 448 | info.si_code = SI_QUEUE; |
| 449 | info.si_pid = getpid(); |
| 450 | info.si_uid = getuid(); |
| 451 | info.si_value.sival_ptr = data.get(); |
| 452 | // Since we're using a signal to pass information between the two threads, |
| 453 | // we need to help TSAN out and explicitly tell it about the happens-before |
| 454 | // relationship here. |
| 455 | ANNOTATE_HAPPENS_BEFORE(data.get()); |
| 456 | if (syscall(SYS_rt_tgsigqueueinfo, getpid(), tid, g_stack_trace_signum, &info) != 0) { |
| 457 | return Status::NotFound("unable to deliver signal: process may have exited"); |
| 458 | } |
| 459 | |
| 460 | // The signal is now pending to the target thread. We don't store it in a unique_ptr |
| 461 | // inside the class since we need to be careful to destruct it safely in case the |
| 462 | // target thread hasn't yet received the signal when this instance gets destroyed. |
| 463 | sig_data_ = data.release(); |
| 464 | tid_ = tid; |
| 465 | |
| 466 | return Status::OK(); |
| 467 | } |
| 468 | |
| 469 | Status StackTraceCollector::AwaitCollection(MonoTime deadline) { |
| 470 | CHECK(sig_data_) << "Must successfully call TriggerAsync() first"; |