Skip to content

Commit f5b0e57

Browse files
committed
Bugfix: SignalTrace mode has memory access problem (#3031)
* Bugfix: SignalTrace mode has memory access problem
1 parent bea48d7 commit f5b0e57

2 files changed

Lines changed: 22 additions & 16 deletions

File tree

src/bthread/task_tracer.cpp

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -356,15 +356,18 @@ void TaskTracer::SignalHandler(int, siginfo_t* info, void* context) {
356356
// Ref has been taken before the signal is sent, so no need to add ref here.
357357
butil::intrusive_ptr<SignalSync> signal_sync(
358358
static_cast<SignalSync*>(info->si_value.sival_ptr), false);
359-
if (NULL == signal_sync || NULL == signal_sync->result) {
359+
if (NULL == signal_sync) {
360360
// The signal is not from Tracer, such as TaskControl, do nothing.
361361
return;
362362
}
363-
Result* result = signal_sync->result;
363+
void *pcs[Result::MAX_TRACE_NUM];
364364
// Skip the first frame, which is the signal handler itself.
365-
result->frame_count = absl::DefaultStackUnwinder(&result->ips[0], NULL,
366-
arraysize(result->ips),
367-
1, context, NULL);
365+
int depth = absl::DefaultStackUnwinder(pcs, NULL, arraysize(pcs), 1,
366+
context, NULL);
367+
signal_sync->pcs.reserve(depth);
368+
for (int i = 0; i < depth; ++i) {
369+
signal_sync->pcs.push_back(pcs[i]);
370+
}
368371
// write() is async-signal-safe.
369372
// Don't care about the return value.
370373
butil::ignore_result(write(signal_sync->pipe_fds[1], "1", 1));
@@ -415,11 +418,9 @@ TaskTracer::Result TaskTracer::SignalTrace(pid_t tid) {
415418

416419
// Each signal trace has an independent SignalSync to
417420
// prevent the previous SignalHandler from affecting the new SignalTrace.
418-
Result result;
419-
butil::intrusive_ptr<SignalSync> signal_sync(new SignalSync(&result));
421+
butil::intrusive_ptr<SignalSync> signal_sync(new SignalSync());
420422
if (!signal_sync->Init()) {
421-
result.SetError("Fail to init SignalSync");
422-
return result;
423+
return Result::MakeErrorResult("Fail to init SignalSync");
423424
}
424425

425426
// Add reference for SignalHandler.
@@ -432,8 +433,7 @@ TaskTracer::Result TaskTracer::SignalTrace(pid_t tid) {
432433
if (errno != EAGAIN || sigqueue_try++ >= 3) {
433434
// Remove reference for SignalHandler.
434435
signal_sync->RemoveRefManually();
435-
result.SetError("Fail to sigqueue: %s", berror());
436-
return result;
436+
return Result::MakeErrorResult("Fail to sigqueue: %s, tid: %d", berror(), tid);
437437
}
438438
}
439439
_inuse_signal_syncs.push_back(signal_sync);
@@ -450,8 +450,7 @@ TaskTracer::Result TaskTracer::SignalTrace(pid_t tid) {
450450
if (FLAGS_signal_trace_timeout_ms > 0) {
451451
timer.stop();
452452
if (timer.m_elapsed() >= FLAGS_signal_trace_timeout_ms) {
453-
result.SetError("Timeout exceed %dms", FLAGS_signal_trace_timeout_ms);
454-
break;
453+
return Result::MakeErrorResult("Timeout exceed %dms", FLAGS_signal_trace_timeout_ms);
455454
}
456455
timeout = (int64_t)FLAGS_signal_trace_timeout_ms - timer.m_elapsed();
457456
}
@@ -462,10 +461,17 @@ TaskTracer::Result TaskTracer::SignalTrace(pid_t tid) {
462461
if (EINTR == errno) {
463462
continue;
464463
}
465-
result.SetError("Fail to poll: %s", berror());
464+
return Result::MakeErrorResult("Fail to poll: %s", berror());
466465
}
467466
break;
468467
}
468+
469+
Result result;
470+
result.frame_count = signal_sync->pcs.size();
471+
for(size_t i = 0; i < result.frame_count; ++i) {
472+
result.ips[i] = signal_sync->pcs[i];
473+
}
474+
469475
return result;
470476
}
471477

src/bthread/task_tracer.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,12 @@ class TaskTracer {
8787

8888
// For signal trace.
8989
struct SignalSync : public butil::SharedObject {
90-
explicit SignalSync(Result* result) : result(result) {}
90+
explicit SignalSync() {}
9191
~SignalSync() override;
9292
bool Init();
9393

9494
int pipe_fds[2]{-1, -1};
95-
Result* result{NULL};
95+
std::vector<void *> pcs;
9696
};
9797

9898
static TaskStatus WaitForJumping(TaskMeta* m);

0 commit comments

Comments
 (0)