cutter icon indicating copy to clipboard operation
cutter copied to clipboard

Breakpoints don't work with multiple threads

Open karliss opened this issue 5 years ago • 9 comments

Environment information

  • Operating System: Linux
  • Cutter version: 59af77fb7272765b3d50e0af6067e036e4d4e93b
  • File format: ELF

Describe the bug

Triggering breakpoint with secondary thread causes UI to freeze.

To Reproduce

Steps to reproduce the behavior:

  1. compile test program g++ -o a a.cpp -pthread
  2. open test executable
  3. start debugging
  4. insert breakpoint in thread_func
  5. continue
  6. observe main thread gets stopped
  7. try switching to one of secondary threads - observe that gui freezes

Expected behavior

GUI doesn't freeze.

When breakpoint gets triggered by a thread cutter switches to thread that triggered it.

Additional context

Test program

#include <thread>
#include <iostream>

void thread_func() {
    int64_t counter = 0;
    while(true) {
        ++counter;
        if (counter%10000000000LL == 0) {
            std::cout << counter << "\n";
        }
    }
}

 int main() {
    std::thread t1(thread_func);
    std::thread t2(thread_func);
    t1.join();
    t2.join();
}

karliss avatar Dec 15 '19 20:12 karliss

Looked at the stacktraces. One thread is stuck in linux_select -> linux_stop_thread waiting for thread to stop. Not sure what happens to Qt event loop. My initial guess was one of the GUI updates is waiting for r2 lock which is blocked by task doing waitpid but I didn't saw any threads with Qt event loop in stacktrace.

karliss avatar Dec 16 '19 17:12 karliss

Repeating it second time I saw what I expected GUI trying to refresh information waiting on r2 lock, task thread waiting for debugged thread to stop. Can a thread be stopped if it is already stopped due to other reasons?

karliss avatar Dec 16 '19 18:12 karliss

Small note: tested and this doesn't happen in windows.

Thanks for debugging and trying to reproduce the issue!

Can a thread be stopped if it is already stopped due to other reasons?

You are supposed to be able to queue multiple signals. You'll have SIGSTOP and SIGTRAP waiting for the debugging process to handle. Not sure why it doesn't receive any one of those..

linux_select

So it does try to switch to the breakpoint. I remember this working while we were working on the ThreadsWidget so it must be some regression due to attach changes.

yossizap avatar Dec 16 '19 18:12 yossizap

Yeah, this is probably specific to Linux native debug backend.

karliss avatar Dec 16 '19 19:12 karliss

I just noticed dbg.threads: Stop all threads when debugger breaks (see dbg.forks) option which is false by default. I wonder how can it work reliably without stopping all threads when breakpoint is hit and user/debugger is poking process memory and changing breakpoints while some of the threads are running.

karliss avatar Dec 23 '19 12:12 karliss

Didn't notice any difference after enabling it but there might be more than one problem.

karliss avatar Dec 23 '19 12:12 karliss

I wonder how can it work reliably without stopping all threads when breakpoint is hit

Yep, and dbg.threads is only in use in windows debug. Another issue is that unless dbg.trace_clone is enabled the debugger won't even attach after clone and configure a new thread. I started working on a refactor before the release and didn't have time since, should finish it by this weekend.

yossizap avatar Dec 23 '19 14:12 yossizap

Retest after radareorg/radare2#17251

karliss avatar Jul 10 '20 12:07 karliss

Retested this with the latest Cutter on Linux. GUI doesn't freeze anymore but the debugging process never stopped and reached a breakpoint.

XVilka avatar Jun 21 '22 12:06 XVilka