]> git.tdb.fi Git - builder.git/blobdiff - source/externaltask.cpp
Use default member initializers and constructor delegation
[builder.git] / source / externaltask.cpp
index 257d1318fb22a42d31a5e2ed04e95424cb0a80ae..37a36d39150da641b3a39e91d5c0fb866576af02 100644 (file)
@@ -1,11 +1,9 @@
 #include <cstdlib>
-#include <unistd.h>
-#include <sys/wait.h>
 #include <msp/fs/dir.h>
 #include <msp/io/console.h>
 #include <msp/io/file.h>
 #include <msp/io/print.h>
-#include <msp/time/units.h>
+#include <msp/time/timedelta.h>
 #include "externaltask.h"
 
 using namespace std;
@@ -13,12 +11,7 @@ using namespace Msp;
 
 ExternalTask::ExternalTask(const Arguments &a, const FS::Path &wd):
        argv(a),
-       work_dir(wd),
-       process(0),
-       exit_code(-1),
-       stdout_action(PASSTHROUGH),
-       stderr_action(PASSTHROUGH),
-       capture_pipe(0)
+       work_dir(wd)
 {
        if(argv.empty())
                throw invalid_argument("ExternalTask::ExternalTask");
@@ -32,20 +25,20 @@ ExternalTask::~ExternalTask()
 string ExternalTask::get_command() const
 {
        string cmd;
-       for(vector<string>::const_iterator i=argv.begin(); i!=argv.end(); ++i)
+       for(const string &a: argv)
        {
-               if(i!=argv.begin())
+               if(!cmd.empty())
                        cmd += ' ';
 
-               for(string::const_iterator j=i->begin(); j!=i->end(); ++j)
+               for(char c: a)
                {
-                       if(*j=='"' || *j=='\'' || *j==' ' || *j=='\\' || *j=='&')
+                       if(c=='"' || c=='\'' || c==' ' || c=='\\' || c=='&')
                                cmd += '\\';
-                       cmd += *j;
+                       cmd += c;
                }
        }
 
-       if(!stdin_file.empty())
+       if(stdin_action==REDIRECT)
        {
                cmd += " <";
                cmd += stdin_file.str();
@@ -70,9 +63,15 @@ void ExternalTask::start()
 
        process = new Process;
 
-       if(stdout_action==IGNORE || stderr_action==IGNORE)
+       if(stdin_action==IGNORE || stdout_action==IGNORE || stderr_action==IGNORE)
        {
-               devnull = new IO::File("/dev/null", IO::M_WRITE);
+#ifdef _WIN32
+               devnull = new IO::File("nul", IO::M_RDWR);
+#else
+               devnull = new IO::File("/dev/null", IO::M_RDWR);
+#endif
+               if(stdin_action==IGNORE)
+                       process->redirect_cin(*devnull);
                if(stdout_action==IGNORE)
                        process->redirect_cout(*devnull);
                if(stderr_action==IGNORE)
@@ -94,7 +93,7 @@ void ExternalTask::start()
                        process->redirect_cerr(*capture_pipe);
        }
 
-       if(!stdin_file.empty())
+       if(stdin_action==REDIRECT)
        {
                infile = new IO::File((work_dir/stdin_file).str());
                process->redirect_cin(*infile);
@@ -125,9 +124,9 @@ Task::Status ExternalTask::wait()
 
 Task::Status ExternalTask::do_wait(bool block)
 {
-       if(process)
+       while(process)
        {
-               if(process->wait(block))
+               if(process->wait(block && !capture_pipe))
                {
                        exit_code = process->get_exit_code();
                        delete process;
@@ -135,7 +134,7 @@ Task::Status ExternalTask::do_wait(bool block)
                }
 
                // Do this after waiting to avoid a race condition
-               while(capture_pipe && IO::poll(*capture_pipe, IO::P_INPUT, Time::zero))
+               while(capture_pipe && IO::poll(*capture_pipe, IO::P_INPUT, 10*Time::msec))
                {
                        char buf[1024];
                        unsigned len = capture_pipe->read(buf, sizeof(buf));
@@ -146,7 +145,10 @@ Task::Status ExternalTask::do_wait(bool block)
                }
 
                if(process)
-                       return RUNNING;
+               {
+                       if(!block)
+                               return RUNNING;
+               }
                else
                        signal_finished.emit(!exit_code);
        }
@@ -156,6 +158,7 @@ Task::Status ExternalTask::do_wait(bool block)
 
 void ExternalTask::set_stdin(const FS::Path &f)
 {
+       stdin_action = REDIRECT;
        stdin_file = f;
 }
 
@@ -179,11 +182,12 @@ void ExternalTask::set_stderr(StreamAction a)
        stderr_action = a;
 }
 
-string ExternalTask::run_and_capture_output(const Arguments &argv, const FS::Path &wd)
+string ExternalTask::run_and_capture_output(const Arguments &argv, const FS::Path &wd, bool capture_stderr)
 {
        ExternalTask task(argv, wd);
+       task.stdin_action = IGNORE;
        task.set_stdout(CAPTURE);
-       task.set_stderr(IGNORE);
+       task.set_stderr(capture_stderr ? CAPTURE : IGNORE);
        task.start();
        if(task.wait()!=SUCCESS)
                throw runtime_error(format("%s failed", argv.front()));