X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fsystem_exec.cc;h=90c7294f5533fae89ad0ea37ec60e942818cf6a6;hb=aac5f4c6d67d0ca782f12d355e853d35e58924b9;hp=eb81c5fcb2158d040a11532561b2154d9b37f6a0;hpb=1053529e4fddcd00891cbbc08cf4107e8335f873;p=ardour.git diff --git a/gtk2_ardour/system_exec.cc b/gtk2_ardour/system_exec.cc index eb81c5fcb2..90c7294f55 100644 --- a/gtk2_ardour/system_exec.cc +++ b/gtk2_ardour/system_exec.cc @@ -38,7 +38,7 @@ using namespace std; void * interposer_thread (void *arg); -static void close_fd (int* fd) { if (!fd) return; if (*fd >= 0) ::close (*fd); *fd = -1; } +static void close_fd (int& fd) { if (fd >= 0) ::close (fd); fd = -1; } SystemExec::SystemExec (std::string c, std::string a) : cmd(c) @@ -414,19 +414,33 @@ void SystemExec::terminate () { ::pthread_mutex_lock(&write_lock); + + /* close stdin in an attempt to get the child to exit cleanly. + */ + close_stdin(); + if (pid) { ::usleep(50000); sched_yield(); wait(WNOHANG); } + /* 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(50000); sched_yield(); wait(WNOHANG); } + + /* if pid is non-zero, the child task is STILL executing after being + * sent SIGTERM. Act tough ... send SIGKILL + */ + if (pid) { ::fprintf(stderr, "Process is still running! trying SIGKILL\n"); ::kill(pid, SIGKILL); @@ -442,15 +456,23 @@ int SystemExec::wait (int options) { int status=0; + int ret; + if (pid==0) return -1; - if (pid==::waitpid(pid, &status, options)) { + + ret = waitpid (pid, &status, options); + + if (ret == pid) { if (WEXITSTATUS(status) || WIFSIGNALED(status)) { pid=0; } } else { - if (errno == ECHILD) { - pid=0; - } + if (ret != 0) { + if (errno == ECHILD) { + /* no currently running children, reset pid */ + pid=0; + } + } /* else the process is still running */ } return status; } @@ -488,18 +510,18 @@ SystemExec::start (int stderr_mode) pid=r; /* check if execve was successful. */ - close_fd(&pok[1]); + close_fd(pok[1]); char buf; for ( ;; ) { ssize_t n = ::read(pok[0], &buf, 1 ); if ( n==1 ) { /* child process returned from execve */ pid=0; - close_fd(&pok[0]); - close_fd(&pin[1]); - close_fd(&pin[0]); - close_fd(&pout[1]); - close_fd(&pout[0]); + close_fd(pok[0]); + close_fd(pin[1]); + close_fd(pin[0]); + close_fd(pout[1]); + close_fd(pout[0]); pin[1] = -1; return -3; } else if ( n==-1 ) { @@ -508,7 +530,7 @@ SystemExec::start (int stderr_mode) } break; } - close_fd(&pok[0]); + close_fd(pok[0]); /* child started successfully */ #if 0 @@ -524,17 +546,17 @@ SystemExec::start (int stderr_mode) } if (r == 0) { /* 2nd child process - catch stdout */ - close_fd(&pin[1]); - close_fd(&pout[1]); + close_fd(pin[1]); + close_fd(pout[1]); output_interposer(); exit(0); } - close_fd(&pout[1]); - close_fd(&pin[0]); - close_fd(&pout[0]); + close_fd(pout[1]); + close_fd(pin[0]); + close_fd(pout[0]); #else /* use pthread */ - close_fd(&pout[1]); - close_fd(&pin[0]); + close_fd(pout[1]); + close_fd(pin[0]); int rv = pthread_create(&thread_id_tt, NULL, interposer_thread, this); thread_active=true; @@ -548,15 +570,15 @@ SystemExec::start (int stderr_mode) } /* child process - exec external process */ - close_fd(&pok[0]); + close_fd(pok[0]); ::fcntl(pok[1], F_SETFD, FD_CLOEXEC); - close_fd(&pin[1]); + close_fd(pin[1]); if (pin[0] != STDIN_FILENO) { ::dup2(pin[0], STDIN_FILENO); } - close_fd(&pin[0]); - close_fd(&pout[0]); + close_fd(pin[0]); + close_fd(pout[0]); if (pout[1] != STDOUT_FILENO) { ::dup2(pout[1], STDOUT_FILENO); } @@ -574,7 +596,7 @@ SystemExec::start (int stderr_mode) } if (pout[1] != STDOUT_FILENO && pout[1] != STDERR_FILENO) { - close_fd(&pout[1]); + close_fd(pout[1]); } if (nicelevel !=0) { @@ -601,7 +623,7 @@ SystemExec::start (int stderr_mode) /* if we reach here something went wrong.. */ char buf = 0; (void) ::write(pok[1], &buf, 1 ); - close_fd(&pok[1]); + close_fd(pok[1]); exit(-1); return -1; } @@ -614,7 +636,7 @@ SystemExec::output_interposer() ssize_t r; unsigned long l = 1; - ioctl(rfd, FIONBIO, &l); // set non-blocking I/O + ioctl(rfd, FIONBIO, &l); // set non-blocking I/O for (;fcntl(rfd, F_GETFL)!=-1;) { r = read(rfd, buf, sizeof(buf)); @@ -636,17 +658,18 @@ void SystemExec::close_stdin() { if (pin[1]<0) return; - close_fd(&pin[0]); - close_fd(&pin[1]); - close_fd(&pout[0]); - close_fd(&pout[1]); + close_fd(pin[0]); + close_fd(pin[1]); + close_fd(pout[0]); + close_fd(pout[1]); } int SystemExec::write_to_stdin(std::string d, size_t len) { const char *data; - size_t r,c; + ssize_t r; + size_t c; ::pthread_mutex_lock(&write_lock); data=d.c_str(); @@ -661,7 +684,7 @@ SystemExec::write_to_stdin(std::string d, size_t len) sleep(1); continue; } - if (r != (len-c)) { + if ((size_t) r != (len-c)) { ::pthread_mutex_unlock(&write_lock); return c; }