Implement Relaunch on Linux

This commit is contained in:
Cheng Zhao 2016-06-02 16:54:21 +09:00
parent c3fe2dae9d
commit a3f39e9d0b
7 changed files with 104 additions and 12 deletions

View file

@ -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<brightray::ContentClient>
AtomMainDelegate::CreateContentClient() {

View file

@ -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<brightray::ContentClient> CreateContentClient() override;

View file

@ -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<std::string>& args,
const std::string& app) {
base::FilePath exe_path;
PathService::Get(base::FILE_EXE, &exe_path);
std::vector<std::string> 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;

View file

@ -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<std::string>& args,
const std::string& app) {
std::vector<std::string> 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];
}

View file

@ -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;
}

View file

@ -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 <signal.h>
#include <sys/prctl.h>
#include <sys/signalfd.h>
#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<std::string>& relauncher_args,
const std::string& program,
const std::vector<std::string>& args) {
std::vector<std::string> 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

View file

@ -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',