C # pause all threads

I have a problem that can be quite unique. I have an application that runs in a headless box for long hours when I am not present but not critical. I would like to be able to debug this application remotely using Visual Studio. For this, I have a code that looks like this:

// Suspend all other threads to prevent loss // of state while we investigate the issue. SuspendAllButCurrentThread(); var remoteDebuggerProcess = new Process { StartInfo = { UseShellExecute = true, FileName = MsVsMonPath; } }; // Exception handling and early return removed here for brevity. remoteDebuggerProcess.Start(); // Wait for a debugger attach. while (!Debugger.IsAttached) { Thread.Sleep(500); } Debugger.Break(); // Once we get here, we've hit continue in the debugger. Restore all of our threads, // then get rid of the remote debugging tools. ResumeAllButCurrentThread(); remoteDebuggerProcess.CloseMainWindow(); remoteDebuggerProcess.WaitForExit(); 

The idea is that in this way I hit the error while I am leaving, and the application pauses efficiently and waits for the remote debugger to connect, which after the first continuation automatically gets the correct context thanks to the call of Debugger.Break .

Here's the problem: the implementation of SuspendAllButCurrentThread is not trivial. Thread.Suspend deprecated, and I cannot run P / Invoke until SuspendThread , because there is no one-to-one mapping between managed threads and native threads (since I need to keep the current thread alive). I do not want to install Visual Studio on the machine in question if it can be avoided. How can I do this job?

+6
source share
2 answers

I cannot run P / Invoke until SuspendThread, because there is no one-to-one mapping between managed threads and native threads

You also cannot list managed threads, only unmanaged threads. In fact, there is a one-to-one comparison between them, it is simply difficult for them to find it. The initial intention was to allow the creation of a custom CLR host that did not use operating system threads to implement Thread, querying the SQL Server group that wanted to use fibers instead. It never worked out, they couldn't get it reliable enough. There is no real CLR host that does not use real operating system threads.

So you can actually use Process.GetCurrentProcess (). Topics for listing all of your threads. And don't suspend your own by calling GetCurrentThreadId (), comparing it to ProcessThread.Id

How reliable this conjecture will be, do not try to do anything radical, like sending a warning, to remind you that the time has come to connect the debugger. You may well have paused a thread that was executing code inside Windows and acquired a global lock. Like a CLR worker thread, such as a finalizer thread or a background GC thread.

The best approach is to use a separate defense process that does all this, just like a debugger. Use the named EventWaitHandle that you create in the security program and OpenExisting () in your main program. The security program needs WaitAny () on this wait descriptor, as well as in the process. Now your main program can simply call Set () to wake up the security program. You can now safely pause all threads.

+5
source

The main problem with Thread.Suspend is that it can leave some object in an unusable state.

From the documentation :

Do not use pause and resume methods to synchronize thread activity. You have no way of knowing which code is the thread that executes when it is paused. If you pause a thread while it holds locks while evaluating security permissions, other threads in AppDomain may be blocked. If you pause a thread while it is executing a class constructor, other threads in the AppDomain that attempt to use this class are blocked. Dead ends can occur very easily.

Therefore, when you try to view the contents of such an unusable object, you are likely to block it too. Therefore, no matter what you use to pause other threads, you may end up in the same scenario. So, the only way is to change the implementation of other threads to ask them to pause themselves: Is there a way to pause a thread endlessly? .

+1
source

Source: https://habr.com/ru/post/951921/


All Articles