yet unheard of edge-case.
[ardour.git] / libs / pbd / system_exec.cc
index b11ef1ce0ef6fe2144c39cb9f940e9f93591cb9a..60e73badfcf19eb567ebe72f91a2a63253608819 100644 (file)
@@ -55,7 +55,10 @@ using namespace std;
 using namespace PBD;
 
 static void * interposer_thread (void *arg);
+
+#ifndef PLATFORM_WINDOWS /* POSIX Process only */
 static void close_fd (int& fd) { if (fd >= 0) ::close (fd); fd = -1; }
+#endif
 
 #if (!defined PLATFORM_WINDOWS && defined NO_VFORK)
 /*
@@ -195,10 +198,13 @@ SystemExec::SystemExec (std::string command, const std::map<char, std::string> s
 {
        init ();
        make_argp_escaped(command, subs);
-       if (!find_file (Searchpath (Glib::getenv ("PATH")), argp[0], cmd)) {
-               // not found in path - use as-is
-               cmd = argp[0];
+
+       if (find_file (Searchpath (Glib::getenv ("PATH")), argp[0], cmd)) {
+               // argp[0] exists in $PATH` - set it to the actual path where it was found
+               free (argp[0]);
+               argp[0] = strdup(cmd.c_str ());
        }
+       // else argp[0] not found in path - leave it as-is, it might be an absolute path
 
        // Glib::find_program_in_path () is only available in Glib >= 2.28
        // cmd = Glib::find_program_in_path (argp[0]);
@@ -281,13 +287,13 @@ SystemExec::~SystemExec ()
        terminate ();
        if (envp) {
                for (int i=0;envp[i];++i) {
-                 free(envp[i]);
+                       free(envp[i]);
                }
                free (envp);
        }
        if (argp) {
                for (int i=0;argp[i];++i) {
-                 free(argp[i]);
+                       free(argp[i]);
                }
                free (argp);
        }
@@ -410,8 +416,7 @@ int
 SystemExec::wait (int options)
 {
        while (is_running()) {
-               WaitForSingleObject(pid->hProcess, INFINITE);
-               Sleep(20);
+               WaitForSingleObject(pid->hProcess, 40);
        }
        return 0;
 }
@@ -419,7 +424,12 @@ SystemExec::wait (int options)
 bool
 SystemExec::is_running ()
 {
-       return pid?true:false;
+       if (!pid) return false;
+       DWORD exit_code;
+       if (GetExitCodeProcess(pid->hProcess, &exit_code)) {
+               if (exit_code == STILL_ACTIVE) return true;
+       }
+       return false;
 }
 
 int
@@ -802,6 +812,10 @@ SystemExec::start (int stderr_mode, const char *vfork_exec_wrapper)
 #else
        signal(SIGPIPE, SIG_DFL);
 #endif
+       if (!vfork_exec_wrapper) {
+               error << _("Cannot start external process, no vfork wrapper") << endmsg;
+               return -1;
+       }
 
        int good_fds[2] = { pok[1],  -1 };
        close_allv(good_fds);
@@ -864,7 +878,16 @@ SystemExec::output_interposer()
        for (;fcntl(rfd, F_GETFL)!=-1;) {
                r = read(rfd, buf, sizeof(buf));
                if (r < 0 && (errno == EINTR || errno == EAGAIN)) {
-                       ::usleep(1000);
+                       fd_set rfds;
+                       struct timeval tv;
+                       FD_ZERO(&rfds);
+                       FD_SET(rfd, &rfds);
+                       tv.tv_sec = 0;
+                       tv.tv_usec = 10000;
+                       int rv = select(1, &rfds, NULL, NULL, &tv);
+                       if (rv == -1) {
+                               break;
+                       }
                        continue;
                }
                if (r <= 0) {