dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.16k stars 4.71k forks source link

Provide a way to attach a managed debugger to this process or a child process #12431

Open loop-evgeny opened 5 years ago

loop-evgeny commented 5 years ago

I have a .NET Core process that starts another .NET Core process. I want to debug the child process with Visual Studio. I control the code for both processes, but still cannot do this!

Starting the parent process under the debugger is useless. Calling System.Diagnostics.Debugger.Launch() in the child process is useless, because that forces attaching a native debugger, not managed. Even if I check "Manually choose debugging engines" in the JIT debug dialog I cannot uncheck "Native", so I'm forced to use mixed-mode debugging. The child process then gets stuck on the Debugger.Launch() line and I cannot continue it.

Debugger.Break() does nothing if a debugger is not already attached.

Debug.Fail() and Debug.Assert(false) just crash the child process.

hoyosjs commented 5 years ago

@dotnet/dotnet-diag in case other team members have other ideas.

As far as I know, this is a limitation on Visual Studio more than anything. For the scenarios that I've come across where I needed this, I ended up using the Child Process Debugging Extension and had a relatively good experience. As you said, mixed mode was necessary.

Maybe @gregg-miskelly has some input here as well 😄 If you try that extension and have no luck loop back and I'll investigate some more possible suggestions.

gregg-miskelly commented 5 years ago

The .NET debugging APIs don't provide a notification for child processes launches, so as @hoyosjs mentioned, currently the Child Process extension is the only good option. That should work with .NET Core on Windows.

loop-evgeny commented 5 years ago

Thanks a lot, @hoyosjs, that extension works! It would still be nice to fix the problem with Debugger.Launch, of course.

sharwell commented 5 years ago

Here's another way to do it, by operating directly against Visual Studio APIs: https://github.com/dotnet/roslyn/pull/28519

loop-evgeny commented 5 years ago

That's useful, thanks! I'd rather not add a reference to the Visual Studio API to my project, so I prefer the extension solution.

hoyosjs commented 5 years ago

@loop-evgeny Glad to hear that worked out for you. I'll take a look as to what can be done about Debugger.Launch when I get some time. I'd like to see what's preventing you from continuing the process, to see if it's a potentially weird issue, a bad user experience, or just something that is quirky but has an easy workaround we can document. Thanks for reporting this.

MarkPflug commented 4 years ago

I could have used something like this today. An API like Debugger.Attach(Process p), that would attach the current (meaning Debugger.IsAttached == true) debugger to the process p. In my scenario p is process that I just created.

cshung commented 4 years ago

If you happen to control the code of the child process, you can add this loop to the beginning of the process as follow:

while (!Debugger.IsAttached)
{
}
MarkPflug commented 4 years ago

Wouldn't it be better to Debugger.Launch() instead? That way I don't melt my CPU waiting for the debugger that may never attach.

The whole point though, is that I don't want to have to manually attach a debugger to the child process that I just created.

cshung commented 4 years ago

Wouldn't it be better to Debugger.Launch() instead? That way I don't melt my CPU waiting for the debugger that may never attach.

The whole point though, is that I don't want to have to manually attach a debugger to the child process that I just created.

Got it, the trick is meant for

  1. You do want to attach a debugger,
  2. You don't get to control the code that launches your process (e.g. msbuild), and
  3. You don't have a console to work with (So you can't just add a Console.ReadLine()) to wait.
MarkPflug commented 4 years ago

Yeah, that's the scenario I mean. For the scenario you describe, the Debugger.Launch() api will trigger a debug attach request in the child process. You can then attach or decline, and the process will resume execution. No loop needed.

But, my original API was describing the inverse, where my parent process wants to attach the current debugger to a child process that it just started. That's the API that is missing.

gregg-miskelly commented 4 years ago

IMHO, it would be better to have the controls for what process to debug be some setting in the debugger (like what the Child Process Debugging Extension does) then to have the app code be in charge of decided what to debug.

One tweak to the while loop from above, I would recommend sticking a Thread.Sleep call in the body of that loop. For example, add code that checks an environment variable to know if the 'pause on startup' is desired, and if so, enter that loop. If you are using VS, and if your process name is unique, you could then use an exe project to attach to the process fairly easily. Clearly not ideal, but about the best that can be done right now.

dotnet-policy-service[bot] commented 1 month ago

Due to lack of recent activity, this issue has been marked as a candidate for backlog cleanup. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will undo this process.

This process is part of our issue cleanup automation.

tommcdon commented 1 month ago

Adding a comment to prevent the bot from cleaning up this issue