diff options
author | Shinichiro Hamaji <shinichiro.hamaji@gmail.com> | 2015-07-02 01:42:31 +0900 |
---|---|---|
committer | Shinichiro Hamaji <shinichiro.hamaji@gmail.com> | 2015-07-03 14:16:46 +0900 |
commit | 62b16e7b9424f88e4907a6879d15ee832ef49477 (patch) | |
tree | a43a61c7a49218a59ddaa78e4eb2b66df8a9fa61 | |
parent | e1113ebeb184e5f6f135a3b0aa43309cc636c336 (diff) | |
download | android_build_kati-62b16e7b9424f88e4907a6879d15ee832ef49477.tar.gz android_build_kati-62b16e7b9424f88e4907a6879d15ee832ef49477.tar.bz2 android_build_kati-62b16e7b9424f88e4907a6879d15ee832ef49477.zip |
[C++] Use vfork and exec instead of popen for $(shell)
-rw-r--r-- | func.cc | 51 |
1 files changed, 50 insertions, 1 deletions
@@ -16,10 +16,14 @@ #include "func.h" +#include <errno.h> #include <glob.h> #include <limits.h> #include <stdio.h> #include <stdlib.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> #include <algorithm> #include <iterator> @@ -426,6 +430,48 @@ static string SortWordsInString(StringPiece s) { } #endif +static void RunCommand(const string& cmd, string* s) { + int pipefd[2]; + if (pipe(pipefd) != 0) + PERROR("pipe failed"); + int pid; + if ((pid = vfork())) { + close(pipefd[1]); + while (true) { + int status; + int result = waitpid(pid, &status, WNOHANG); + if (result < 0) + PERROR("waitpid failed"); + + while (true) { + char buf[4096]; + ssize_t r = read(pipefd[0], buf, 4096); + if (r < 0) + PERROR("read failed"); + if (r == 0) + break; + s->append(buf, buf+r); + } + + if (result != 0) { + break; + } + } + close(pipefd[0]); + } else { + close(pipefd[0]); + if (dup2(pipefd[1], 1) < 0) + PERROR("dup2 failed"); + close(pipefd[1]); + + const char* argv[] = { + // TODO: Handle $(SHELL). + "/bin/sh", "-c", cmd.c_str(), NULL + }; + execvp(argv[0], const_cast<char**>(argv)); + } +} + void ShellFunc(const vector<Value*>& args, Evaluator* ev, string* s) { shared_ptr<string> cmd = args[0]->Eval(ev); if (ev->avoid_io()) { @@ -448,9 +494,9 @@ void ShellFunc(const vector<Value*>& args, Evaluator* ev, string* s) { return; #endif - COLLECT_STATS_WITH_SLOW_REPORT("func shell time", cmd->c_str()); string out; +#if 0 // TODO: Handle $(SHELL). FILE* fp = popen(cmd->c_str(), "r"); while (true) { @@ -462,6 +508,9 @@ void ShellFunc(const vector<Value*>& args, Evaluator* ev, string* s) { break; } } +#else + RunCommand(*cmd, &out); +#endif while (out[out.size()-1] == '\n') out.pop_back(); |