relauncher_linux.cc 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  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 "shell/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/process/launch.h"
  13. #include "base/synchronization/waitable_event.h"
  14. namespace relauncher::internal {
  15. // this is global to be visible to the sa_handler
  16. base::WaitableEvent parentWaiter;
  17. void RelauncherSynchronizeWithParent() {
  18. base::ScopedFD relauncher_sync_fd(kRelauncherSyncFD);
  19. static const auto signum = SIGUSR2;
  20. // send signum to current process when parent process ends.
  21. if (HANDLE_EINTR(prctl(PR_SET_PDEATHSIG, signum)) != 0) {
  22. PLOG(ERROR) << "prctl";
  23. return;
  24. }
  25. // set up a signum handler
  26. struct sigaction action;
  27. memset(&action, 0, sizeof(action));
  28. action.sa_handler = [](int /*signum*/) { parentWaiter.Signal(); };
  29. if (sigaction(signum, &action, nullptr) != 0) {
  30. PLOG(ERROR) << "sigaction";
  31. return;
  32. }
  33. // write a '\0' character to the pipe to the parent process.
  34. // this is how the parent knows that we're ready for it to exit.
  35. if (HANDLE_EINTR(write(relauncher_sync_fd.get(), "", 1)) != 1) {
  36. PLOG(ERROR) << "write";
  37. return;
  38. }
  39. // Wait for the parent to exit
  40. parentWaiter.Wait();
  41. }
  42. int LaunchProgram(const StringVector& relauncher_args,
  43. const StringVector& argv) {
  44. // Redirect the stdout of child process to /dev/null, otherwise after
  45. // relaunch the child process will raise exception when writing to stdout.
  46. base::ScopedFD devnull(HANDLE_EINTR(open("/dev/null", O_WRONLY)));
  47. base::LaunchOptions options;
  48. options.allow_new_privs = true;
  49. options.new_process_group = true; // detach
  50. options.fds_to_remap.emplace_back(devnull.get(), STDERR_FILENO);
  51. options.fds_to_remap.emplace_back(devnull.get(), STDOUT_FILENO);
  52. base::Process process = base::LaunchProcess(argv, options);
  53. return process.IsValid() ? 0 : 1;
  54. }
  55. } // namespace relauncher::internal