relauncher_linux.cc 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. // Copyright (c) 2016 GitHub, Inc.
  2. // Use of this source code is governed by the MIT license that can be
  3. // found in the LICENSE file.
  4. #include "atom/browser/relauncher.h"
  5. #include <fcntl.h>
  6. #include <signal.h>
  7. #include <sys/prctl.h>
  8. #include <sys/signalfd.h>
  9. #include "base/files/file_util.h"
  10. #include "base/files/scoped_file.h"
  11. #include "base/logging.h"
  12. #include "base/posix/eintr_wrapper.h"
  13. #include "base/process/launch.h"
  14. namespace relauncher {
  15. namespace internal {
  16. void RelauncherSynchronizeWithParent() {
  17. base::ScopedFD relauncher_sync_fd(kRelauncherSyncFD);
  18. // Don't execute signal handlers of SIGUSR2.
  19. sigset_t mask;
  20. sigemptyset(&mask);
  21. sigaddset(&mask, SIGUSR2);
  22. if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
  23. PLOG(ERROR) << "sigprocmask";
  24. return;
  25. }
  26. // Create a signalfd that watches for SIGUSR2.
  27. int usr2_fd = signalfd(-1, &mask, 0);
  28. if (usr2_fd < 0) {
  29. PLOG(ERROR) << "signalfd";
  30. return;
  31. }
  32. // Send SIGUSR2 to current process when parent process ends.
  33. if (HANDLE_EINTR(prctl(PR_SET_PDEATHSIG, SIGUSR2)) != 0) {
  34. PLOG(ERROR) << "prctl";
  35. return;
  36. }
  37. // Write a '\0' character to the pipe.
  38. if (HANDLE_EINTR(write(relauncher_sync_fd.get(), "", 1)) != 1) {
  39. PLOG(ERROR) << "write";
  40. return;
  41. }
  42. // Wait the SIGUSR2 signal to happen.
  43. struct signalfd_siginfo si;
  44. HANDLE_EINTR(read(usr2_fd, &si, sizeof(si)));
  45. }
  46. int LaunchProgram(const StringVector& relauncher_args,
  47. const StringVector& argv) {
  48. // Redirect the stdout of child process to /dev/null, otherwise after
  49. // relaunch the child process will raise exception when writing to stdout.
  50. base::ScopedFD devnull(HANDLE_EINTR(open("/dev/null", O_WRONLY)));
  51. base::FileHandleMappingVector no_stdout;
  52. no_stdout.push_back(std::make_pair(devnull.get(), STDERR_FILENO));
  53. no_stdout.push_back(std::make_pair(devnull.get(), STDOUT_FILENO));
  54. base::LaunchOptions options;
  55. options.allow_new_privs = true;
  56. options.new_process_group = true; // detach
  57. options.fds_to_remap = &no_stdout;
  58. base::Process process = base::LaunchProcess(argv, options);
  59. return process.IsValid() ? 0 : 1;
  60. }
  61. } // namespace internal
  62. } // namespace relauncher