Răsfoiți Sursa

libuv: win,process: avoid kernel bug with starting Windows Store apps

Backport upstream libuv commit `93ca3f15` (win,process: avoid kernel bug
with starting Windows Store apps, 2023-09-27) from libuv PR 4152.

Fixes: #23029
Patch-by: Jameson Nash <[email protected]>
Brad King 2 ani în urmă
părinte
comite
fe2ecf920f
1 a modificat fișierele cu 29 adăugiri și 12 ștergeri
  1. 29 12
      Utilities/cmlibuv/src/win/process.c

+ 29 - 12
Utilities/cmlibuv/src/win/process.c

@@ -102,6 +102,21 @@ static void uv__init_global_job_handle(void) {
                                &info,
                                sizeof info))
     uv_fatal_error(GetLastError(), "SetInformationJobObject");
+
+
+  if (!AssignProcessToJobObject(uv_global_job_handle_, GetCurrentProcess())) {
+    /* Make sure this handle is functional. The Windows kernel has a bug that
+     * if the first use of AssignProcessToJobObject is for a Windows Store
+     * program, subsequent attempts to use the handle with fail with
+     * INVALID_PARAMETER (87). This is possibly because all uses of the handle
+     * must be for the same Terminal Services session. We can ensure it is tied
+     * to our current session now by adding ourself to it. We could remove
+     * ourself afterwards, but there doesn't seem to be a reason to.
+     */
+    DWORD err = GetLastError();
+    if (err != ERROR_ACCESS_DENIED)
+      uv_fatal_error(err, "AssignProcessToJobObject");
+  }
 }
 
 
@@ -1101,6 +1116,7 @@ int uv_spawn(uv_loop_t* loop,
      * breakaway.
      */
     process_flags |= DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP;
+    process_flags |= CREATE_SUSPENDED;
   }
 
   if (options->cpumask != NULL) {
@@ -1159,20 +1175,8 @@ int uv_spawn(uv_loop_t* loop,
       TerminateProcess(info.hProcess, 1);
       goto done;
     }
-
-    /* The process affinity of the child is set.  Let it run.  */
-    if (ResumeThread(info.hThread) == ((DWORD)-1)) {
-      err = GetLastError();
-      TerminateProcess(info.hProcess, 1);
-      goto done;
-    }
   }
 
-  /* Spawn succeeded. Beyond this point, failure is reported asynchronously. */
-
-  process->process_handle = info.hProcess;
-  process->pid = info.dwProcessId;
-
   /* If the process isn't spawned as detached, assign to the global job object
    * so windows will kill it when the parent process dies. */
   if (!(options->flags & UV_PROCESS_DETACHED)) {
@@ -1195,6 +1199,19 @@ int uv_spawn(uv_loop_t* loop,
     }
   }
 
+  if (process_flags & CREATE_SUSPENDED) {
+    if (ResumeThread(info.hThread) == ((DWORD)-1)) {
+      err = GetLastError();
+      TerminateProcess(info.hProcess, 1);
+      goto done;
+    }
+  }
+
+  /* Spawn succeeded. Beyond this point, failure is reported asynchronously. */
+
+  process->process_handle = info.hProcess;
+  process->pid = info.dwProcessId;
+
   /* Set IPC pid to all IPC pipes. */
   for (i = 0; i < options->stdio_count; i++) {
     const uv_stdio_container_t* fdopt = &options->stdio[i];