blob: 48752517335e5fb512d9a584f34be77e394194a8 [file] [log] [blame]
// Copyright 2015 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SHILL_PROCESS_MANAGER_H_
#define SHILL_PROCESS_MANAGER_H_
#include <map>
#include <string>
#include <vector>
#include <base/callback.h>
#include <base/cancelable_callback.h>
#include <base/files/file_path.h>
#include <base/lazy_instance.h>
#include <base/memory/weak_ptr.h>
#include <base/tracked_objects.h>
#include <chromeos/minijail/minijail.h>
#include <chromeos/process.h>
#include <chromeos/process_reaper.h>
namespace shill {
class EventDispatcher;
// The ProcessManager is a singleton providing process creation and
// asynchronous process termination. Need to initialize it once with
// Init method call.
class ProcessManager {
public:
virtual ~ProcessManager();
// This is a singleton -- use ProcessManager::GetInstance()->Foo().
static ProcessManager* GetInstance();
// Register async signal handler and setup process reaper.
virtual void Init(EventDispatcher* dispatcher);
// Create and start a process for |program| with |arguments|. |enivronment|
// variables will be setup in the child process before exec the |program|.
// |terminate_with_parent| is used to indicate if child process should
// self terminate if the parent process exits. |exit_callback| will be
// invoked when child process exits (not terminated by us). Return -1
// if failed to start the process, otherwise, return the pid of the child
// process.
virtual pid_t StartProcess(
const tracked_objects::Location& from_here,
const base::FilePath& program,
const std::vector<std::string>& arguments,
const std::map<std::string, std::string>& environment,
bool terminate_with_parent,
const base::Callback<void(int)>& exit_callback);
// Same as above, except the spawned process will be started in a minijail.
virtual pid_t StartProcessInMinijail(
const tracked_objects::Location& from_here,
const base::FilePath& program,
const std::vector<std::string>& arguments,
const std::string& user,
const std::string& group,
uint64_t capmask,
const base::Callback<void(int)>& exit_callback);
// Stop the given |pid|. Previously registered |exit_callback| will be
// unregistered, since the caller is not interested in this process anymore
// and that callback might not be valid by the time this process terminates.
// This will attempt to terminate the child process by sending a SIGTERM
// signal first. If the process doesn't terminate within a certain time,
// ProcessManager will attempt to send a SIGKILL signal. It will give up
// with an error log If the process still doesn't terminate within a certain
// time.
virtual bool StopProcess(pid_t pid);
protected:
ProcessManager();
private:
friend class ProcessManagerTest;
friend struct base::DefaultLazyInstanceTraits<ProcessManager>;
using TerminationTimeoutCallback = base::CancelableClosure;
// Invoked when process |pid| exited.
void OnProcessExited(pid_t pid, const siginfo_t& info);
// Invoked when process |pid| did not terminate within a certain timeout.
// |kill_signal| indicates the signal used for termination. When it is set
// to true, SIGKILL was used to terminate the process, otherwise, SIGTERM
// was used.
void ProcessTerminationTimeoutHandler(pid_t pid, bool kill_signal);
// Send a termination signal to process |pid|. If |kill_signal| is set to
// true, SIGKILL is sent, otherwise, SIGTERM is sent. After signal is sent,
// |pid| and timeout handler is added to |pending_termination_processes_|
// list, to make sure process |pid| does exit in timely manner.
bool TerminateProcess(pid_t pid, bool kill_signal);
// Used to watch processes.
chromeos::AsynchronousSignalHandler async_signal_handler_;
chromeos::ProcessReaper process_reaper_;
EventDispatcher* dispatcher_;
chromeos::Minijail* minijail_;
// Processes to watch for the caller.
std::map<pid_t, base::Callback<void(int)>> watched_processes_;
// Processes being terminated by us. Use a timer to make sure process
// does exit, log an error if it failed to exit within a specific timeout.
std::map<pid_t, std::unique_ptr<TerminationTimeoutCallback>>
pending_termination_processes_;
base::WeakPtrFactory<ProcessManager> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(ProcessManager);
};
} // namespace shill
#endif // SHILL_PROCESS_MANAGER_H_