Developer forums (C::B DEVELOPMENT STRICTLY!) > Development

debugger stop button on Linux console pgm crashes CB

<< < (2/4) > >>

Pecan:
The line "    m_State.StopDriver();" in debuggergdb.cpp is causing a crash in linux when the user hits the stop debugger button. It clears m_State.m_pDriver which is still being used by the events:

EVT_PIPEDPROCESS_STDOUT(idGDBProcess, DebuggerGDB::OnGDBOutput)
EVT_PIPEDPROCESS_STDERR(idGDBProcess, DebuggerGDB::OnGDBError)


 


--- Code: ---
void DebuggerGDB::OnGDBTerminated(wxCommandEvent& event)
{
    m_PidToAttach = 0;

    m_TimerPollDebugger.Stop();
    m_LastExitCode = event.GetInt();
    //the process deletes itself
//    m_pProcess = 0L;

    ClearActiveMarkFromAllEditors();
    m_State.StopDriver();
    Manager::Get()->GetMessageManager()->Log(m_PageIndex, _("Debugger finished with status %d"), m_LastExitCode);

    if (m_NoDebugInfo)
    {
        cbMessageBox(_("This project/target has no debugging info."
                        "Please change this in the project's build options and retry..."),
                        _("Error"),
                        wxICON_STOP);
    }

    // switch to the user-defined layout when finished debugging
    DoSwitchLayout(_T("layout_end"));
}


--- End code ---

The crashes stop when that line is commented out. But it causes OnProjectActivated and OnProjectClosed to think the project is still in debugging mode.

Pecan:
I cannot understand this situation. Look at the last line.
The debugger states that "m_State.HasDriver()" is false, yet the call was make anyway. What the hell ???


--- Code: ---Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread -1231042896 (LWP 5287)]
0xb4641020 in DebuggerDriver::CurrentCommand (this=0x8bf1db8)
    at /home/pecan/devel/trunk/src/plugins/debuggergdb/debuggerdriver.cpp:98
98          return m_DCmds.GetCount() ? m_DCmds[0] : 0;
(gdb) bt
#0  0xb4641020 in DebuggerDriver::CurrentCommand (this=0x8bf1db8)
    at /home/pecan/devel/trunk/src/plugins/debuggergdb/debuggerdriver.cpp:98
#1  0xb4666b37 in GDB_driver::ParseOutput (this=0x8bf1db8, output=@0xbf91780c)
    at /home/pecan/devel/trunk/src/plugins/debuggergdb/gdb_driver.cpp:620
#2  0xb464484d in DebuggerGDB::ParseOutput (this=0x8a17918, output=@0xbf91780c)
    at /home/pecan/devel/trunk/src/plugins/debuggergdb/debuggergdb.cpp:1543
#3  0xb4646c8c in DebuggerGDB::OnGDBOutput (this=0x8a17918, event=@0xb3c005c4)
    at /home/pecan/devel/trunk/src/plugins/debuggergdb/debuggergdb.cpp:1918
#4  0xb792d655 in wxAppConsole::HandleEvent ()
   from /usr/lib/libwx_baseu-2.6.so.0
#5  0xb79bcb52 in wxEvtHandler::ProcessEventIfMatches ()
   from /usr/lib/libwx_baseu-2.6.so.0
#6  0xb79bcc9d in wxEventHashTable::HandleEvent ()
   from /usr/lib/libwx_baseu-2.6.so.0
#7  0xb79bce1f in wxEvtHandler::ProcessEvent ()
   from /usr/lib/libwx_baseu-2.6.so.0
#8  0xb79bd2d0 in wxEvtHandler::ProcessPendingEvents ()
   from /usr/lib/libwx_baseu-2.6.so.0
#9  0xb792dbef in wxAppConsole::ProcessPendingEvents ()
   from /usr/lib/libwx_baseu-2.6.so.0
#10 0xb770a4dd in Manager::ProcessPendingEvents () at sdk/manager.cpp:108
#11 0xb77c94cf in SimpleTextLog::AddLog (this=0x8b24490, msg=@0xbf917b9c,
    addNewLine=true) at sdk/simpletextlog.cpp:70
#12 0xb770f001 in MessageManager::Log (this=0x862afa8, id=6, msg=@0xbf917b9c)
    at sdk/messagemanager.cpp:455
