Browse Source

fix relaunch on linux (#14975)

* chore: re-enable relaunch test for Linux

* fix: relauncher_linux listening for parent exit
Charles Kerr 6 years ago
parent
commit
9d4818c784
2 changed files with 18 additions and 29 deletions
  1. 18 21
      atom/browser/relauncher_linux.cc
  2. 0 8
      spec/api-app-spec.js

+ 18 - 21
atom/browser/relauncher_linux.cc

@@ -12,47 +12,44 @@
 #include "base/files/file_util.h"
 #include "base/files/scoped_file.h"
 #include "base/logging.h"
-#include "base/posix/eintr_wrapper.h"
 #include "base/process/launch.h"
+#include "base/synchronization/waitable_event.h"
 
 namespace relauncher {
 
 namespace internal {
 
+// this is global to be visible to the sa_handler
+base::WaitableEvent parentWaiter;
+
 void RelauncherSynchronizeWithParent() {
   base::ScopedFD relauncher_sync_fd(kRelauncherSyncFD);
+  static const auto signum = SIGUSR2;
 
-  // Don't execute signal handlers of SIGUSR2.
-  sigset_t mask;
-  sigemptyset(&mask);
-  sigaddset(&mask, SIGUSR2);
-  if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
-    PLOG(ERROR) << "sigprocmask";
-    return;
-  }
-
-  // Create a signalfd that watches for SIGUSR2.
-  int usr2_fd = signalfd(-1, &mask, 0);
-  if (usr2_fd < 0) {
-    PLOG(ERROR) << "signalfd";
+  // send signum to current process when parent process ends.
+  if (HANDLE_EINTR(prctl(PR_SET_PDEATHSIG, signum)) != 0) {
+    PLOG(ERROR) << "prctl";
     return;
   }
 
-  // Send SIGUSR2 to current process when parent process ends.
-  if (HANDLE_EINTR(prctl(PR_SET_PDEATHSIG, SIGUSR2)) != 0) {
-    PLOG(ERROR) << "prctl";
+  // set up a signum handler
+  struct sigaction action;
+  memset(&action, 0, sizeof(action));
+  action.sa_handler = [](int /*signum*/) { parentWaiter.Signal(); };
+  if (sigaction(signum, &action, nullptr) != 0) {
+    PLOG(ERROR) << "sigaction";
     return;
   }
 
-  // Write a '\0' character to the pipe.
+  // write a '\0' character to the pipe to the parent process.
+  // this is how the parent knows that we're ready for it to exit.
   if (HANDLE_EINTR(write(relauncher_sync_fd.get(), "", 1)) != 1) {
     PLOG(ERROR) << "write";
     return;
   }
 
-  // Wait the SIGUSR2 signal to happen.
-  struct signalfd_siginfo si;
-  HANDLE_EINTR(read(usr2_fd, &si, sizeof(si)));
+  // Wait for the parent to exit
+  parentWaiter.Wait();
 }
 
 int LaunchProgram(const StringVector& relauncher_args,

+ 0 - 8
spec/api-app-spec.js

@@ -217,14 +217,6 @@ describe('app module', () => {
     let server = null
     const socketPath = process.platform === 'win32' ? '\\\\.\\pipe\\electron-app-relaunch' : '/tmp/electron-app-relaunch'
 
-    // TODO(alexeykuzmin): [Ch68] Fails on Linux.
-    // Enable the test back.
-    before(function () {
-      if (process.platform === 'linux') {
-        this.skip()
-      }
-    })
-
     beforeEach(done => {
       fs.unlink(socketPath, () => {
         server = net.createServer()