gpt4 book ai didi

c# - Windows 进程(C#/C++/等)的错误退出代码?

转载 作者:可可西里 更新时间:2023-11-01 10:25:39 29 4
gpt4 key购买 nike

我们的 C# 应用程序以代码 0 退出,即使它在代码中明确返回 -1:

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

如果使用 void Main 也会发生同样的情况:

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

正如关于 SO 的其他问题所暗示的那样,它可能是其他线程中未处理的 CLR/C++/ native 异常。然而,我在最后一个线程之前添加了所有托管/ native 线程的正常关闭,但行为仍然存在。

可能是什么原因?

最佳答案

事实证明这是因为我们使用了 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 标志会自动终止所有进程,因此无法为所有进程设置退出代码,因此操作系统以退出代码 0 退出进程。

在 C# 中,我们遵循标准指南来清理资源并使用 SafeHandle 派生类来确保 CloseHandle 被调用并且完全相同的事情发生了 - 在 CLR 实际发生之前退出它为所有 SafeHandle 调用 ::CloseHandle,忽略由返回值和 Environment.Exit 设置的实际返回代码。

然而,更有趣的是,如果在 C# 和 C++ 中都删除了对 CloseHandle 的显式(或不那么显式)调用,操作系统仍会在进程退出后关闭所有句柄CLR/CRT 退出,返回实际退出码。所以有时最好不要清理资源 :-) 或者换句话说,在调用 native ::ExitProcess 之前,您不能保证退出代码完好无损。

因此,为了解决这个特定问题,我可以在子进程启动时调用 AssignProcessToJobObject,或者删除对 CloseHandle 的显式(或不那么显式)调用。我选择了第一种方法。

关于c# - Windows 进程(C#/C++/等)的错误退出代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19284718/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com