在ASP.NET Core Process中创建的子进程在退出时被杀死

Mis*_*tyK 21 .net c# asp.net-web-api

我正在使用Process类在ASP.NET Core(.NET Framework)中生成子进程:

var process = new Process
            {
                StartInfo = new ProcessStartInfo(executableDir)
                {
                    Arguments = commandDefinition.CommandDef.ArgumentsAsString,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    UseShellExecute = false,
                    CreateNoWindow = true,
                    WorkingDirectory = _contentPath,
                },
            };

process.Start()
Run Code Online (Sandbox Code Playgroud)

据我所知,当父(ASP.Net Core)进程被杀死时,子进程应该保持活跃状态​​.我使用两个控制台应用程序测试了这种行为,并且在杀死父进程后,子进程永远不会被杀死 但是,当我在ASP.NET Core中生成一个新进程时,子进程在以下情况下被杀死:

  • IIS回收应用程序.
  • MSDeploy发布了新版本的ASP.NET Core应用程序.
  • 使用dotnet watch时,应用程序在代码更改期间重新启动.

如果通过任务管理器杀死父级,它不会被杀死.(经过一些测试后并非总是如此)

从上面我怀疑ASP.NET Core中有一种机制可以在成功退出时杀死所有子进程.它在某处记录了吗?有没有办法避免它?我找不到有关此类行为的任何信息.

编辑:repro实际上非常简单.

  1. 创建ASP.NET核心项目(.NET Framework或.NET Core,无关紧要)
  2. 将以下代码添加到您的Startup班级
  3. 启动网络应用.它将在IIS Express下托管.计算过程将开始.现在要么通过任务管理器杀死你的应用程序,要么通过IIS express托盘图标关闭它.
  4. 计算过程将被杀死.(有时您需要尝试刷新离线网页)
 var process = new Process
 {
      StartInfo = new ProcessStartInfo("calc.exe")
      {
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            UseShellExecute = false,
            CreateNoWindow = true,
      },
 };
 process.Start();
Run Code Online (Sandbox Code Playgroud)

Edit2:问题似乎在IIS中.我在launchSettings.json中有两个配置文件.如果我使用IISExpress运行它然后它会关闭,但是当使用第二个时它会存在.

"IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "launchUrl": "api/values",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "WebApplication3Core": {
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "api/values",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      },
      "applicationUrl": "http://localhost:52135/"
    }
Run Code Online (Sandbox Code Playgroud)

Edit4:

我用过程监视器做了一些研究,这是输出:

SS1

SS2

SS3

正如您在ss1中所看到的,iisexpress存在"Process Exit"操作,然后有许多不可用的日志,并且在一段时间后有一个针对calc.exe的Process Exit.它与正常退出没有任何不同.唯一的区别是后面的日志说"CloseFile"和我的网络应用程序的路径,我不知道它实际意味着什么.肯定是iis杀死了calc.exe.我有IIS Express 10.0.14358版本(服务器版本,我发现这也是10)

Sim*_*ier 5

正如我在评论中所说,有一个由 ASP.NET 核心在进程外场景中创建的作业对象。相关的源代码部分在这里:

https://github.com/aspnet/AspNetCore/blob/master/src/Servers/IIS/AspNetCoreModuleV2/OutOfProcessRequestHandler/serverprocess.cpp#L89

HRESULT
SERVER_PROCESS::SetupJobObject(VOID)
{
    HRESULT                                 hr = S_OK;
    JOBOBJECT_EXTENDED_LIMIT_INFORMATION    jobInfo = { 0 };

    if (m_hJobObject == NULL)
    {
      ....
            jobInfo.BasicLimitInformation.LimitFlags =
                JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;

            if (!SetInformationJobObject(m_hJobObject,
                JobObjectExtendedLimitInformation,
                &jobInfo,
                sizeof jobInfo))
            {
                hr = HRESULT_FROM_WIN32(GetLastError());
            }
        }
    }

    return hr;
}
Run Code Online (Sandbox Code Playgroud)

根据文档,JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE

当作业的最后一个句柄关闭时,导致与作业关联的所有进程终止。

如果进一步挖掘来源,它似乎不是可选的。

现在,如果您重现您的步骤,您实际上可以自己看到这一点。使用Process Explorer并导航到您的 dotnet.exe 进程,它将显示以下内容:

在此处输入图片说明

  • 注意 1:实际上calc.exe保持活动状态(至少在我的 Windows 10 安装中,因为它现在是一个 WinRT 应用程序,因此它最终不会成为 dotnet.exe 的子项),这就是我使用的原因notepad.exe
  • 注意2:iisexpress.exe也创建了一个作业对象,但它被配置为脱离正常,这意味着它不会杀死子进程。
  • 注意 3:如果您从 Visual Studio 运行(不是我的屏幕截图),您可能会看到和VSIISExeLauncher.exe之间的中间过程。这个还创建了一个带有“关闭时杀死”的作业对象以增加混乱......iisexpress.exedotnet.exe

  • 一个完整的谜团解决方案。 (2认同)