Оказывается, это произошло потому, что мы использовали JobObjects, чтобы убедиться, что все дочерний процесс выхода, когда ток выходит из процесса с использованием этого кода в C (мы на самом деле р-вызывается из C#):
HANDLE h = ::CreateJobObject(NULL, NULL);
JOBOBJECT_EXTENDED_LIMIT_INFORMATION info;
::ZeroMemory(&info, sizeof(info));
info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
::SetInformationJobObject(h, JobObjectExtendedLimitInformation, &info, sizeof(info));
::AssignProcessToJobObject(h, ::GetCurrentProcess());
...
::CloseHandle(h);
return -1;
Этот код добавляет текущий процесс и все его дочерние процессы к объекту задания, который будет закрыт при текущем выходе процесса. НО, но он имеет побочный эффект, когда был вызван CloseHandle
, он убьет текущий процесс, не достигнув линии return -1
. А так как JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
флаг автоматически убивает все процессы, нет способа установить код выхода для всех процессов, поэтому ОС вышла из процесса с кодом выхода 0.
В C# мы следовали стандартным рекомендациям по очистке ресурсов и использованию SafeHandle
- чтобы убедиться, что вызывается CloseHandle
, и абсолютно то же самое произошло - до того, как CLR на самом деле вышла из него, вызывается ::CloseHandle
для всех SafeHandle
s, игнорируя фактический код возврата, установленный как возвращаемым значением, так и Environment.Exit
.
Однако, что еще более интересно, заключается в том, что если явный (или не столь явный) вызов CloseHandle
удаляется как на C#, так и на C++, ОС все равно будет закрывать все дескрипторы на выходе процесса после выхода CLR/CRT и будет возвращен фактический код выхода. Поэтому иногда полезно не очищать ресурсы :-) или, другими словами, до тех пор, пока не будет вызван родной ::ExitProcess
, вы не можете гарантировать, что код выхода будет неповрежден.
Так, чтобы исправить эту конкретную проблему, я мог либо вызвать AssignProcessToJobObject
всякий раз, когда дочерний процесс запускается или удаляется явный (или не столь явный) вызов на CloseHandle
. Я выбрал первый подход.