Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/bthread/task_control.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

// Date: Tue Jul 10 17:40:58 CST 2012

#include <pthread.h>
#include <sys/syscall.h> // SYS_gettid
#include "butil/scoped_lock.h" // BAIDU_SCOPED_LOCK
#include "butil/errno.h" // berror
Expand Down Expand Up @@ -90,7 +91,7 @@ void* TaskControl::worker_thread(void* arg) {
return NULL;
}

g->_tid = syscall(SYS_gettid);
g->_tid = pthread_self();

std::string worker_thread_name = butil::string_printf(
"brpc_wkr:%d-%d", g->tag(),
Expand Down
2 changes: 1 addition & 1 deletion src/bthread/task_group.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1107,7 +1107,7 @@ void print_task(std::ostream& os, bthread_t tid) {
TaskStatistics stat = {0, 0, 0};
TaskStatus status = TASK_STATUS_UNKNOWN;
bool traced = false;
pid_t worker_tid = 0;
pthread_t worker_tid{};
{
BAIDU_SCOPED_LOCK(m->version_lock);
if (given_ver == *m->version_butex) {
Expand Down
4 changes: 2 additions & 2 deletions src/bthread/task_group.h
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ class TaskGroup {

bthread_tag_t tag() const { return _tag; }

pid_t tid() const { return _tid; }
pthread_t tid() const { return _tid; }

int64_t current_task_cpu_clock_ns() {
if (_last_cpu_clock_ns == 0) {
Expand Down Expand Up @@ -378,7 +378,7 @@ friend class TaskControl;
bthread_tag_t _tag{BTHREAD_TAG_DEFAULT};

// Worker thread id.
pid_t _tid{-1};
pthread_t _tid{};
};

} // namespace bthread
Expand Down
2 changes: 1 addition & 1 deletion src/bthread/task_meta.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ struct TaskMeta {
// Whether bthread is traced?
bool traced{false};
// Worker thread id.
pid_t worker_tid{-1};
pthread_t worker_tid{};

public:
// Only initialize [Not Reset] fields, other fields will be reset in
Expand Down
35 changes: 20 additions & 15 deletions src/bthread/task_tracer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,18 @@
#ifdef BRPC_BTHREAD_TRACER

#include "bthread/task_tracer.h"
#include <unistd.h>
#include <poll.h>
#include <gflags/gflags.h>
#include <absl/debugging/stacktrace.h>
#include <absl/debugging/symbolize.h>
#include "butil/debug/stack_trace.h"
#include "bthread/processor.h"
#include "bthread/task_group.h"
#include "butil/fd_utility.h"
#include "butil/memory/scope_guard.h"
#include "butil/reloadable_flags.h"
#include "butil/fd_utility.h"
#include "bthread/task_group.h"
#include "bthread/processor.h"
#include <absl/debugging/stacktrace.h>
#include <absl/debugging/symbolize.h>
#include <csignal>
Comment thread
chenBright marked this conversation as resolved.
#include <gflags/gflags.h>
#include <poll.h>
#include <pthread.h>
#include <unistd.h>

namespace bthread {

Expand Down Expand Up @@ -151,7 +152,7 @@ void TaskTracer::set_status(TaskStatus s, TaskMeta* m) {
m->status = s;
}
if (TASK_STATUS_CREATED == s) {
m->worker_tid = -1;
m->worker_tid = pthread_t{};
}
}

Expand All @@ -161,7 +162,7 @@ void TaskTracer::set_status(TaskStatus s, TaskMeta* m) {
}
}

void TaskTracer::set_running_status(pid_t worker_tid, TaskMeta* m) {
void TaskTracer::set_running_status(pthread_t worker_tid, TaskMeta* m) {
BAIDU_SCOPED_LOCK(m->version_lock);
m->worker_tid = worker_tid;
m->status = TASK_STATUS_RUNNING;
Expand Down Expand Up @@ -230,7 +231,7 @@ TaskTracer::Result TaskTracer::TraceImpl(bthread_t tid) {

BAIDU_SCOPED_LOCK(_mutex);
TaskStatus status;
pid_t worker_tid;
pthread_t worker_tid;
const uint32_t given_version = get_version(tid);
{
BAIDU_SCOPED_LOCK(m->version_lock);
Expand Down Expand Up @@ -368,7 +369,7 @@ void TaskTracer::SignalHandler(int, siginfo_t* info, void* context) {
butil::ignore_result(write(signal_sync->pipe_fds[1], "1", 1));
}

TaskTracer::Result TaskTracer::SignalTrace(pid_t tid) {
TaskTracer::Result TaskTracer::SignalTrace(pthread_t worker_tid) {
// CAUTION:
// https://github.com/gperftools/gperftools/wiki/gperftools'-stacktrace-capturing-methods-and-their-issues#libunwind
// Generally, libunwind promises async-signal-safety for capturing backtraces.
Expand Down Expand Up @@ -403,6 +404,10 @@ TaskTracer::Result TaskTracer::SignalTrace(pid_t tid) {
//
// Therefore, use async-signal-safe absl::DefaultStackUnwinder instead of libunwind.

if (pthread_equal(worker_tid, pthread_self())) {
return Result::MakeErrorResult("Forbid to trace self");
}

// Remove unused SignalSyncs.
auto iter = std::remove_if(
_inuse_signal_syncs.begin(), _inuse_signal_syncs.end(),
Expand All @@ -424,11 +429,11 @@ TaskTracer::Result TaskTracer::SignalTrace(pid_t tid) {
sigval value{};
value.sival_ptr = signal_sync.get();
size_t sigqueue_try = 0;

Copilot AI Jul 25, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding a comment explaining why rt_tgsigqueueinfo is used instead of sigqueue, since this is the core fix for the bug described in the PR title.

Suggested change
size_t sigqueue_try = 0;
size_t sigqueue_try = 0;
// Use rt_tgsigqueueinfo instead of sigqueue to send a signal to a specific thread
// (worker_tid) within the process. The standard sigqueue function does not support
// targeting individual threads, which is essential for this implementation.

Copilot uses AI. Check for mistakes.
while (sigqueue(tid, SIGURG, value) != 0) {
while (pthread_sigqueue(worker_tid, SIGURG, value) != 0) {
if (errno != EAGAIN || sigqueue_try++ >= 3) {
// Remove reference for SignalHandler.
signal_sync->RemoveRefManually();
return Result::MakeErrorResult("Fail to sigqueue: %s, tid: %d", berror(), tid);
return Result::MakeErrorResult("Fail to pthread_sigqueue: %s", berror());
}
}
_inuse_signal_syncs.push_back(signal_sync);
Expand Down
20 changes: 10 additions & 10 deletions src/bthread/task_tracer.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@

#ifdef BRPC_BTHREAD_TRACER

#include <signal.h>
#include <vector>
#include <libunwind.h>
#include "butil/synchronization/condition_variable.h"
#include "bthread/mutex.h"
#include "bthread/task_meta.h"
#include "butil/intrusive_ptr.hpp"
#include "butil/strings/safe_sprintf.h"
#include "butil/shared_object.h"
#include "bthread/task_meta.h"
#include "bthread/mutex.h"
#include "butil/strings/safe_sprintf.h"
#include "butil/synchronization/condition_variable.h"
#include <libunwind.h>
#include <signal.h>
#include <vector>

namespace bthread {

Expand All @@ -39,10 +39,10 @@ class TaskTracer {
bool Init();
// Set the status to `s'.
void set_status(TaskStatus s, TaskMeta* meta);
static void set_running_status(pid_t worker_tid, TaskMeta* meta);
static void set_running_status(pthread_t worker_tid, TaskMeta* meta);
static bool set_end_status_unsafe(TaskMeta* m);

// Trace the bthread of `tid'.
// Trace the bthread of `tid`.
std::string Trace(bthread_t tid);
void Trace(std::ostream& os, bthread_t tid);

Expand Down Expand Up @@ -103,7 +103,7 @@ class TaskTracer {

static bool RegisterSignalHandler();
static void SignalHandler(int sig, siginfo_t* info, void* context);
Result SignalTrace(pid_t worker_tid);
Result SignalTrace(pthread_t worker_tid);

// Make sure only one bthread is traced at a time.
Mutex _trace_request_mutex;
Expand Down
Loading