I have a utility application to spawn (or respawn) other processes, set up the console window and its title and icon and connect the standard handles to file-like objects (file, named pipe, socket).
In case of any failure this application has to terminate immediately and as fast as possible.
if ( !success )
ExitProcess( 1 );
Problems come with "Window 10 parallel library loading support in ntdll.dll".
As described in this answer and in this article this feature prevents the fast fail.
Programs which execute in less than 30 seconds will appear to hang due to ntdll!TppWorkerThreadwaiting for the idle timeout before the process terminates.
Even if I set MaxLoaderThreads in the Registry, the tread pool is created when I call LoadLibrary.
My Question is, how to terminate the process without waiting for the loader-threads, without calling ZwCreateUserProcess directly and without modifying the Registry on the target machine.
My idea is to have a replacement for ExitProcess which calls TerminateProcess as follows (and it seems to work).
VOID WINAPI ExitProcessNow( UINT uExitCode )
{
if ( TerminateProcess( GetCurrentProcess(),
uExitCode ) )
ExitThread( uExitCode );
else
ExitProcess( uExitCode );
}
EDIT Some clarification
Assume the following program:
#include <Windows.h>
#ifndef _DEBUG
#pragma comment ( linker, "/ENTRY:EntryPoint" )
#else
#define EntryPoint main
#endif
#define NUMBER_OF_WORKER_THREADS 3
DWORD __stdcall WorkerThreadProc( PVOID __unused )
{
for ( ;; )
Sleep( 1000 );
}
void EntryPoint()
{
for ( int ii = NUMBER_OF_WORKER_THREADS; ii; --ii )
CloseHandle( CreateThread( NULL, 0, WorkerThreadProc, NULL, 0, NULL ) );
Sleep( 10000 );
// For demonstration do not call ExitProcess.
// ExitProcess( 0 );
}
The initial thread starts three workers, waits 10 seconds and then exits. The workers are running indefinitely.
If _DEBUG
is not defined, there is no CRT code which calls ExitProcess at the end of main()
and the process continues running with three threads at WorkerThreadProc.
This was the situation I observed. My process and/or a spawned process where running with three threads with an entry point at ntdll!Tp...
.
My code definitively called ExitProcess
(after replacing ExitProcess
by TerminateProcess
it worked).
The point is, in cases when the program has to exit it has to exit immediately, independent of any locks in any library or any thread. Maybe it has something to do with the parallel loading or not, maybe there is as deadlock in my or the spawned code, it doesn't matter. The program has to exit and the process has to become signaled.
The main use case of this program is to respawn other programs when they exit for any reason as /sbin/init does when configured with respawn
in /etc/inittab.