-
Notifications
You must be signed in to change notification settings - Fork 219
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix termination on MinGW/Cygwin by calling Windows API to terminate. #636
Conversation
MinGW and Cygwin do not allow Async break to occur without user intervention. The problem is with -exec-abort (stop debugging) while in run mode requires us to do an async break so that we can abort. Since we can't do that without additional user intervention, we will terminate the child process instead.
src/MICore/Debugger.cs
Outdated
// to terminate debugging. | ||
if ((this.IsCygwin || this.IsMinGW) && _debuggeePids.Count > 0) | ||
{ | ||
int debuggeePid = _debuggeePids.First().Value; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_debuggeePids [](start = 42, length = 13)
Is there a reason you only pick the first?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gregg-miskelly I took the code from CmdBreakInternal() (line 697) that breaks on the first thread. Would it be better to iterate through the list and terminate each individual item?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is what I would have thought, but @paulmaybee would be more familiar with the child process code. Maybe there is a reason that isn't needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't hurt to terminate all pids. Normally having more than one is a transient state. However there is a non-trivial amount of work done by gdb in between reporting that a new process is available and detaching so that vs can reattach separate miengine instance. If something goes wrong/hangs then killing all children is most likely the right way to recover.
src/MICore/Debugger.cs
Outdated
finally | ||
{ | ||
if (handle != IntPtr.Zero) | ||
Marshal.FreeCoTaskMem(handle); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FreeCoTaskMem [](start = 40, length = 13)
You need to P/Invoke to CloseHandle
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
src/MICore/Debugger.cs
Outdated
// the normal path of sending an internal async break so we can exit doesn't work. | ||
// Therefore, we will call TerminateProcess on the debuggee with the exit code of 0 | ||
// to terminate debugging. | ||
if ((this.IsCygwin || this.IsMinGW) && _debuggeePids.Count > 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
) [](start = 82, length = 1)
Exclude gdbserver cases?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Otherwise LGTM
src/MICore/Debugger.cs
Outdated
public static extern IntPtr OpenProcess(int dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId); | ||
[DllImport("kernel32.dll", SetLastError = true)] | ||
[return: MarshalAs(UnmanagedType.Bool)] | ||
static extern bool TerminateProcess(IntPtr hProcess, uint uExitCode); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: private?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Recommend terminating all pids. Otherwise LGTM.
MinGW and Cygwin do not allow Async break to occur without user
intervention. The problem is with -exec-abort (stop debugging) while in
run mode requires us to do an async break so that we can abort. Since we
can't do that without additional user intervention, we will terminate
the child process instead.