From a3f39e9d0b1ffee1a299e2799948ca8dc445f052 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 2 Jun 2016 16:54:21 +0900 Subject: [PATCH] Implement Relaunch on Linux --- atom/app/atom_main_delegate.cc | 2 + atom/app/atom_main_delegate.h | 2 + atom/browser/browser.cc | 12 ++++++ atom/browser/browser_mac.mm | 11 ----- atom/browser/relauncher.cc | 14 +++++- atom/browser/relauncher_linux.cc | 74 ++++++++++++++++++++++++++++++++ filenames.gypi | 1 + 7 files changed, 104 insertions(+), 12 deletions(-) create mode 100644 atom/browser/relauncher_linux.cc diff --git a/atom/app/atom_main_delegate.cc b/atom/app/atom_main_delegate.cc index dbd271239332..f4e0b6044481 100644 --- a/atom/app/atom_main_delegate.cc +++ b/atom/app/atom_main_delegate.cc @@ -158,6 +158,7 @@ int AtomMainDelegate::RunProcess( return -1; } +#if defined(OS_MACOSX) bool AtomMainDelegate::ShouldSendMachPort(const std::string& process_type) { return process_type != kRelauncherProcess; } @@ -166,6 +167,7 @@ bool AtomMainDelegate::DelaySandboxInitialization( const std::string& process_type) { return process_type == kRelauncherProcess; } +#endif std::unique_ptr AtomMainDelegate::CreateContentClient() { diff --git a/atom/app/atom_main_delegate.h b/atom/app/atom_main_delegate.h index 377665f629da..58a380bd7d5a 100644 --- a/atom/app/atom_main_delegate.h +++ b/atom/app/atom_main_delegate.h @@ -27,8 +27,10 @@ class AtomMainDelegate : public brightray::MainDelegate { int RunProcess( const std::string& process_type, const content::MainFunctionParams& main_function_params) override; +#if defined(OS_MACOSX) bool ShouldSendMachPort(const std::string& process_type) override; bool DelaySandboxInitialization(const std::string& process_type) override; +#endif // brightray::MainDelegate: std::unique_ptr CreateContentClient() override; diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index 093209ef7c47..92da10bc5a65 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -8,6 +8,7 @@ #include "atom/browser/atom_browser_main_parts.h" #include "atom/browser/native_window.h" +#include "atom/browser/relauncher.h" #include "atom/browser/window_list.h" #include "base/files/file_util.h" #include "base/message_loop/message_loop.h" @@ -33,6 +34,17 @@ Browser* Browser::Get() { return AtomBrowserMainParts::Get()->browser(); } +void Browser::Relaunch(const std::vector& args, + const std::string& app) { + base::FilePath exe_path; + PathService::Get(base::FILE_EXE, &exe_path); + + std::vector args_with_app(args); + args_with_app.insert(args_with_app.begin(), + app.empty() ? exe_path.value() : app); + relauncher::RelaunchApp(args_with_app); +} + void Browser::Quit() { if (is_quiting_) return; diff --git a/atom/browser/browser_mac.mm b/atom/browser/browser_mac.mm index 271b88de4ce0..4561eab8c950 100644 --- a/atom/browser/browser_mac.mm +++ b/atom/browser/browser_mac.mm @@ -8,27 +8,16 @@ #include "atom/browser/mac/atom_application_delegate.h" #include "atom/browser/mac/dict_util.h" #include "atom/browser/native_window.h" -#include "atom/browser/relauncher.h" #include "atom/browser/window_list.h" #include "base/mac/bundle_locations.h" #include "base/mac/foundation_util.h" #include "base/strings/sys_string_conversions.h" #include "brightray/common/application_info.h" -#include "brightray/common/mac/main_application_bundle.h" #include "net/base/mac/url_conversions.h" #include "url/gurl.h" namespace atom { -void Browser::Relaunch(const std::vector& args, - const std::string& app) { - std::vector args_with_app(args); - args_with_app.insert( - args_with_app.begin(), - app.empty() ? brightray::MainApplicationBundlePath().value() : app); - relauncher::RelaunchApp(args_with_app); -} - void Browser::Focus() { [[AtomApplication sharedApplication] activateIgnoringOtherApps:YES]; } diff --git a/atom/browser/relauncher.cc b/atom/browser/relauncher.cc index 47c77a119ad2..58c4d57df801 100644 --- a/atom/browser/relauncher.cc +++ b/atom/browser/relauncher.cc @@ -11,18 +11,24 @@ #include "base/files/file_util.h" #include "base/logging.h" #include "base/path_service.h" -#include "base/posix/eintr_wrapper.h" #include "base/process/launch.h" #include "base/strings/stringprintf.h" #include "content/public/common/content_paths.h" #include "content/public/common/content_switches.h" #include "content/public/common/main_function_params.h" +#if defined(OS_POSIX) +#include "base/posix/eintr_wrapper.h" +#endif + namespace relauncher { namespace internal { +#if defined(OS_POSIX) const int kRelauncherSyncFD = STDERR_FILENO + 1; +#endif + const char* kRelauncherTypeArg = "--type=relauncher"; const char* kRelauncherArgSeparator = "---"; @@ -59,6 +65,7 @@ bool RelaunchAppWithHelper(const std::string& helper, relaunch_args.insert(relaunch_args.end(), args.begin(), args.end()); +#if defined(OS_POSIX) int pipe_fds[2]; if (HANDLE_EINTR(pipe(pipe_fds)) != 0) { PLOG(ERROR) << "pipe"; @@ -85,9 +92,12 @@ bool RelaunchAppWithHelper(const std::string& helper, base::FileHandleMappingVector fd_map; fd_map.push_back( std::make_pair(pipe_write_fd.get(), internal::kRelauncherSyncFD)); +#endif base::LaunchOptions options; +#if defined(OS_POSIX) options.fds_to_remap = &fd_map; +#endif if (!base::LaunchProcess(relaunch_args, options).IsValid()) { LOG(ERROR) << "base::LaunchProcess failed"; return false; @@ -96,6 +106,7 @@ bool RelaunchAppWithHelper(const std::string& helper, // The relauncher process is now starting up, or has started up. The // original parent process continues. +#if defined(OS_POSIX) pipe_write_fd.reset(); // close(pipe_fds[1]); // Synchronize with the relauncher process. @@ -113,6 +124,7 @@ bool RelaunchAppWithHelper(const std::string& helper, // Since a byte has been successfully read from the relauncher process, it's // guaranteed to have set up its kqueue monitoring this process for exit. // It's safe to exit now. +#endif return true; } diff --git a/atom/browser/relauncher_linux.cc b/atom/browser/relauncher_linux.cc new file mode 100644 index 000000000000..7ad0c03cbd00 --- /dev/null +++ b/atom/browser/relauncher_linux.cc @@ -0,0 +1,74 @@ +// Copyright (c) 2016 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/relauncher.h" + +#include +#include +#include + +#include "atom/common/atom_command_line.h" +#include "base/files/file_util.h" +#include "base/logging.h" +#include "base/posix/eintr_wrapper.h" +#include "base/process/launch.h" + +namespace relauncher { + +namespace internal { + +void RelauncherSynchronizeWithParent() { + base::ScopedFD relauncher_sync_fd(kRelauncherSyncFD); + + // 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"; + return; + } + + // Send SIGUSR2 to current process when parent process ends. + if (HANDLE_EINTR(prctl(PR_SET_PDEATHSIG, SIGUSR2)) != 0) { + PLOG(ERROR) << "prctl"; + return; + } + + // Write a '\0' character to the pipe. + 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))); +} + +int LaunchProgram(const std::vector& relauncher_args, + const std::string& program, + const std::vector& args) { + std::vector argv; + argv.reserve(1 + args.size()); + argv.push_back(program); + argv.insert(argv.end(), args.begin(), args.end()); + + base::LaunchOptions options; + options.allow_new_privs = true; + options.new_process_group = true; // detach + base::Process process = base::LaunchProcess(argv, options); + return process.IsValid() ? 0 : 1; +} + +} // namespace internal + +} // namespace relauncher diff --git a/filenames.gypi b/filenames.gypi index 3cee4ca50c5b..0317aef6b105 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -225,6 +225,7 @@ 'atom/browser/net/url_request_fetch_job.h', 'atom/browser/node_debugger.cc', 'atom/browser/node_debugger.h', + 'atom/browser/relauncher_linux.cc', 'atom/browser/relauncher_mac.cc', 'atom/browser/relauncher.cc', 'atom/browser/relauncher.h',