diff --git a/librz/core/cmd/cmd.c b/librz/core/cmd/cmd.c index 1f1900450b5..ac7fb7dfe2d 100644 --- a/librz/core/cmd/cmd.c +++ b/librz/core/cmd/cmd.c @@ -3079,6 +3079,7 @@ static char *system_exec_stdin(bool is_pipe, int argc, char **argv, const ut8 *i rz_subprocess_stdin_write(proc, input, input_len); rz_subprocess_wait(proc, UT64_MAX); + rz_subprocess_ret(proc); output = (char *)rz_subprocess_out(proc, length); rz_subprocess_free(proc); diff --git a/librz/util/subprocess.c b/librz/util/subprocess.c index dac4fe67ffa..18bec57a046 100644 --- a/librz/util/subprocess.c +++ b/librz/util/subprocess.c @@ -41,6 +41,7 @@ struct rz_subprocess_t { HANDLE stderr_read; HANDLE proc; int ret; + RzThreadSemaphore *ret_sem; RzStrBuf out; RzStrBuf err; }; @@ -326,6 +327,11 @@ RZ_API RZ_OWN RzSubprocess *rz_subprocess_start_opt(RZ_NONNULL const RzSubproces goto error; } proc->ret = -1; + proc->ret_sem = rz_th_sem_new(0); + if (!proc->ret_sem) { + rz_sys_perror("rz_th_sem_new"); + goto error; + } proc->stdout_read = NULL; proc->stderr_read = NULL; proc->stdin_write = NULL; @@ -456,6 +462,7 @@ RZ_API RZ_OWN RzSubprocess *rz_subprocess_start_opt(RZ_NONNULL const RzSubproces return proc; error: if (proc) { + rz_th_sem_free(proc->ret_sem); if (proc->stderr_read && proc->stderr_read != proc->stdout_read) { CloseHandle(proc->stderr_read); } @@ -619,6 +626,7 @@ static RzSubprocessWaitReason subprocess_wait(RzSubprocess *proc, ut64 timeout_m if (GetExitCodeProcess(proc->proc, &exit_code)) { proc->ret = exit_code; } + rz_th_sem_post(proc->ret_sem); continue; } break; @@ -695,6 +703,7 @@ RZ_API void rz_subprocess_free(RzSubprocess *proc) { if (!proc) { return; } + rz_th_sem_free(proc->ret_sem); if (proc->stdin_write) { CloseHandle(proc->stdin_write); } @@ -738,8 +747,8 @@ struct rz_subprocess_t { int stdin_fd; int stdout_fd; int stderr_fd; - int killpipe[2]; int ret; + RzThreadSemaphore *ret_sem; RzStrBuf out; RzStrBuf err; int master_fd; ///< Needed to check whether PTY @@ -806,8 +815,7 @@ static void *sigchld_th(void *th) { } else { proc->ret = -1; } - ut8 r = 0; - rz_xwrite(proc->killpipe[1], &r, 1); + rz_th_sem_post(proc->ret_sem); subprocess_unlock(); } } @@ -1048,8 +1056,12 @@ RZ_API RZ_OWN RzSubprocess *rz_subprocess_start_opt(RZ_NONNULL const RzSubproces if (!proc) { goto error; } - proc->killpipe[0] = proc->killpipe[1] = -1; proc->ret = -1; + proc->ret_sem = rz_th_sem_new(0); + if (!proc->ret_sem) { + perror("rz_th_sem_new"); + goto error; + } proc->stdin_fd = -1; proc->stdout_fd = -1; proc->stderr_fd = -1; @@ -1058,15 +1070,6 @@ RZ_API RZ_OWN RzSubprocess *rz_subprocess_start_opt(RZ_NONNULL const RzSubproces rz_strbuf_init(&proc->out); rz_strbuf_init(&proc->err); - if (rz_sys_pipe(proc->killpipe, true) == -1) { - perror("pipe"); - goto error; - } - if (fcntl(proc->killpipe[1], F_SETFL, O_NONBLOCK) < 0) { - perror("fcntl"); - goto error; - } - int stdin_pipe[2] = { -1, -1 }; int stdout_pipe[2] = { -1, -1 }; int stderr_pipe[2] = { -1, -1 }; @@ -1174,11 +1177,8 @@ RZ_API RZ_OWN RzSubprocess *rz_subprocess_start_opt(RZ_NONNULL const RzSubproces return proc; error: free(argv); - if (proc && proc->killpipe[0] == -1) { - rz_sys_pipe_close(proc->killpipe[0]); - } - if (proc && proc->killpipe[1] == -1) { - rz_sys_pipe_close(proc->killpipe[1]); + if (proc) { + rz_th_sem_free(proc->ret_sem); } if (stderr_pipe[0] != -1 && stderr_pipe[0] != stdout_pipe[0] && !(proc && stderr_pipe[0] == proc->master_fd)) { rz_sys_pipe_close(stderr_pipe[0]); @@ -1266,7 +1266,7 @@ static RzSubprocessWaitReason subprocess_wait(RzSubprocess *proc, ut64 timeout_m bool stdout_pty = proc->stdout_fd != -1 && proc->stdout_fd == proc->master_fd; bool stderr_pty = proc->stderr_fd != -1 && proc->stderr_fd == proc->master_fd; - while ((!bytes_enabled || n_bytes) && ((stdout_enabled && !stdout_eof) || (stderr_enabled && !stderr_eof) || !child_dead)) { + while ((!bytes_enabled || n_bytes) && ((stdout_enabled && !stdout_eof) || (stderr_enabled && !stderr_eof))) { fd_set rfds; FD_ZERO(&rfds); int nfds = 0; @@ -1282,12 +1282,6 @@ static RzSubprocessWaitReason subprocess_wait(RzSubprocess *proc, ut64 timeout_m nfds = proc->stderr_fd; } } - if (!child_dead) { - FD_SET(proc->killpipe[0], &rfds); - if (proc->killpipe[0] > nfds) { - nfds = proc->killpipe[0]; - } - } nfds++; struct timeval timeout_s; @@ -1325,11 +1319,12 @@ static RzSubprocessWaitReason subprocess_wait(RzSubprocess *proc, ut64 timeout_m n_bytes -= r; } } - if (FD_ISSET(proc->killpipe[0], &rfds)) { + if (stdout_eof && stderr_eof) { timedout = false; child_dead = true; } if (timedout) { + rz_th_sem_post(proc->ret_sem); break; } } @@ -1430,7 +1425,6 @@ RZ_API void rz_subprocess_kill(RzSubprocess *proc) { } RZ_API RzSubprocessOutput *rz_subprocess_drain(RzSubprocess *proc) { - subprocess_lock(); RzSubprocessOutput *out = RZ_NEW(RzSubprocessOutput); if (out) { out->ret = rz_subprocess_ret(proc); @@ -1438,7 +1432,6 @@ RZ_API RzSubprocessOutput *rz_subprocess_drain(RzSubprocess *proc) { out->err = rz_subprocess_err(proc, &out->err_len); out->timeout = false; } - subprocess_unlock(); return out; } @@ -1449,10 +1442,9 @@ RZ_API void rz_subprocess_free(RzSubprocess *proc) { subprocess_lock(); rz_pvector_remove_data(&subprocs, proc); subprocess_unlock(); + rz_th_sem_free(proc->ret_sem); rz_strbuf_fini(&proc->out); rz_strbuf_fini(&proc->err); - rz_sys_pipe_close(proc->killpipe[0]); - rz_sys_pipe_close(proc->killpipe[1]); if (proc->master_fd != -1) { rz_sys_pipe_close(proc->master_fd); @@ -1548,7 +1540,10 @@ RZ_API void rz_subprocess_pty_free(RZ_OWN RzPty *pty) { #endif RZ_API int rz_subprocess_ret(RzSubprocess *proc) { - return proc->ret; + rz_th_sem_wait(proc->ret_sem); + int ret = proc->ret; + rz_th_sem_post(proc->ret_sem); + return ret; } RZ_API ut8 *rz_subprocess_out(RzSubprocess *proc, int *length) { diff --git a/librz/util/thread_sem.c b/librz/util/thread_sem.c index 109ee844bb9..6b45798b6e8 100644 --- a/librz/util/thread_sem.c +++ b/librz/util/thread_sem.c @@ -112,7 +112,8 @@ RZ_API void rz_th_sem_post(RZ_NONNULL RzThreadSemaphore *sem) { RZ_API void rz_th_sem_wait(RZ_NONNULL RzThreadSemaphore *sem) { rz_return_if_fail(sem); #if HAVE_PTHREAD - sem_wait(sem->sem); + while (sem_wait(sem->sem) < 0 && errno == EINTR) + ; #elif __WINDOWS__ WaitForSingleObject(sem->sem, INFINITE); #endif