|
@@ -0,0 +1,85 @@
|
|
|
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
+From: Jameson Nash <[email protected]>
|
|
|
+Date: Mon, 2 Oct 2023 15:15:18 +0200
|
|
|
+Subject: win,process: avoid assert after spawning Store app (#4152)
|
|
|
+
|
|
|
+Make sure this handle is functional. The Windows kernel seems to have 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 possilby 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.
|
|
|
+
|
|
|
+Secondly, we start the process suspended so that we can make sure we
|
|
|
+added it to the job control object before it does anything itself (such
|
|
|
+as launch more jobs or exit).
|
|
|
+
|
|
|
+Fixes: https://github.com/JuliaLang/julia/issues/51461
|
|
|
+
|
|
|
+diff --git a/deps/uv/src/win/process.c b/deps/uv/src/win/process.c
|
|
|
+index 24c633393fd15dcf87726b174d6b027a969e0f0d..4ad9fec900fa66b0e8c6894701e94f420de903a8 100644
|
|
|
+--- a/deps/uv/src/win/process.c
|
|
|
++++ b/deps/uv/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");
|
|
|
++ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+@@ -1098,6 +1113,7 @@ int uv_spawn(uv_loop_t* loop,
|
|
|
+ * breakaway.
|
|
|
+ */
|
|
|
+ process_flags |= DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP;
|
|
|
++ process_flags |= CREATE_SUSPENDED;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!CreateProcessW(application_path,
|
|
|
+@@ -1115,11 +1131,6 @@ int uv_spawn(uv_loop_t* loop,
|
|
|
+ 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)) {
|
|
|
+@@ -1142,6 +1153,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];
|