blob: b13fc174fbea1091bcf8a6625d2eae6602f2d2dc [file] [log] [blame]
// Copyright 2013 The Goma 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 DEVTOOLS_GOMA_CLIENT_SPAWNER_H_
#define DEVTOOLS_GOMA_CLIENT_SPAWNER_H_
#include <stdint.h>
#include <string>
#include <vector>
#ifdef _WIN32
#include "config_win.h"
#endif
using std::string;
namespace devtools_goma {
// A subclass of Spawner spawns a child process. It takes a file as stdin
// for the child process, and redirects the child process' stdout to another
// file.
//
// Spawning a process may cause strange behavior under multi-threaded
// environment especially in posix, and prohibited in our code base.
// You might only need to use a subclass of this class in:
// gomacc (not dispatcher) or subprocess_impl.
class Spawner {
public:
enum WaitPolicy {
NO_HANG = 0,
WAIT_INFINITE = 1,
NEED_KILL = 2,
};
enum ConsoleOutputOption {
MERGE_STDOUT_STDERR = 0,
STDOUT_ONLY = 1,
};
enum class ProcessStatus {
RUNNING,
EXITED,
};
static const int kInvalidPid;
virtual ~Spawner() {}
// Set files for redirection.
// If either of |stdin_filename|, |stdout_filename|, or |stderr_filename| is
// not empty, it is used as stdin, stdout, or stderr of the child process.
// |option| to specify which console outputs are stored to |stdout_filename|
// when |stderr_filename| is empty.
// Note: this must be called BEFORE the Run method.
// Note: you cannot use this method with SetConsoleOutputBuffer.
void SetFileRedirection(const string& stdin_filename,
const string& stdout_filename,
const string& stderr_filename,
ConsoleOutputOption option) {
stdin_filename_ = stdin_filename;
stdout_filename_ = stdout_filename;
stderr_filename_ = stderr_filename;
console_output_option_ = option;
}
// Set buffer to redirect stdout and stderr.
// |option| to specify which console outputs are stored to |console_output|.
// Note: this must be called BEFORE the Run method.
// Note: if |stdout_filename| or |stderr_filename| are set by
// SetFileRedirection, you cannot use this method.
void SetConsoleOutputBuffer(string* console_output,
ConsoleOutputOption option) {
console_output_ = console_output;
console_output_option_ = option;
}
// If |detach| is true, the Spawner detaches the process.
// Note: this must be called BEFORE the Run method.
void SetDetach(bool detach) { detach_ = detach; }
// If |keep| is true, the Spawner does not override env
// (e.g. TMP and/or TEMP are kept).
void SetKeepEnv(bool keep) { keep_env_ = keep; }
// If |umask| is positive value, it is used as umask of the process.
// Note: this feature only works on SpawnerPosix.
void SetUmask(int32_t umask) { umask_ = umask; }
// Spawns a child process.
// On Success,
// * returns spawned process id in SpawnerWin.
// * returns a monitor process id that spawned |cmd| in SpawnerPosix.
// Note: SpawnerPosix::Run first spawn a monitor process, and then monitor
// process spawn a child process not to inherit signal handlers.
// Returns kInvalidPid on non fatal error, and dies with fatal error. |prog|
// is a program name, |args| is its arguments, |envs| is its environment, and
// |cwd| is a current working directory.
virtual int Run(const string& cmd, const std::vector<string>& args,
const std::vector<string>& envs, const string& cwd) = 0;
// Kills the process.
virtual ProcessStatus Kill() = 0;
// Waits for process termination.
// If |wait_policy| is NO_HANG, it just returns current status.
// If |wait_policy| is WAIT_INFINITE, it wait until the process finishes.
// If |wait_policy| is NEED_KILL, it kills process if the process is running.
virtual ProcessStatus Wait(WaitPolicy wait_policy) = 0;
// Returns true if the process is running.
virtual bool IsChildRunning() const = 0;
// Returns true if the process is signaled.
virtual bool IsSignaled() const = 0;
// Set the process is signaled.
virtual void SetSignaled() = 0;
// Returns the exit code of the process.
virtual int ChildStatus() const = 0;
// Returns the memory used during the execution.
// Returns -1 if this info is not available.
virtual int64_t ChildMemKb() const = 0;
// Returns the signal that caused the child process to terminate.
// (Only meaningful for SpawnerPosix).
virtual int ChildTermSignal() const = 0;
protected:
Spawner() :
console_output_(NULL), detach_(false), keep_env_(false), umask_(-1),
console_output_option_(MERGE_STDOUT_STDERR) {}
string stdin_filename_, stdout_filename_, stderr_filename_;
string* console_output_;
bool detach_;
bool keep_env_;
int32_t umask_;
ConsoleOutputOption console_output_option_;
private:
DISALLOW_COPY_AND_ASSIGN(Spawner);
};
inline std::ostream& operator<<(std::ostream& os,
Spawner::ProcessStatus status) {
switch (status) {
case Spawner::ProcessStatus::RUNNING:
return os << "RUNNING";
case Spawner::ProcessStatus::EXITED:
return os << "EXITED";
}
}
} // namespace devtools_goma
#endif // DEVTOOLS_GOMA_CLIENT_SPAWNER_H_