#13 0xb4641f8a in DebuggerGDB::DebugLog (this=0x8a17918, msg=@0xbf917b9c)
    at /home/pecan/devel/trunk/src/plugins/debuggergdb/debuggergdb.cpp:566
#14 0xb4666af9 in GDB_driver::ParseOutput (this=0x8bf1db8, output=@0xbf917b9c)
    at /home/pecan/devel/trunk/src/plugins/debuggergdb/gdb_driver.cpp:613
#15 0xb464484d in DebuggerGDB::ParseOutput (this=0x8a17918, output=@0xbf917b9c)
    at /home/pecan/devel/trunk/src/plugins/debuggergdb/debuggergdb.cpp:1543
#16 0xb4646c8c in DebuggerGDB::OnGDBOutput (this=0x8a17918, event=@0xb3c00570)
    at /home/pecan/devel/trunk/src/plugins/debuggergdb/debuggergdb.cpp:1918
#17 0xb792d655 in wxAppConsole::HandleEvent ()
   from /usr/lib/libwx_baseu-2.6.so.0
#18 0xb79bcb52 in wxEvtHandler::ProcessEventIfMatches ()
   from /usr/lib/libwx_baseu-2.6.so.0
#19 0xb79bcc9d in wxEventHashTable::HandleEvent ()
   from /usr/lib/libwx_baseu-2.6.so.0
#20 0xb79bce1f in wxEvtHandler::ProcessEvent ()
   from /usr/lib/libwx_baseu-2.6.so.0
#21 0xb79bd2d0 in wxEvtHandler::ProcessPendingEvents ()
   from /usr/lib/libwx_baseu-2.6.so.0
#22 0xb792dbef in wxAppConsole::ProcessPendingEvents ()
---Type <return> to continue, or q <return> to quit---q
 from /usr/lib/libwx_baseQuit
(gdb) f 3
#3  0xb4646c8c in DebuggerGDB::OnGDBOutput (this=0x8a17918, event=@0xb3c005c4)
    at /home/pecan/devel/trunk/src/plugins/debuggergdb/debuggergdb.cpp:1918
1918    }
(gdb) p m_state
No symbol "m_state" in current context.
(gdb) p m_State
$1 = {m_pPlugin = 0x8a17918, m_pDriver = 0x0,
  m_Watches = {<wxArrayPtrVoid> = {<wxBaseArrayPtrVoid> = {m_nSize = 0,
        m_nCount = 0, m_pItems = 0x0}, <No data fields>}, <No data fields>},
  m_Breakpoints = {<wxBaseArrayPtrVoid> = {m_nSize = 0, m_nCount = 0,
      m_pItems = 0x0}, <No data fields>}, m_BpAutoIndex = 0}
(gdb) f 2
#2  0xb464484d in DebuggerGDB::ParseOutput (this=0x8a17918, output=@0xbf91780c)
    at /home/pecan/devel/trunk/src/plugins/debuggergdb/debuggergdb.cpp:1543
1543            m_State.GetDriver()->ParseOutput(output);
(gdb) p m_State
$2 = {m_pPlugin = 0x8a17918, m_pDriver = 0x0,
  m_Watches = {<wxArrayPtrVoid> = {<wxBaseArrayPtrVoid> = {m_nSize = 0,
        m_nCount = 0, m_pItems = 0x0}, <No data fields>}, <No data fields>},
  m_Breakpoints = {<wxBaseArrayPtrVoid> = {m_nSize = 0, m_nCount = 0,
      m_pItems = 0x0}, <No data fields>}, m_BpAutoIndex = 0}
(gdb) f 1
#1  0xb4666b37 in GDB_driver::ParseOutput (this=0x8bf1db8, output=@0xbf91780c)
    at /home/pecan/devel/trunk/src/plugins/debuggergdb/gdb_driver.cpp:620
620             DebuggerCmd* cmd = CurrentCommand();
(gdb) p m_State
No symbol "m_State" in current context.
(gdb) f
#1  0xb4666b37 in GDB_driver::ParseOutput (this=0x8bf1db8, output=@0xbf91780c)
    at /home/pecan/devel/trunk/src/plugins/debuggergdb/gdb_driver.cpp:620
