X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=libs%2Fpbd%2Fsystem_exec.cc;h=351e4ee066ae118f2f69e0e64de6cf2b90715f42;hb=1ce58ad90aab58bca10af9c448b8e186ac532480;hp=811bd43d3907aded2701ba02581aa79c2f3186b8;hpb=4b0933938f46fbafeaab1a5c0ad953f0eac53df6;p=ardour.git diff --git a/libs/pbd/system_exec.cc b/libs/pbd/system_exec.cc index 811bd43d39..351e4ee066 100644 --- a/libs/pbd/system_exec.cc +++ b/libs/pbd/system_exec.cc @@ -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) /* @@ -167,6 +170,7 @@ SystemExec::init () stdinP[0] = stdinP[1] = INVALID_HANDLE_VALUE; stdoutP[0] = stdoutP[1] = INVALID_HANDLE_VALUE; stderrP[0] = stderrP[1] = INVALID_HANDLE_VALUE; + w_args = NULL; #endif } @@ -196,6 +200,29 @@ SystemExec::SystemExec (std::string command, const std::map s init (); make_argp_escaped(command, subs); +#ifdef PLATFORM_WINDOWS + if (argp[0] && strlen (argp[0]) > 0) { + std::string wa = argp[0]; + // only add quotes to command if required.. + if (argp[0][0] != '"' + && argp[0][strlen(argp[0])-1] != '"' + && strchr(argp[0], ' ')) { + wa = "\""; + wa += argp[0]; + wa += "\""; + } + // ...but always quote all args + for (int i = 1; argp[i]; ++i) { + std::string tmp (argp[i]); + while (tmp.find("\"") != std::string::npos) + tmp.replace(tmp.find("\""), 1, "\\\""); + wa += " \""; + wa += tmp; + wa += '"'; + } + w_args = strdup(wa.c_str()); + } +#else 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]); @@ -205,7 +232,7 @@ SystemExec::SystemExec (std::string command, const std::map s // Glib::find_program_in_path () is only available in Glib >= 2.28 // cmd = Glib::find_program_in_path (argp[0]); - +#endif make_envp(); } @@ -253,7 +280,7 @@ SystemExec::make_argp_escaped(std::string command, const std::map "\" - case '\0': + case '\0': case '\\': arg += '\\'; break; default : arg += '\\'; arg += c; break; } @@ -308,6 +335,22 @@ interposer_thread (void *arg) { return 0; } +string +SystemExec::to_s () const +{ +#ifdef PLATFORM_WINDOWS + return string (w_args ? w_args : ""); +#else + stringstream out; + if (argp) { + for (int i = 0; argp[i]; ++i) { + out << argp[i] << " "; + } + } + return out.str(); +#endif +} + #ifdef PLATFORM_WINDOWS /* Windows Process */ /* HELPER FUNCTIONS */ @@ -360,13 +403,10 @@ SystemExec::make_wargs(char **a) { char **tmp = ++a; while (tmp && *tmp) { wa.append(" \""); - std::string arg(*tmp); - size_t start_pos = 0; - while((start_pos = arg.find("\\", start_pos)) != std::string::npos) { - arg.replace(start_pos, 1, "\\\\"); - start_pos += 2; + wa.append(*tmp); + if (strlen(*tmp) > 0 && (*tmp)[strlen(*tmp) - 1] == '\\') { + wa.append("\\"); } - wa.append(arg); wa.append("\""); tmp++; } @@ -413,8 +453,7 @@ int SystemExec::wait (int options) { while (is_running()) { - WaitForSingleObject(pid->hProcess, INFINITE); - Sleep(20); + WaitForSingleObject(pid->hProcess, 40); } return 0; } @@ -422,7 +461,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 @@ -526,6 +570,7 @@ SystemExec::output_interposer() ReadStdout(data, bytesRead);/* EMIT SIGNAL */ } Terminated();/* EMIT SIGNAL */ + pthread_exit(0); } void @@ -644,7 +689,7 @@ SystemExec::terminate () /* if pid is non-zero, the child task is still executing (i.e. it did * not exit in response to stdin being closed). try to kill it. */ - + if (pid) { ::kill(pid, SIGTERM); ::usleep(250000); @@ -664,6 +709,7 @@ SystemExec::terminate () wait(); if (thread_active) pthread_join(thread_id_tt, NULL); thread_active = false; + assert(pid == 0); ::pthread_mutex_unlock(&write_lock); } @@ -805,6 +851,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); @@ -887,6 +937,7 @@ SystemExec::output_interposer() ReadStdout(rv, r);/* EMIT SIGNAL */ } Terminated();/* EMIT SIGNAL */ + pthread_exit(0); } void