From 03df28b18b92b3fd3d2ba1000903c088dc5b0fcf Mon Sep 17 00:00:00 2001 From: Andre Heinecke Date: Mon, 29 Apr 2019 08:54:39 +0200 Subject: [PATCH] common,w32: Breakaway detached childs when in job * common/exechelp-w32.c (gnupg_spawn_process_detached): Add CREATE_BREAKAWAY_FROM_JOB creation flag if required. -- When the gpg process is assigned to a W32 "Job" the child processes are killed once the Job is finished. As we want our detached processes to linger e.g. gpg-agent the breakaway flag is required in that case. GnuPG-Bug-Id: T4333 Thanks to Jan Echternach for reporting this and providing a patch. Signed-off-by: Andre Heinecke --- common/exechelp-w32.c | 45 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/common/exechelp-w32.c b/common/exechelp-w32.c index 86b1d6869..ea158a33f 100644 --- a/common/exechelp-w32.c +++ b/common/exechelp-w32.c @@ -856,6 +856,7 @@ gnupg_spawn_process_detached (const char *pgmname, const char *argv[], STARTUPINFO si; int cr_flags; char *cmdline; + BOOL in_job = FALSE; /* We don't use ENVP. */ @@ -884,6 +885,50 @@ gnupg_spawn_process_detached (const char *pgmname, const char *argv[], | GetPriorityClass (GetCurrentProcess ()) | CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS); + + /* Check if we were spawned as part of a Job. + * In a job we need to add CREATE_BREAKAWAY_FROM_JOB + * to the cr_flags, otherwise our child processes + * are killed when we terminate. */ + if (!IsProcessInJob (GetCurrentProcess(), NULL, &in_job)) + { + log_error ("IsProcessInJob() failed: %s\n", w32_strerror (-1)); + in_job = FALSE; + } + + if (in_job) + { + /* Only try to break away from job if it is allowed, otherwise + * CreateProcess() would fail with an "Access is denied" error. */ + JOBOBJECT_EXTENDED_LIMIT_INFORMATION info; + if (!QueryInformationJobObject (NULL, JobObjectExtendedLimitInformation, + &info, sizeof info, NULL)) + { + log_error ("QueryInformationJobObject() failed: %s\n", + w32_strerror (-1)); + } + else if ((info.BasicLimitInformation.LimitFlags & + JOB_OBJECT_LIMIT_BREAKAWAY_OK)) + { + log_debug ("Using CREATE_BREAKAWAY_FROM_JOB flag\n"); + cr_flags |= CREATE_BREAKAWAY_FROM_JOB; + } + else if ((info.BasicLimitInformation.LimitFlags & + JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK)) + { + /* The child process should automatically detach from the job. */ + log_debug ("Not using CREATE_BREAKAWAY_FROM_JOB flag; " + "JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK is set\n"); + } + else + { + /* It seems that the child process must remain in the job. + * This is not necessarily an error, although it can cause premature + * termination of the child process when the job is closed. */ + log_debug ("Not using CREATE_BREAKAWAY_FROM_JOB flag\n"); + } + } + /* log_debug ("CreateProcess(detached), path='%s' cmdline='%s'\n", */ /* pgmname, cmdline); */ if (!CreateProcess (pgmname, /* Program to start. */