620             DebuggerCmd* cmd = CurrentCommand();
(gdb) f 0
#0  0xb4641020 in DebuggerDriver::CurrentCommand (this=0x8bf1db8)
    at /home/pecan/devel/trunk/src/plugins/debuggergdb/debuggerdriver.cpp:98
98          return m_DCmds.GetCount() ? m_DCmds[0] : 0;
(gdb) p m_DCmds
$3 = {<wxBaseArrayPtrVoid> = {m_nSize = 16, m_nCount = 1,
    m_pItems = 0x0}, <No data fields>}
(gdb) l
93          RunQueue();
94      }
95
96      DebuggerCmd* DebuggerDriver::CurrentCommand()
97      {
98          return m_DCmds.GetCount() ? m_DCmds[0] : 0;
99      }
100
101     void DebuggerDriver::RunQueue()
102     {
(gdb) up
#1  0xb4666b37 in GDB_driver::ParseOutput (this=0x8bf1db8, output=@0xbf91780c)
    at /home/pecan/devel/trunk/src/plugins/debuggergdb/gdb_driver.cpp:620
620             DebuggerCmd* cmd = CurrentCommand();
(gdb) l
615         int idx = buffer.First(GDB_PROMPT);
616         if (idx != wxNOT_FOUND)
617         {
618             m_ProgramIsStopped = true;
619             m_QueueBusy = false;
620             DebuggerCmd* cmd = CurrentCommand();
621             if (cmd)
622             {
623     //            Log(_T("Command parsing output: ") + buffer.Left(idx));
624                 RemoveTopCommand(false);
(gdb) up
#2  0xb464484d in DebuggerGDB::ParseOutput (this=0x8a17918, output=@0xbf91780c)
    at /home/pecan/devel/trunk/src/plugins/debuggergdb/debuggergdb.cpp:1543
1543            m_State.GetDriver()->ParseOutput(output);
(gdb) p m_state
No symbol "m_state" in current context.
(gdb) p m_State
$4 = {m_pPlugin = 0x8a17918, m_pDriver = 0x0,
  m_Watches = {<wxArrayPtrVoid> = {<wxBaseArrayPtrVoid> = {m_nSize = 0,
        m_nCount = 0, m_pItems = 0x0}, <No data fields>}, <No data fields>},
  m_Breakpoints = {<wxBaseArrayPtrVoid> = {m_nSize = 0, m_nCount = 0,
      m_pItems = 0x0}, <No data fields>}, m_BpAutoIndex = 0}
(gdb) l
1538
1539    void DebuggerGDB::ParseOutput(const wxString& output)
1540    {
1541        if (m_State.HasDriver())
1542        {
1543            m_State.GetDriver()->ParseOutput(output);
1544        }
1545    }
1546
1547    void DebuggerGDB::BringAppToFront()
(gdb) p m_State.HasDriver()
$5 = false
(gdb)


--- End code ---

Pecan:
In the pre-waking hours this morning it finally dawned on me what is going on here.

debuggerGDB m_State variables are being manipulated from two different threads without a critical section.

The message queues and mState.m_pDriver (especially) are being changed while m_pProcess (the PipedProcess) functions:

EVT_PIPEDPROCESS_STDOUT(idGDBProcess, DebuggerGDB::OnGDBOutput)
EVT_PIPEDPROCESS_STDERR(idGDBProcess, DebuggerGDB::OnGDBError)

are also changing the queues and depending on the variables pointed to by m_pDriver, which is being cleared by DebuggerGDB.{Stop()|Cleanup()|StopDriver()}

This explains the crashes and the weird freezes and hangs I often get while debugging, because m_pProcess(PipedProcess) is adding messages while DebuggerGDB and gdb_Driver are removing 'em asynchronously.

This is why the message queue shows it has x number of msgs, but that m_pItems\[x\] are empty.

@Yiannis
Do you want to fix this, or would you care for me to try and find a place to add a wxCriticalSection and see how it goes.

artoj:
Excellent work, thanks Pecan! :)

mandrav:

--- Quote from: pecan ---@Yiannis
Do you want to fix this, or would you care for me to try and find a place to add a wxCriticalSection and see how it goes.
--- End quote ---

Although I have failed to reproduce a crash, I will have a look.
And no threads are used in the debugger plugin AFAIR...

Navigation

[0] Message Index

[#] Next page

[*] Previous page

Go to full version