]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
chore: Undo revert in "Fix MSVC crash when using /Zi /Fddebug.pdb"
authorJoel Rosdahl <joel@rosdahl.net>
Mon, 5 Feb 2024 18:42:57 +0000 (19:42 +0100)
committerJoel Rosdahl <joel@rosdahl.net>
Mon, 5 Feb 2024 19:11:35 +0000 (20:11 +0100)
In preparation for solving #1386 while keeping the essence of #1274.

This reverts commit a2bf2956d78599b2397081a9e7b253a569c7c932.

src/execute.cpp

index 02885397bf22a1fcd8b405d03e202ebb6bbbac0f..0c51671bf589c6c814c3fbaa1e4b72327b6149b4 100644 (file)
@@ -117,6 +117,76 @@ win32execute(const char* path,
              int fd_stderr,
              const std::string& temp_dir)
 {
+  BOOL is_process_in_job = false;
+  DWORD dw_creation_flags = 0;
+
+  {
+    BOOL job_success =
+      IsProcessInJob(GetCurrentProcess(), nullptr, &is_process_in_job);
+    if (!job_success) {
+      DWORD error = GetLastError();
+      LOG("failed to IsProcessInJob: {} ({})",
+          util::win32_error_message(error),
+          error);
+      return 0;
+    }
+    if (is_process_in_job) {
+      JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobInfo = {};
+      BOOL querySuccess =
+        QueryInformationJobObject(nullptr,
+                                  JobObjectExtendedLimitInformation,
+                                  &jobInfo,
+                                  sizeof(jobInfo),
+                                  nullptr);
+      if (!querySuccess) {
+        DWORD error = GetLastError();
+        LOG("failed to QueryInformationJobObject: {} ({})",
+            util::win32_error_message(error),
+            error);
+        return 0;
+      }
+
+      const auto& limit_flags = jobInfo.BasicLimitInformation.LimitFlags;
+      bool is_kill_active = limit_flags & JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
+      bool allow_break_away = limit_flags & JOB_OBJECT_LIMIT_BREAKAWAY_OK;
+      if (!is_kill_active && allow_break_away) {
+        is_process_in_job = false;
+        dw_creation_flags = CREATE_BREAKAWAY_FROM_JOB | CREATE_SUSPENDED;
+      }
+    } else {
+      dw_creation_flags = CREATE_SUSPENDED;
+    }
+  }
+
+  HANDLE job = nullptr;
+  if (!is_process_in_job) {
+    job = CreateJobObject(nullptr, nullptr);
+    if (job == nullptr) {
+      DWORD error = GetLastError();
+      LOG("failed to CreateJobObject: {} ({})",
+          util::win32_error_message(error),
+          error);
+      return -1;
+    }
+
+    {
+      // Set the job object to terminate all child processes when the parent
+      // process is killed.
+      JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobInfo = {};
+      jobInfo.BasicLimitInformation.LimitFlags =
+        JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
+      BOOL job_success = SetInformationJobObject(
+        job, JobObjectExtendedLimitInformation, &jobInfo, sizeof(jobInfo));
+      if (!job_success) {
+        DWORD error = GetLastError();
+        LOG("failed to JobObjectExtendedLimitInformation: {} ({})",
+            util::win32_error_message(error),
+            error);
+        return -1;
+      }
+    }
+  }
+
   PROCESS_INFORMATION pi;
   memset(&pi, 0x00, sizeof(pi));
 
@@ -174,7 +244,7 @@ win32execute(const char* path,
                            nullptr,
                            nullptr,
                            1,
-                           0,
+                           dw_creation_flags,
                            nullptr,
                            nullptr,
                            &si,
@@ -191,12 +261,27 @@ win32execute(const char* path,
         error);
     return -1;
   }
+  if (job) {
+    BOOL assign_success = AssignProcessToJobObject(job, pi.hProcess);
+    if (!assign_success) {
+      TerminateProcess(pi.hProcess, 1);
+
+      DWORD error = GetLastError();
+      LOG("failed to assign process to job object {}: {} ({})",
+          full_path,
+          util::win32_error_message(error),
+          error);
+      return -1;
+    }
+    ResumeThread(pi.hThread);
+  }
   WaitForSingleObject(pi.hProcess, INFINITE);
 
   DWORD exitcode;
   GetExitCodeProcess(pi.hProcess, &exitcode);
   CloseHandle(pi.hProcess);
   CloseHandle(pi.hThread);
+  CloseHandle(job);
   if (!doreturn) {
     exit(exitcode);
   }