Repository: kudu Updated Branches: refs/heads/master b4de65a8a -> e81db65a4
Add option to set CWD to Subprocess This is useful for executing processes which must be run from a specific directory. Change-Id: I73dc4983b0074312623790ce026e6ad88439df89 Reviewed-on: http://gerrit.cloudera.org:8080/7176 Reviewed-by: Adar Dembo <[email protected]> Reviewed-by: Alexey Serbin <[email protected]> Tested-by: Kudu Jenkins Reviewed-by: Andrew Wong <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/kudu/repo Commit: http://git-wip-us.apache.org/repos/asf/kudu/commit/e81db65a Tree: http://git-wip-us.apache.org/repos/asf/kudu/tree/e81db65a Diff: http://git-wip-us.apache.org/repos/asf/kudu/diff/e81db65a Branch: refs/heads/master Commit: e81db65a427d5394329420e7edc430a677b77705 Parents: b4de65a Author: Dan Burkert <[email protected]> Authored: Tue Jun 13 15:32:41 2017 -0700 Committer: Dan Burkert <[email protected]> Committed: Wed Jun 14 20:20:10 2017 +0000 ---------------------------------------------------------------------- src/kudu/util/subprocess-test.cc | 20 ++++++++++++++++++++ src/kudu/util/subprocess.cc | 16 ++++++++++++++-- src/kudu/util/subprocess.h | 6 ++++++ 3 files changed, 40 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/kudu/blob/e81db65a/src/kudu/util/subprocess-test.cc ---------------------------------------------------------------------- diff --git a/src/kudu/util/subprocess-test.cc b/src/kudu/util/subprocess-test.cc index fb3d183..9e7e5cb 100644 --- a/src/kudu/util/subprocess-test.cc +++ b/src/kudu/util/subprocess-test.cc @@ -25,6 +25,7 @@ #include <gtest/gtest.h> #include "kudu/gutil/strings/substitute.h" +#include "kudu/util/path_util.h" #include "kudu/util/test_util.h" using std::string; @@ -136,6 +137,25 @@ TEST_F(SubprocessTest, TestEnvVars) { ASSERT_OK(p.Wait()); } +// Test that the the subprocesses CWD can be set. +TEST_F(SubprocessTest, TestCurrentDir) { + string dir_path = GetTestPath("d"); + string file_path = JoinPathSegments(dir_path, "f"); + ASSERT_OK(Env::Default()->CreateDir(dir_path)); + std::unique_ptr<WritableFile> file; + ASSERT_OK(Env::Default()->NewWritableFile(file_path, &file)); + + Subprocess p({ "/bin/ls", "f" }); + p.SetCurrentDir(dir_path); + p.ShareParentStdout(false); + ASSERT_OK(p.Start()); + ASSERT_OK(p.Wait()); + + int rc; + ASSERT_OK(p.GetExitStatus(&rc, nullptr)); + EXPECT_EQ(0, rc); +} + // Tests writing to the subprocess stdin. TEST_F(SubprocessTest, TestCallWithStdin) { string stdout; http://git-wip-us.apache.org/repos/asf/kudu/blob/e81db65a/src/kudu/util/subprocess.cc ---------------------------------------------------------------------- diff --git a/src/kudu/util/subprocess.cc b/src/kudu/util/subprocess.cc index 1f38b9f..5944cc8 100644 --- a/src/kudu/util/subprocess.cc +++ b/src/kudu/util/subprocess.cc @@ -50,9 +50,10 @@ #include "kudu/util/monotime.h" #include "kudu/util/path_util.h" #include "kudu/util/signal.h" -#include "kudu/util/stopwatch.h" #include "kudu/util/status.h" +#include "kudu/util/stopwatch.h" +using std::map; using std::string; using std::unique_ptr; using std::vector; @@ -418,6 +419,11 @@ Status Subprocess::Start() { // don't explicitly ignore any other signals in Kudu. ResetSigPipeHandlerToDefault(); + // Set the current working directory of the subprocess. + if (!cwd_.empty()) { + PCHECK(chdir(cwd_.c_str()) == 0); + } + // Set the environment for the subprocess. This is more portable than // using execvpe(), which doesn't exist on OS X. We rely on the 'p' // variant of exec to do $PATH searching if the executable specified @@ -680,10 +686,16 @@ Status Subprocess::DoWait(int* wait_status, WaitMode mode) { return Status::OK(); } -void Subprocess::SetEnvVars(std::map<std::string, std::string> env) { +void Subprocess::SetEnvVars(map<string, string> env) { + CHECK_EQ(state_, kNotStarted); env_ = std::move(env); } +void Subprocess::SetCurrentDir(string cwd) { + CHECK_EQ(state_, kNotStarted); + cwd_ = std::move(cwd); +} + void Subprocess::SetFdShared(int stdfd, bool share) { CHECK_EQ(state_, kNotStarted); CHECK_NE(fd_state_[stdfd], DISABLED); http://git-wip-us.apache.org/repos/asf/kudu/blob/e81db65a/src/kudu/util/subprocess.h ---------------------------------------------------------------------- diff --git a/src/kudu/util/subprocess.h b/src/kudu/util/subprocess.h index 9834e3a..2f5ad05 100644 --- a/src/kudu/util/subprocess.h +++ b/src/kudu/util/subprocess.h @@ -76,6 +76,11 @@ class Subprocess { // Repeated calls to this function replace earlier calls. void SetEnvVars(std::map<std::string, std::string> env); + // Set the initial current working directory of the subprocess. + // + // Must be set before starting the subprocess. + void SetCurrentDir(std::string cwd); + // Start the subprocess. Can only be called once. // // This returns a bad Status if the fork() fails. However, @@ -175,6 +180,7 @@ class Subprocess { int child_pid_; enum StreamMode fd_state_[3]; int child_fds_[3]; + std::string cwd_; // The cached wait status if Wait()/WaitNoBlock() has been called. // Only valid if state_ == kExited.
