Copilot commented on code in PR #3019:
URL: https://github.com/apache/brpc/pull/3019#discussion_r2188406550


##########
test/bthread_unittest.cpp:
##########
@@ -639,22 +638,18 @@ void spin_and_log_trace() {
         while (!start) {
             usleep(10 * 1000);
         }
-        bthread::FLAGS_enable_fast_unwind = false;
+
         std::string st1 = bthread::stack_trace(th);
         LOG(INFO) << "spin_and_log stack trace:\n" << st1;
+        ok = st1.find("spin_and_log") != std::string::npos;
 
-        bthread::FLAGS_enable_fast_unwind = true;
-        std::string st2 = bthread::stack_trace(th);
-        LOG(INFO) << "fast_unwind spin_and_log stack trace:\n" << st2;
         stop = true;
         ASSERT_EQ(0, bthread_join(th, NULL));
 
-        std::string st3 = bthread::stack_trace(th);
-        LOG(INFO) << "ended bthread stack trace:\n" << st3;
-        ASSERT_NE(std::string::npos, st3.find("not exist now"));
+        std::string st2 = bthread::stack_trace(th);
+        LOG(INFO) << "ended bthread stack trace:\n" << st2;
+        ASSERT_NE(std::string::npos, st2.find("not exist now"));
 

Review Comment:
   The `ok` variable only checks `st1` but never includes `st2`. If `st2` fails 
to contain "not exist now", the assertion will fire but the loop break will 
still depend solely on `st1`. Consider updating `ok` to require both traces 
succeed before breaking.



##########
src/bthread/task_tracer.cpp:
##########
@@ -472,99 +403,69 @@ TaskTracer::Result TaskTracer::SignalTrace(pid_t tid) {
     // #19 0x00007f0d390088dc in __cxa_throw () from 
/lib/x86_64-linux-gnu/libstdc++.so.6
     // #20 0x00007f0d3b5b2245 in __cxxabiv1::__cxa_throw 
(thrownException=0x7f0d114ea8c0, type=0x7f0d3d6dd830 <typeinfo for 
rockset::GRPCError>, destructor=<optimized out>) at 
/src/folly/folly/experimental/exception_tracer/ExceptionTracerLib.cpp:107
     //
-    // Therefore, we do not capture backtracks in the signal handler to avoid 
mutex
-    // reentry and deadlock. Instead, we capture backtracks in this function 
and
-    // ends the signal handler after capturing backtraces is complete.
-    // Even so, there is still a deadlock problem:
-    // the worker thread is interrupted when during an existing 
dl_iterate_phdr call,
-    // and wait for the capturing backtraces to complete. This function capture
-    // backtracks with dl_iterate_phdr. We introduce a timeout mechanism in 
signal
-    // handler to avoid deadlock.
+    // Therefore, use async-signal-safe absl::DefaultStackUnwinder instead of 
libunwind.
+
+    // Remove unused SignalSyncs.
+    auto iter = std::remove_if(
+        _inuse_signal_syncs.begin(), _inuse_signal_syncs.end(),
+        [](butil::intrusive_ptr<SignalSync>& sync) {
+            return sync->ref_count() == 0;
+    });
+    _inuse_signal_syncs.erase(iter, _inuse_signal_syncs.end());
 
     // Each signal trace has an independent SignalSync to
     // prevent the previous SignalHandler from affecting the new SignalTrace.
-    butil::intrusive_ptr<SignalSync> signal_sync(new SignalSync());
+    Result result;
+    butil::intrusive_ptr<SignalSync> signal_sync(new SignalSync(&result));
     if (!signal_sync->Init()) {
-        return Result::MakeErrorResult("Fail to init SignalSync");
+        result.SetError("Fail to init SignalSync");
+        return result;
     }
+
     // Add reference for SignalHandler.
     signal_sync->AddRefManually();
 
-    union sigval value{};
+    sigval value{};
     value.sival_ptr = signal_sync.get();
     size_t sigqueue_try = 0;
     while (sigqueue(tid, SIGURG, value) != 0) {
         if (errno != EAGAIN || sigqueue_try++ >= 3) {
-            return Result::MakeErrorResult("Fail to sigqueue: %s", berror());
+            // Remove reference for SignalHandler.
+            signal_sync->RemoveRefManually();
+            result.MakeErrorResult("Fail to sigqueue: %s", berror());

Review Comment:
   `MakeErrorResult` is a static factory method, not an instance method. This 
line will not compile. Use `result.SetError(...)` or return 
`Result::MakeErrorResult(...)` instead.



##########
src/bthread/task_tracer.cpp:
##########
@@ -362,85 +355,23 @@ void TaskTracer::SignalHandler(int, siginfo_t* info, 
void* context) {
     ErrnoGuard guard;
     butil::intrusive_ptr<SignalSync> signal_sync(
         static_cast<SignalSync*>(info->si_value.sival_ptr));
-    if (NULL == signal_sync) {
+    Result* result = signal_sync->result;
+    if (NULL == signal_sync || NULL == result) {

Review Comment:
   This dereferences `signal_sync` before checking if it is null. Swap the 
null-check and the dereference to avoid potential crashes if `signal_sync` is 
null.
   ```suggestion
       if (NULL == signal_sync) {
           // The signal is not from Tracer, such as TaskControl, do nothing.
           return;
       }
       Result* result = signal_sync->result;
       if (NULL == result) {
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to