2013-10-09 41 views
2

我們的C#應用​​程序退出時碼0,即使它明確地返回-1代碼:Windows進程錯誤的退出代碼(C#/ C++/etc)?

internal class Program 
{ 
    public int Main() 
    { 
     .... 
     return -1; 
    } 
} 

同樣的事情發生,如果void Main使用:

internal class Program 
{ 
    public void Main() 
    { 
     .... 
     Environment.Exit(-1); 
    } 
} 

由於對SO提出的其他問題它可能是一些其他線程中未處理的CLR/C++/native異常。 但是,在這最後一次之前,我已經正常關閉了所有託管/本機線程,但行爲依然存在。

可能是什麼原因?

回答

2

原來這事,因爲我們使用JobObjects確保在使用用C此代碼當前進程退出(我們實際上是從C#P-調用的)的所有子進程退出:

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標誌自動殺死所有進程有沒有辦法來設置所有進程退出代碼,所以OS退出過程,退出代碼0

在C#中,我們遵循標準的指導方針,清理資源,並使用SafeHandle - 派生類來確保CloseHandle被調用,並且絕對是相同的 - 在CLR實際退出之前,它調用::CloseHandle爲所有SafeHandle s忽略返回值和Environment.Exit的實際返回碼集。

但是更有意思的是,如果在C#和C++中都刪除了對CloseHandle的明確(或不那麼明確)的調用,OS仍然會在CLR/CRT退出後關閉進程出口處的所有句柄,並且實際的退出碼將被退回。所以有時候最好不要清理資源:-)換句話說,直到調用本地::ExitProcess,你不能保證退出代碼將完好無損。

所以要解決這個特殊問題,我可以調用AssignProcessToJobObject每當一個子進程啓動或刪除對CloseHandle明確(或不那麼明確)的調用。我選擇了第一種方法。

相關問題