diff options
author | Lukacs Berki <lberki@google.com> | 2016-04-27 11:17:51 +0000 |
---|---|---|
committer | Kristina Chodorow <kchodorow@google.com> | 2016-04-27 17:11:48 +0000 |
commit | 7494c920da2927c446872ff150abe5f37b24cabf (patch) | |
tree | 8d1e4a480e3c5b3ad410e7d9909f93c019063d30 /src/main/cpp/blaze_util_posix.cc | |
parent | 3f57a63c79527ca0c3343cb5172b3c61cd0f94d1 (diff) |
Use native process control on Windows to launch subprocesses.
This is necessary because msys2 signals don't work on native Win32 processes, for example, java.exe .
Forcefully terminating the process still doesn't work because it uses signals. It's a-coming.
--
MOS_MIGRATED_REVID=120903711
Diffstat (limited to 'src/main/cpp/blaze_util_posix.cc')
-rw-r--r-- | src/main/cpp/blaze_util_posix.cc | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/src/main/cpp/blaze_util_posix.cc b/src/main/cpp/blaze_util_posix.cc index 44ad43cb17..e7f85b28e3 100644 --- a/src/main/cpp/blaze_util_posix.cc +++ b/src/main/cpp/blaze_util_posix.cc @@ -12,7 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include <fcntl.h> #include <limits.h> +#include <signal.h> #include <sys/types.h> #include <unistd.h> @@ -20,6 +22,7 @@ #include "src/main/cpp/blaze_util_platform.h" #include "src/main/cpp/util/errors.h" #include "src/main/cpp/util/exit_code.h" +#include "src/main/cpp/util/file.h" namespace blaze { @@ -64,4 +67,73 @@ std::string ListSeparator() { return ":"; } bool SymlinkDirectories(const string &target, const string &link) { return symlink(target.c_str(), link.c_str()) == 0; } + +// Causes the current process to become a daemon (i.e. a child of +// init, detached from the terminal, in its own session.) We don't +// change cwd, though. +static void Daemonize(const string& daemon_output) { + // Don't call die() or exit() in this function; we're already in a + // child process so it won't work as expected. Just don't do + // anything that can possibly fail. :) + + signal(SIGHUP, SIG_IGN); + if (fork() > 0) { + // This second fork is required iff there's any chance cmd will + // open an specific tty explicitly, e.g., open("/dev/tty23"). If + // not, this fork can be removed. + _exit(blaze_exit_code::SUCCESS); + } + + setsid(); + + close(0); + close(1); + close(2); + + open("/dev/null", O_RDONLY); // stdin + // stdout: + if (open(daemon_output.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666) == -1) { + // In a daemon, no-one can hear you scream. + open("/dev/null", O_WRONLY); + } + dup(STDOUT_FILENO); // stderr (2>&1) +} + +int ExecuteDaemon(const string& exe, const std::vector<string>& args_vector, + const string& daemon_output, const string& server_dir) { + int fds[2]; + if (pipe(fds)) { + pdie(blaze_exit_code::INTERNAL_ERROR, "pipe creation failed"); + } + int child = fork(); + if (child == -1) { + pdie(blaze_exit_code::INTERNAL_ERROR, "fork() failed"); + } else if (child > 0) { // we're the parent + close(fds[1]); // parent keeps only the reading side + return fds[0]; + } else { + close(fds[0]); // child keeps only the writing side + } + + Daemonize(daemon_output); + string pid_string = ToString(getpid()); + string pid_file = blaze_util::JoinPath(server_dir, ServerPidFile()); + string pid_symlink_file = + blaze_util::JoinPath(server_dir, ServerPidSymlink()); + + if (!WriteFile(pid_string, pid_file)) { + // The exit code does not matter because we are already in the daemonized + // server. The output of this operation will end up in jvm.out . + pdie(0, "Cannot write PID file"); + } + + UnlinkPath(pid_symlink_file.c_str()); + if (symlink(pid_string.c_str(), pid_symlink_file.c_str()) < 0) { + pdie(0, "Cannot write PID symlink"); + } + + ExecuteProgram(exe, args_vector); + pdie(0, "Cannot execute %s", exe.c_str()); +} + } // namespace blaze. |