Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ internal struct STARTUPINFO
}

internal const int PROC_THREAD_ATTRIBUTE_HANDLE_LIST = 0x00020002;
internal const int CREATE_BREAKAWAY_FROM_JOB = 0x01000000;
internal const int EXTENDED_STARTUPINFO_PRESENT = 0x00080000;

[StructLayout(LayoutKind.Sequential)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public SafeJobHandle() : base(true) { }
internal static partial SafeJobHandle CreateJobObjectW(IntPtr lpJobAttributes, IntPtr lpName);

internal const uint JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE = 0x00002000;
internal const uint JOB_OBJECT_LIMIT_BREAKAWAY_OK = 0x00000800;

internal enum JOBOBJECTINFOCLASS
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ private static bool TryOpenCore(int processId, [NotNullWhen(true)] out SafeProce
private static unsafe Interop.Kernel32.SafeJobHandle CreateKillOnParentExitJob()
{
Interop.Kernel32.JOBOBJECT_EXTENDED_LIMIT_INFORMATION limitInfo = default;
limitInfo.BasicLimitInformation.LimitFlags = Interop.Kernel32.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
limitInfo.BasicLimitInformation.LimitFlags = Interop.Kernel32.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | Interop.Kernel32.JOB_OBJECT_LIMIT_BREAKAWAY_OK;
Comment thread
adamsitnik marked this conversation as resolved.

Interop.Kernel32.SafeJobHandle jobHandle = Interop.Kernel32.CreateJobObjectW(IntPtr.Zero, IntPtr.Zero);
if (jobHandle.IsInvalid || !Interop.Kernel32.SetInformationJobObject(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,85 @@ public unsafe void StartWithCallback_CreateProcess_CanRedirectOutput()
Assert.Equal(0, process.ExitCode);
}

[ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
[InlineData(true)]
[InlineData(false)]
public unsafe void ChildProcess_CanBreakAwayFromJob(bool killOnParentExit)
{
using Process process = CreateProcess(() =>
{
using (Process grandChild = CreateProcess(() =>
{
return RemoteExecutor.SuccessExitCode;
}))
{
ProcessStartInfo grandChildStartInfo = grandChild.StartInfo;

using Process started = WindowsProcessStartArguments.Start(grandChildStartInfo, (WindowsProcessStartArguments args) =>
{
Interop.Kernel32.STARTUPINFOEX startupInfoEx = default;
Interop.Kernel32.PROCESS_INFORMATION processInfo = default;
Interop.Kernel32.SECURITY_ATTRIBUTES unused_SecAttrs = default;

startupInfoEx.StartupInfo.cb = sizeof(Interop.Kernel32.STARTUPINFOEX);
startupInfoEx.StartupInfo.hStdInput = args.StandardInput;
startupInfoEx.StartupInfo.hStdOutput = args.StandardOutput;
startupInfoEx.StartupInfo.hStdError = args.StandardError;
startupInfoEx.StartupInfo.dwFlags = Interop.Advapi32.StartupInfoOptions.STARTF_USESTDHANDLES;

int creationFlags = Interop.Kernel32.CREATE_BREAKAWAY_FROM_JOB | Interop.Kernel32.EXTENDED_STARTUPINFO_PRESENT;
if (args.EnvironmentVariables != null)
{
creationFlags |= Interop.Advapi32.StartupInfoOptions.CREATE_UNICODE_ENVIRONMENT;
}

if (!Interop.Kernel32.CreateProcess(
null,
args.Arguments,
ref unused_SecAttrs,
ref unused_SecAttrs,
bInheritHandles: true,
creationFlags,
args.EnvironmentVariables,
null,
&startupInfoEx,
&processInfo
))
{
throw new Win32Exception();
}

Interop.Kernel32.CloseHandle(processInfo.hThread);

return processInfo.hProcess;
});

try
{
Assert.True(started.WaitForExit(WaitInMS));
return started.ExitCode;
}
finally
{
started.Kill();
}
}
});

process.StartInfo.KillOnParentExit = killOnParentExit;
process.Start();

try
{
Assert.True(process.WaitForExit(WaitInMS));
Assert.Equal(RemoteExecutor.SuccessExitCode, process.ExitCode);
}
finally
{
process.Kill();
}
}

private unsafe int RunWithInvalidHandles(ProcessStartInfo startInfo)
{
const nint INVALID_HANDLE_VALUE = -1;
Expand Down
Loading