void GDB_driver::ParseOutput(const wxString& output)
{
m_Cursor.changed = false;
// Watch for initial debug info and grab the child PID
// this is put here because we need this info even if
// we don't get a prompt back.
// It's "cheap" anyway because the line we 're after is
// the very first line printed by gdb when running our
// program. It then sets the child PID and never enters here
// again because the "want_debug_events" condition below
// is not satisfied anymore...
if (platform::windows && want_debug_events)
{
wxRegEx* re = 0;
if ((m_GDBVersionMajor > 6 || (m_GDBVersionMajor == 6 && m_GDBVersionMinor >= 7)) &&
output.Contains(_T("CREATE_PROCESS_DEBUG_EVENT")))
{
re = &reChildPid2;
}
else if (m_GDBVersionMajor <= 6 && output.Contains(_T("do_initial_child_stuff")))
re = &reChildPid;
else if (m_attachedToProcess)
re = &reAttachedChildPid;
if (re)
{
// got the line with the PID, parse it out:
// e.g.
// gdb: do_initial_child_stuff: process 1392
if (re->Matches(output))
{
wxString pidStr = re->GetMatch(output, 1);
long pid = 0;
pidStr.ToLong(&pid);
SetChildPID(pid);
want_debug_events = false;
disable_debug_events = true;
m_pDBG->Log(wxString::Format(_("Child process PID: %d"), pid));
}
}
}
else if (!platform::windows && m_ChildPID == 0)
{
if (reChildPid3.Matches(output)) // [Switching to Thread -1234655568 (LWP 18590)]
{
wxString pidStr = reChildPid3.GetMatch(output, 1);
long pid = 0;
pidStr.ToLong(&pid);
SetChildPID(pid);
m_pDBG->Log(wxString::Format(_("Child process PID: %d"), pid));
}
}
if (!want_debug_events &&
(output.StartsWith(_T("gdb: ")) ||
output.StartsWith(_T("Warning: ")) ||
output.StartsWith(_T("ContinueDebugEvent "))))
{
return;
}
static wxString buffer;
buffer << output << _T('\n');
m_pDBG->DebugLog(output);
int idx = buffer.First(GDB_PROMPT);
if (idx == wxNOT_FOUND)
{
// don't uncomment the following line
// m_ProgramIsStopped is set to false in DebuggerDriver::RunQueue()
// m_ProgramIsStopped = false;
return; // come back later
}
if (disable_debug_events)
{
// we don't want debug events anymore (we got the pid)
QueueCommand(new DebuggerCmd(this, _T("set debugevents off")));
disable_debug_events = false;
}
Debugger name and version: GNU gdb (GDB) 7.4.50.20120331-cvs
[debug]>>>>>>cb_gdb:
[debug]> set width 0
[debug]>>>>>>cb_gdb:
[debug]> set height 0
[debug]>>>>>>cb_gdb:
[debug]> set breakpoint pending on
[debug]>>>>>>cb_gdb:
[debug]> set print asm-demangle on
[debug]>>>>>>cb_gdb:
[debug]> set unwindonsignal on
[debug]>>>>>>cb_gdb:
[debug]> set print elements 0
[debug]>>>>>>cb_gdb:
[debug]> set debugevents on
[debug]>>>>>>cb_gdb:
[debug]> set disassembly-flavor att
[debug]>>>>>>cb_gdb:
[debug]> catch throw
[debug]Catchpoint 1 (throw)
[debug]>>>>>>cb_gdb:
[debug]> source E:\code\gcc\PCXMinGW463\\bin\my.gdb
[debug]>>>>>>cb_gdb:
[debug]> directory E:/code/cb/test_code/IsAlpha/
[debug]Source directories searched: E:/code/cb/test_code/IsAlpha;$cdir;$cwd
[debug]>>>>>>cb_gdb:
[debug]> break "E:/code/cb/test_code/IsAlpha/IsAlphaMain.cpp:114"
[debug]Breakpoint 2 at 0x401f5c: file E:\code\cb\test_code\IsAlpha\IsAlphaMain.cpp, line 114.
[debug]>>>>>>cb_gdb:
[debug]> break "E:/code/cb/test_code/IsAlpha/IsAlphaMain.cpp:106"
[debug]Breakpoint 3 at 0x401e6b: file E:\code\cb\test_code\IsAlpha\IsAlphaMain.cpp, line 106.
[debug]>>>>>>cb_gdb:
[debug]> run
[debug]Starting program: E:\code\cb\test_code\IsAlpha\bin\Debug\IsAlpha.exe
[debug]gdb: windows_init_thread_list
Child process PID: 2684
[debug][New Thread 2684.0xf40]
[debug]Breakpoint 3, IsAlphaFrame::OnAbout (this=0xb66da0, event=...) at E:\code\cb\test_code\IsAlpha\IsAlphaMain.cpp:106
[debug]E:\code\cb\test_code\IsAlpha\IsAlphaMain.cpp:106:3032:beg:0x401e6b
[debug]>>>>>>cb_gdb:
At E:\code\cb\test_code\IsAlpha\IsAlphaMain.cpp:106
[debug]> set debugevents off
[debug]>>>>>>cb_gdb:
2, there are some message "[New Thread 2684.0xf40]", and this 2684 is just the PID, so can we simplify use this info to get PID?If this also works with older, but wide spread debuggers (6.8) and also in other cases like attaching to a process for example - why not?
I will test 6.8 version and give feedback.2, there are some message "[New Thread 2684.0xf40]", and this 2684 is just the PID, so can we simplify use this info to get PID?If this also works with older, but wide spread debuggers ( 6.8 ) and also in other cases like attaching to a process for example - why not?
[debug]gdb: win32_init_thread_list
Child process PID: 1748
[debug][New thread 1748.0x1300]
Did you also test it with non-threaded application (simple hello world example should do it) ?My original test was a wxWidgets app(single thread), now I test a single thread hello world console app, both of them show the correct message that I needed.
I don't get any such message here on linux in this case.If you look at the original post's code snippet, you can see
else if (!platform::windows && m_ChildPID == 0)
{
if (reChildPid3.Matches(output)) // [Switching to Thread -1234655568 (LWP 18590)]
{
wxString pidStr = reChildPid3.GetMatch(output, 1);
long pid = 0;
pidStr.ToLong(&pid);
SetChildPID(pid);
m_pDBG->Log(wxString::Format(_("Child process PID: %d"), pid));
}
}
// [Switching to Thread -1234655568 (LWP 18590)]
// [New Thread -1234655568 (LWP 18590)]
static wxRegEx reChildPid3(_T("Thread[ \t]+[xA-Fa-f0-9-]+[ \t]+\\(LWP ([0-9]+)\\)]"));
[New thread 1748.0x1300]
ollydbg: Patches welcome, but please wait for 2-3 days until we do the merge...Ok, I put this in my TODO list. Also, the patch should be only touch the Windows side (not Linux side).
And Jens is correct because gdb doesn't always print the threading notifications, but if it works on windows I have nothing against it.
Index: gdb_driver.cpp
===================================================================
--- gdb_driver.cpp (revision 7929)
+++ gdb_driver.cpp (working copy)
@@ -75,6 +75,7 @@
// [Switching to Thread -1234655568 (LWP 18590)]
// [New Thread -1234655568 (LWP 18590)]
static wxRegEx reChildPid3(_T("Thread[ \t]+[xA-Fa-f0-9-]+[ \t]+\\(LWP ([0-9]+)\\)]"));
+static wxRegEx reChildPid4(_T("\\[New [tT]hread[ \t]+[0-9]+\\.[xA-Fa-f0-9-]+\\]"));
static wxRegEx reAttachedChildPid(wxT("Attaching to process ([0-9]+)"));
static wxRegEx reInferiorExited(wxT("^\\[Inferior[ \\t].+[ \\t]exited normally\\]$"), wxRE_EXTENDED);
@@ -92,8 +93,6 @@
m_IsStarted(false),
m_GDBVersionMajor(0),
m_GDBVersionMinor(0),
- want_debug_events(true),
- disable_debug_events(false),
m_attachedToProcess(false),
m_catchThrowIndex(-1)
{
@@ -243,19 +242,6 @@
// disalbe result string truncations
QueueCommand(new DebuggerCmd(this, wxString::Format(wxT("set print elements %d"), printElements)));
- // want debug events
- if(platform::windows)
- {
- QueueCommand(new DebuggerCmd(this, _T("set debugevents on")));
- want_debug_events = true;
- disable_debug_events = false;
- }
- else
- {
- want_debug_events = false;
- disable_debug_events = false;
- }
-
if (platform::windows && isConsole)
QueueCommand(new DebuggerCmd(this, _T("set new-console on")));
@@ -750,43 +736,18 @@
{
m_Cursor.changed = false;
- // Watch for initial debug info and grab the child PID
- // this is put here because we need this info even if
- // we don't get a prompt back.
- // It's "cheap" anyway because the line we 're after is
- // the very first line printed by gdb when running our
- // program. It then sets the child PID and never enters here
- // again because the "want_debug_events" condition below
- // is not satisfied anymore...
- if (platform::windows && want_debug_events)
+ if (platform::windows && m_ChildPID == 0)
{
- wxRegEx* re = 0;
- if ((m_GDBVersionMajor > 6 || (m_GDBVersionMajor == 6 && m_GDBVersionMinor >= 7)) &&
- output.Contains(_T("CREATE_PROCESS_DEBUG_EVENT")))
+ if (reChildPid4.Matches(output)) // [New Thread 2684.0xf40] or [New thread 2684.0xf40]
{
- re = &reChildPid2;
+ wxString pidStr = reChildPid4.GetMatch(output, 0);
+ pidStr = pidStr.BeforeFirst(_T('.')); //[New Thread 2684.0xf40] -> [New Thread 2684
+ pidStr = pidStr.AfterFirst(_T('d')); //[New Thread 2684 -> 2684
+ long pid = 0;
+ pidStr.ToLong(&pid);
+ SetChildPID(pid);
+ m_pDBG->Log(wxString::Format(_("Child process PID: %d"), pid));
}
- else if (m_GDBVersionMajor <= 6 && output.Contains(_T("do_initial_child_stuff")))
- re = &reChildPid;
- else if (m_attachedToProcess)
- re = &reAttachedChildPid;
-
- if (re)
- {
- // got the line with the PID, parse it out:
- // e.g.
- // gdb: do_initial_child_stuff: process 1392
- if (re->Matches(output))
- {
- wxString pidStr = re->GetMatch(output, 1);
- long pid = 0;
- pidStr.ToLong(&pid);
- SetChildPID(pid);
- want_debug_events = false;
- disable_debug_events = true;
- m_pDBG->Log(wxString::Format(_("Child process PID: %d"), pid));
- }
- }
}
else if (!platform::windows && m_ChildPID == 0)
{
@@ -800,10 +761,9 @@
}
}
- if (!want_debug_events &&
- (output.StartsWith(_T("gdb: ")) ||
- output.StartsWith(_T("Warning: ")) ||
- output.StartsWith(_T("ContinueDebugEvent "))))
+ if ( output.StartsWith(_T("gdb: "))
+ ||output.StartsWith(_T("Warning: "))
+ ||output.StartsWith(_T("ContinueDebugEvent ")))
{
return;
}
@@ -822,13 +782,6 @@
return; // come back later
}
- if (disable_debug_events)
- {
- // we don't want debug events anymore (we got the pid)
- QueueCommand(new DebuggerCmd(this, _T("set debugevents off")));
- disable_debug_events = false;
- }
-
m_QueueBusy = false;
int changeFrameAddr = 0 ;
DebuggerCmd* cmd = CurrentCommand();
Index: gdb_driver.h
===================================================================
--- gdb_driver.h (revision 7929)
+++ gdb_driver.h (working copy)
@@ -127,8 +127,6 @@
long m_GDBVersionMinor;
wxString flavour;
- bool want_debug_events;
- bool disable_debug_events;
bool m_attachedToProcess;
// for remote debugging usage (mainly)
You're very bold in removing the debug events code.:)
Are you really really sure that gdb will print these messages for every program you start?I'm sure at least Windows GDB 6.8-7.4.
What about remote debugging, can you try it?I have never used remote debugging. I will try it under WinXP.
gdb\windows-nat.c
#define DEBUG_EVENTS(x) if (debug_events) printf_unfiltered x
case CREATE_PROCESS_DEBUG_EVENT:
DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
(unsigned) current_event.dwProcessId,
(unsigned) current_event.dwThreadId,
"CREATE_PROCESS_DEBUG_EVENT"));
CloseHandle (current_event.u.CreateProcessInfo.hFile);
if (++saw_create != 1)
break;
[New Thread 2684.0xf40]
struct thread_info *
add_thread_with_info (ptid_t ptid, struct private_thread_info *private)
{
struct thread_info *result = add_thread_silent (ptid);
result->private = private;
if (print_thread_events)
printf_unfiltered (_("[New %s]\n"), target_pid_to_str (ptid));
annotate_new_thread ();
return result;
}
/* Convert pid to printable format. */
static char *
windows_pid_to_str (struct target_ops *ops, ptid_t ptid)
{
static char buf[80];
if (ptid_get_tid (ptid) != 0)
{
snprintf (buf, sizeof (buf), "Thread %d.0x%lx",
ptid_get_pid (ptid), ptid_get_tid (ptid));
return buf;
}
return normal_pid_to_str (ptid);
}
/* Print notices when new threads are attached and detached. */
int print_thread_events = 1;
static void
show_print_thread_events (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
fprintf_filtered (file,
_("Printing of thread events is %s.\n"),
value);
}
This means: the value print_thread_events is enabled by default. That's why we get such message under both Windows and Linux.This is not 100% true for Linux and some (if not all) versions of gdb-7.xx, if you program doesn't use pthreads, it doesn't print it.
Ok, I'm not quite familiar with Linux, so I may wrong.This means: the value print_thread_events is enabled by default. That's why we get such message under both Windows and Linux.This is not 100% true for Linux and some (if not all) versions of gdb-7.xx, if you program doesn't use pthreads, it doesn't print it.
E:\code\gdb\gdbservertest>gdbserver localhost:777 IsAlphaConsole.exe
Process IsAlphaConsole.exe created; pid = 1804
Listening on port 777
Remote debugging from host 127.0.0.1
48 is a digit
49 is a digit
50 is a digit
51 is a digit
52 is a digit
53 is a digit
54 is a digit
55 is a digit
56 is a digit
57 is a digit
178 is a digit
179 is a digit
185 is a digit
E:\code\gdb\gdbbin>gdb IsAlphaConsole.exe
GNU gdb (GDB) 7.4.50.20120331-cvs
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "mingw32".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from E:\code\gdb\gdbbin\IsAlphaConsole.exe...done.
(gdb) target remote localhost:777
Remote debugging using localhost:777
0x7c90120f in ntdll!DbgUiConnectToDbg () from C:\WINDOWS\system32\ntdll.dll
(gdb) b main
Breakpoint 1 at 0x4016ee: file E:\code\cb\test_code\IsAlphaConsole\main.cpp, lin
e 10.
(gdb) b main.cpp:15
Breakpoint 2 at 0x401753: file E:\code\cb\test_code\IsAlphaConsole\main.cpp, lin
e 15.
(gdb) continue
Continuing.
Breakpoint 1, main () at E:\code\cb\test_code\IsAlphaConsole\main.cpp:10
10 for (i = 0; i < 500; ++i)
(gdb) c
Continuing.
Breakpoint 2, main () at E:\code\cb\test_code\IsAlphaConsole\main.cpp:16
16 for (i = 0; i < 500; ++i)
(gdb)
Process IsAlphaConsole.exe created; pid = 1804
E:\code\gdb\gdbbin>gdb IsAlphaConsole.exe
GNU gdb (GDB) 7.4.50.20120331-cvs
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "mingw32".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from E:\code\gdb\gdbbin\IsAlphaConsole.exe...done.
(gdb) set debugevents on
(gdb) target remote localhost:777
Remote debugging using localhost:777
0x7c90120f in ntdll!DbgUiConnectToDbg () from C:\WINDOWS\system32\ntdll.dll
(gdb) b main
Breakpoint 1 at 0x4016ee: file E:\code\cb\test_code\IsAlphaConsole\main.cpp, lin
e 10.
(gdb) b main.cpp:15
Breakpoint 2 at 0x401753: file E:\code\cb\test_code\IsAlphaConsole\main.cpp, lin
e 15.
(gdb) c
Continuing.
Breakpoint 1, main () at E:\code\cb\test_code\IsAlphaConsole\main.cpp:10
10 for (i = 0; i < 500; ++i)
(gdb) c
Continuing.
Morten: Can you do some testing of this patch? If I remember correctly you had some debugevent related problems, so this could be your fix. :)...which patch? The one applied in trunk already?
ollydbg: Is there a chance to try your patch in a 64bit windows with a 64bit executable?Sorry, I do not have a 64bit Windows system nor a 64bit gdb.
[...]
[debug]>>>>>>cb_gdb:
[debug]> run
[debug]Starting program: /home/gokul/Documents/Projects/CodeBlocks/src/devel/codeblocks --debug-log --multiple-instance -ns -ni -v -p debug
[debug][Thread debugging using libthread_db enabled]
[debug]Using host libthread_db library "/lib/i386-linux-gnu/libthread_db.so.1".
Child process PID: 14736
[debug][New Thread 0xb5565b40 (LWP 14736)]
[debug][New Thread 0xb4d64b40 (LWP 14737)]
[debug][New Thread 0xb4563b40 (LWP 14738)]
[debug][New Thread 0xb3b0db40 (LWP 14739)]
[debug][New Thread 0xb330cb40 (LWP 14740)]
[debug][New Thread 0xb1966b40 (LWP 14747)]
[debug][New Thread 0xb0fcdb40 (LWP 14801)]
[debug][New Thread 0xb076db40 (LWP 14802)]
[debug][New Thread 0xafec0b40 (LWP 14803)]
[debug][Thread 0xafec0b40 (LWP 14803) exited]
[debug][Thread 0xb0fcdb40 (LWP 14801) exited]
[debug][Thread 0xb076db40 (LWP 14802) exited]
[debug][Thread 0xb1966b40 (LWP 14747) exited]
[debug]Starting Code::Blocks svn build rev 10703 Jan 29 2016, 03:07:41 - wx2.8.12 (Linux, unicode) - 32 bit
[debug][Thread 0xb4563b40 (LWP 14738) exited]
[debug][Thread 0xb4d64b40 (LWP 14737) exited]
[debug][Thread 0xb5565b40 (LWP 14736) exited]
[debug][Thread 0xb330cb40 (LWP 14740) exited]
[debug][Thread 0xb3b0db40 (LWP 14739) exited]
[debug][Inferior 1 (process 14101) exited normally]
[debug]>>>>>>cb_gdb:
[Inferior 1 (process 14101) exited normally]
[debug]> quit
Debugger finished with status 0
From 9f668e2611366fde9e9ee3a8bd17f553bafd30fb Mon Sep 17 00:00:00 2001
From: huki <gk7huki@gmail.com>
Date: Sat, 30 Jan 2016 02:51:50 +0530
Subject: [PATCH] debugger_gdb: [huki] properly get the pid of the inferior
process
We now break on entry and extract the pid through "info program", then continue if needed.
Fixed functionality of m_ManualBreakOnEntry.
Keep old way of catching pid for remoteDebugging.
---
src/plugins/debuggergdb/gdb_commands.h | 3 +++
src/plugins/debuggergdb/gdb_driver.cpp | 10 ++++++++++
2 files changed, 13 insertions(+)
diff --git a/src/plugins/debuggergdb/gdb_commands.h b/src/plugins/debuggergdb/gdb_commands.h
index 3021cd7..5536c84 100644
--- a/src/plugins/debuggergdb/gdb_commands.h
+++ b/src/plugins/debuggergdb/gdb_commands.h
@@ -722,7 +722,10 @@ class GdbCmd_InfoProgram : public DebuggerCmd
{
long pid;
if (pid_str.ToLong(&pid, 10) && pid != 0)
+ {
m_pDriver->SetChildPID(pid);
+ m_pDriver->GetDebugger()->Log(wxString::Format(_("Child process PID: %ld"), pid));
+ }
}
}
};
diff --git a/src/plugins/debuggergdb/gdb_driver.cpp b/src/plugins/debuggergdb/gdb_driver.cpp
index cc1ccd5..b2365c9 100644
--- a/src/plugins/debuggergdb/gdb_driver.cpp
+++ b/src/plugins/debuggergdb/gdb_driver.cpp
@@ -503,6 +503,7 @@ void GDB_driver::Start(bool breakOnEntry)
{
m_ManualBreakOnEntry = !remoteDebugging;
// start the process
+ #if 0
if (breakOnEntry)
QueueCommand(new GdbCmd_Start(this, remoteDebugging ? _T("continue") : _T("start")));
else
@@ -511,6 +512,9 @@ void GDB_driver::Start(bool breakOnEntry)
m_ManualBreakOnEntry=false; // must be reset or gdb does not stop at first breakpoint
QueueCommand(new GdbCmd_Start(this, remoteDebugging ? _T("continue") : _T("run")));
}
+ #endif
+ // NOTE(huki): use "start" command so we can break on entry and run "info program" to get the pid
+ QueueCommand(new GdbCmd_Start(this, remoteDebugging ? _T("continue") : _T("start")));
m_IsStarted = true;
}
} // Start
@@ -778,6 +782,7 @@ void GDB_driver::ParseOutput(const wxString& output)
{
m_Cursor.changed = false;
+ // NOTE(huki): this doesn't work on linux with GDB 7 - the pid given in the output is wrong
if (platform::windows && m_ChildPID == 0)
{
if (reChildPid2.Matches(output)) // [New Thread 2684.0xf40] or [New thread 2684.0xf40]
@@ -1043,6 +1048,7 @@ void GDB_driver::ParseOutput(const wxString& output)
m_needsUpdate = true;
}
}
+ m_ManualBreakOnEntry = false; // must be reset or gdb does not stop at first breakpoint
}
else if (lines[i].StartsWith(wxT("Temporary breakpoint")))
@@ -1177,7 +1183,11 @@ void GDB_driver::HandleMainBreakPoint(const wxRegEx& reBreak_in, wxString line)
QueueCommand(new GdbCmd_InfoProgram(this), DebuggerDriver::High);
if (m_ManualBreakOnEntry && !m_BreakOnEntry)
+ {
+ m_ManualBreakOnEntry = false;
+ m_ProgramIsStopped = true;
Continue();
+ }
else
{
m_ManualBreakOnEntry = false;
--
2.5.0
From b7a560ac02d6e0f2bedab5a6f02b0fd14875be19 Mon Sep 17 00:00:00 2001
From: T Petrov <tpetrov@codeblocks.org>
Date: Sat, 30 Jan 2016 01:13:12 +0200
Subject: [PATCH] * debugger: Find the debuggee's PID using OS APIs when the
parsing the log fails
---
src/include/globals.h | 6 ++
src/plugins/debuggergdb/debuggergdb.cpp | 15 ++++-
src/sdk/globals.cpp | 98 +++++++++++++++++++++++++++++++++
3 files changed, 118 insertions(+), 1 deletion(-)
diff --git a/src/include/globals.h b/src/include/globals.h
index 704924d..b84aafb 100644
--- a/src/include/globals.h
+++ b/src/include/globals.h
@@ -386,4 +386,10 @@ namespace platform
// one thing that's not checked yet are circular symlinks - watch out!
extern DLLIMPORT wxString realpath(const wxString& path);
+/** Return a vector full with the PIDs of the child processes of the parent.
+ * @param[out] children List of PIDs of the child processes of the parent
+ * @param[in] parent PID of the parent process
+ */
+extern DLLIMPORT void cbGetChildrenPIDs(std::vector<int> &children, int parent);
+
#endif // SDK_GLOBALS_H
diff --git a/src/plugins/debuggergdb/debuggergdb.cpp b/src/plugins/debuggergdb/debuggergdb.cpp
index fded9a9..888de11 100644
--- a/src/plugins/debuggergdb/debuggergdb.cpp
+++ b/src/plugins/debuggergdb/debuggergdb.cpp
@@ -1583,7 +1583,20 @@ void DebuggerGDB::DoBreak(bool temporary)
pid = 0;
}
if (pid <= 0)
- pid = m_Pid; // try poking gdb directly
+ {
+ DebugLog(_("Child PID have not been detected!"), Logger::warning);
+ std::vector<int> childrenPIDs;
+ cbGetChildrenPIDs(childrenPIDs, m_Pid);
+ if (!childrenPIDs.empty())
+ {
+ if (childrenPIDs.size()>1)
+ DebugLog(_("Found more than one child processes. Use the PID of the first "), Logger::warning);
+ pid = childrenPIDs.front();
+ m_State.GetDriver()->SetChildPID(pid);
+ }
+ else
+ pid = m_Pid; // try poking gdb directly
+ }
// non-windows gdb can interrupt the running process. yay!
if (pid <= 0) // look out for the "fake" PIDs (killall)
cbMessageBox(_("Unable to stop the debug process!"), _("Error"), wxOK | wxICON_WARNING);
diff --git a/src/sdk/globals.cpp b/src/sdk/globals.cpp
index d44d81d..b2b3e52 100644
--- a/src/sdk/globals.cpp
+++ b/src/sdk/globals.cpp
@@ -1453,3 +1453,101 @@ int cbProjectTreeImages::VirtualFolderIconIndex()
{
return (int)fvsVirtualFolder;
}
+
+namespace
+{
+static int ParseParentPID(const char *line)
+{
+ const char *p = strchr(line, '(');
+ if (!p)
+ return -1;
+ ++p;
+ int open_paren_count = 1;
+ while (*p && open_paren_count > 0)
+ {
+ switch (*p)
+ {
+ case '(':
+ open_paren_count++;
+ break;
+ case ')':
+ open_paren_count--;
+ break;
+ }
+
+ ++p;
+ }
+ if (*p == ' ')
+ ++p;
+ int dummy;
+ int ppid;
+ int count = sscanf(p, "%c %d", (char *) &dummy, &ppid);
+ return count == 2 ? ppid : -1;
+}
+
+} // namespace
+
+void cbGetChildrenPIDs(std::vector<int> &children, int parent)
+{
+#ifndef __WXMSW__
+ const char *c_proc_base = "/proc";
+ DIR *dir = opendir(c_proc_base);
+ if (!dir)
+ return;
+ struct dirent *entry;
+ do
+ {
+ entry = readdir(dir);
+ if (entry)
+ {
+ int pid = atoi(entry->d_name);
+ if (pid != 0)
+ {
+ char filestr[PATH_MAX + 1];
+ snprintf(filestr, PATH_MAX, "%s/%d/stat", c_proc_base, pid);
+ FILE *file = fopen(filestr, "r");
+ if (file)
+ {
+ char line[101];
+ fgets(line, 100, file);
+ fclose(file);
+ int ppid = ParseParentPID(line);
+ if (ppid == parent)
+ children.push_back(pid);
+ }
+ }
+ }
+ } while (entry);
+ closedir(dir);
+#else
+ // get a function pointer to DebugBreakProcess under windows (XP+)
+ typedef HANDLE WINAPI (*CreateToolhelp32SnapshotApiCall)(DWORD dwFlags, DWORD th32ProcessID);
+ static CreateToolhelp32SnapshotApiCall CreateToolhelp32SnapshotFunc = 0;
+ #if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501)
+ if (!CreateToolhelp32SnapshotFunc) {
+ kernelLib = LoadLibrary(TEXT("kernel32.dll"));
+ if (kernelLib)
+ CreateToolhelp32SnapshotFunc = (CreateToolhelp32SnapshotApiCall)GetProcAddress(kernelLib, "CreateToolhelp32Snapshot");
+ }
+ #endif
+
+ if ((CreateToolhelp32SnapshotFunc!=NULL) && (Process32FirstFunc!=NULL) && (Process32NextFunc!=NULL) )
+ {
+ HANDLE snap = CreateToolhelp32SnapshotFunc(TH32CS_SNAPALL,0);
+ if (snap!=INVALID_HANDLE_VALUE)
+ {
+ PROCESSENTRY32 lppe;
+ lppe.dwSize = sizeof(PROCESSENTRY32);
+ BOOL ok = Process32FirstFunc(snap, &lppe);
+ while (ok == TRUE)
+ {
+ if (lppe.th32ParentProcessID == parent) // Have my Child...
+ children.push_back(lppe.th32ProcessID);
+ lppe.dwSize = sizeof(PROCESSENTRY32);
+ ok = Process32NextFunc(snap, &lppe);
+ }
+ CloseHandle(snap);
+ }
+ }
+#endif
+}
--
2.7.0
Child process PID: 8295
[debug][New Thread 0xb4b27b40 (LWP 8295)]
[debug][New Thread 0xb4b27b40 (LWP 8296)]
[debug][Thread 0xb4b27b40 (LWP 8295) exited]
[debug][New Thread 0xb01ffb40 (LWP 8297)]
[debug]Child process (pid:8295) doesn't exists
[debug]Child PID have not been detected!
Trying to interrupt process with pid: 8290; child pid: 8295 gdb pid: 8288
Continuing...
[debug]Program received signal SIGINT, Interrupt.
[debug]0xb7fdbbe8 in __kernel_vsyscall ()
[debug]>>>>>>cb_gdb:
Can you try it? Probably you should disable the pid detection.Does not compile at all on Windows. Process32FirstFunc and Process32NextFunc are undefined. Did you miss to provide some portions?
Did you miss to provide some portions?Maybe the Windows part should more look like this:
// get a function pointer to DebugBreakProcess under windows (XP+)
typedef HANDLE WINAPI CreateToolhelp32SnapshotFunc(DWORD dwFlags, DWORD th32ProcessID);
static CreateToolhelp32SnapshotFunc* snapshotFunc = NULL;
typedef BOOL WINAPI Process32FirstFunc(HANDLE hSnapshot, LPPROCESSENTRY32 lppe);
static Process32FirstFunc* firstFunc = NULL;
typedef BOOL WINAPI Process32NextFunc(HANDLE hSnapshot, LPPROCESSENTRY32 lppe);
static Process32NextFunc* nextFunc = NULL;
HMODULE kernel32DLL = LoadLibrary(TEXT("kernel32.dll"));
if (kernel32DLL)
{
snapshotFunc = (CreateToolhelp32SnapshotFunc*) GetProcAddress(kernel32DLL, "CreateToolhelp32Snapshot");
firstFunc = (Process32FirstFunc*) GetProcAddress(kernel32DLL, "Process32First");
nextFunc = (Process32NextFunc*) GetProcAddress(kernel32DLL, "Process32Next");
}
if ( (NULL!=snapshotFunc) && (NULL!=firstFunc) && (NULL!=nextFunc) )
{
HANDLE snap = snapshotFunc(TH32CS_SNAPALL,0);
if (snap!=INVALID_HANDLE_VALUE)
{
PROCESSENTRY32 lppe;
lppe.dwSize = sizeof(PROCESSENTRY32);
BOOL ok = firstFunc(snap, &lppe);
while (ok == TRUE)
{
if (lppe.th32ParentProcessID == parent) // Have my Child...
children.push_back(lppe.th32ProcessID);
lppe.dwSize = sizeof(PROCESSENTRY32);
ok = nextFunc(snap, &lppe);
}
CloseHandle(snap);
}
}
For some reason on your systems the first thread doesn't have the same pid as the process.In fact the main thread does have the same pid as the process, but it's not printed by gdb. Gdb only seems to print additionally created threads. As an example, this is a gdb log with thread info (note that there is no "New Thread" message for the main thread):
[New Thread 0xb4b27b40 (LWP 3861)]
[Thread 0xb4b27b40 (LWP 3861) exited]
[New Thread 0xb4b27b40 (LWP 3862)]
[New Thread 0xb01feb40 (LWP 3863)]
^C
Program received signal SIGINT, Interrupt.
0xb7fdbbe8 in __kernel_vsyscall ()
(gdb) info threads
Id Target Id Frame
4 Thread 0xb01feb40 (LWP 3863) [...]
3 Thread 0xb4b27b40 (LWP 3862) [...]
* 1 Thread 0xb5240780 (LWP 3857) [...]
(gdb) info program
Using the running image of child Thread 0xb5240780 (LWP 3857).
Can you check if the parent pid of the threads in your program is the same as the pid of the process?Yes it is:
~$ ps -L 3857
PID LWP TTY STAT TIME COMMAND
3857 3857 pts/9 tl 0:00 [...]
3857 3862 pts/9 tl 0:00 [...]
3857 3863 pts/9 tl 0:00 [...]