Skip to content

Commit 5fbd271

Browse files
committed
Use PROC_THREAD_ATTRIBUTE_JOB_LIST to atomically assign a process to a job on creation
1 parent f14e0a0 commit 5fbd271

File tree

5 files changed

+21
-22
lines changed

5 files changed

+21
-22
lines changed

src/ChildProcess/Interop/Windows/Kernel32.CreateProcess.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ namespace Asmichi.Interop.Windows
1212
internal static partial class Kernel32
1313
{
1414
// Process Creation Flags
15-
public const int CREATE_SUSPENDED = 0x00000004;
1615
public const int CREATE_UNICODE_ENVIRONMENT = 0x00000400;
1716
public const int EXTENDED_STARTUPINFO_PRESENT = 0x00080000;
1817
public const int CREATE_NO_WINDOW = 0x08000000;

src/ChildProcess/Interop/Windows/Kernel32.JobObject.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,6 @@ public static extern SafeJobObjectHandle CreateJobObject(
2121
[In] IntPtr lpJobAttributes,
2222
[In] char[]? lpName);
2323

24-
[DllImport(DllName, SetLastError = true)]
25-
public static extern bool AssignProcessToJobObject(
26-
[In] SafeJobObjectHandle hJob,
27-
[In] SafeProcessHandle hProcess);
28-
2924
[DllImport(DllName, SetLastError = true)]
3025
public static extern unsafe bool SetInformationJobObject(
3126
[In] SafeJobObjectHandle hJob,

src/ChildProcess/Interop/Windows/Kernel32.ProcThreadAttributeList.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ namespace Asmichi.Interop.Windows
1111
internal static partial class Kernel32
1212
{
1313
public static readonly IntPtr PROC_THREAD_ATTRIBUTE_HANDLE_LIST = new IntPtr(0x20002);
14+
public static readonly IntPtr PROC_THREAD_ATTRIBUTE_JOB_LIST = new IntPtr(0x2000d);
1415
public static readonly IntPtr PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE = new IntPtr(0x20016);
1516

1617
[DllImport(DllName, SetLastError = true)]

src/ChildProcess/Interop/Windows/ProcThreadAttributeList.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,21 @@ public unsafe void UpdateHandleList(IntPtr* handles, int count)
3939
}
4040
}
4141

42+
public unsafe void UpdateJobList(IntPtr* handles, int count)
43+
{
44+
if (!Kernel32.UpdateProcThreadAttribute(
45+
_unmanaged,
46+
0,
47+
Kernel32.PROC_THREAD_ATTRIBUTE_JOB_LIST,
48+
handles,
49+
sizeof(IntPtr) * count,
50+
IntPtr.Zero,
51+
IntPtr.Zero))
52+
{
53+
throw new Win32Exception();
54+
}
55+
}
56+
4257
public unsafe void UpdatePseudoConsole(IntPtr hPC)
4358
{
4459
if (!Kernel32.UpdateProcThreadAttribute(

src/ChildProcess/ProcessManagement/WindowsChildProcessStateHelper.cs

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -63,22 +63,23 @@ public unsafe IChildProcessStateHolder SpawnProcess(
6363
var childStdOut = stdOut != null ? inheritableHandleStore.Add(stdOut) : null;
6464
var childStdErr = stdErr != null ? inheritableHandleStore.Add(stdErr) : null;
6565

66+
IntPtr jobObjectHandles = jobObjectHandle.DangerousGetHandle();
67+
6668
Span<IntPtr> inheritableHandles = stackalloc IntPtr[inheritableHandleStore.Count];
6769
inheritableHandleStore.DangerousGetHandles(inheritableHandles);
6870
fixed (IntPtr* pInheritableHandles = inheritableHandles)
6971
{
70-
using var attr = new ProcThreadAttributeList(2);
72+
using var attr = new ProcThreadAttributeList(3);
7173
if (pseudoConsole is not null)
7274
{
7375
attr.UpdatePseudoConsole(pseudoConsole.Handle.DangerousGetHandle());
7476
}
7577
attr.UpdateHandleList(pInheritableHandles, inheritableHandles.Length);
78+
attr.UpdateJobList(&jobObjectHandles, 1);
7679

77-
// Create the process suspended so that it will not create a grandchild process before we assign it to the job object.
7880
const int CreationFlags =
7981
Kernel32.CREATE_UNICODE_ENVIRONMENT
80-
| Kernel32.EXTENDED_STARTUPINFO_PRESENT
81-
| Kernel32.CREATE_SUSPENDED;
82+
| Kernel32.EXTENDED_STARTUPINFO_PRESENT;
8283

8384
int processId;
8485
(processId, processHandle, threadHandle) = InvokeCreateProcess(
@@ -91,18 +92,6 @@ public unsafe IChildProcessStateHolder SpawnProcess(
9192
childStdErr,
9293
attr);
9394

94-
if (!Kernel32.AssignProcessToJobObject(jobObjectHandle, processHandle))
95-
{
96-
// Normally this will not fail...
97-
throw new Win32Exception();
98-
}
99-
100-
if (Kernel32.ResumeThread(threadHandle) == -1)
101-
{
102-
// Normally this will not fail...
103-
throw new Win32Exception();
104-
}
105-
10695
return new WindowsChildProcessState(processId, processHandle, jobObjectHandle, pseudoConsole, startInfo.AllowSignal);
10796
}
10897
}

0 commit comments

Comments
 (0)