MCPcopy Create free account
hub / github.com/apache/impala / TriggerAsync

Method TriggerAsync

be/src/kudu/util/debug-util.cc:416–467  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

414
415
416Status 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
469Status StackTraceCollector::AwaitCollection(MonoTime deadline) {
470 CHECK(sig_data_) << "Must successfully call TriggerAsync() first";

Callers 3

TEST_FFunction · 0.80
GetThreadStackFunction · 0.80
SnapshotAllStacksMethod · 0.80

Calls 7

NotSupportedFunction · 0.85
GoogleOnceInitFunction · 0.85
NotFoundFunction · 0.85
OKFunction · 0.85
getMethod · 0.65
releaseMethod · 0.45

Tested by 1

TEST_FFunction · 0.64