diff options
author | Justus Winter <justus@g10code.com> | 2016-01-14 18:20:14 +0100 |
---|---|---|
committer | Justus Winter <justus@g10code.com> | 2016-02-23 11:58:52 +0100 |
commit | 5ba4f6047b84e4cfdb3e6bc88e574ca7a455da81 (patch) | |
tree | b27969273ef7f6f30a86e59ae03eab64ee8b9467 /common/exechelp-posix.c | |
parent | common/exechelp: Add general pipe function. (diff) | |
download | gnupg2-5ba4f6047b84e4cfdb3e6bc88e574ca7a455da81.tar.xz gnupg2-5ba4f6047b84e4cfdb3e6bc88e574ca7a455da81.zip |
common/exechelp: Provide a way to wait for multiple processes.
* common/exechelp-posix.c (gnupg_wait_process): Generalize to
'gnupg_wait_processes'.
* common/exechelp-w32.c (gnupg_wait_process): Likewise.
* common/exechelp-w32ce.c (gnupg_wait_process): New function stub.
* common/exechelp.h (gnupg_wait_process): New prototype.
Signed-off-by: Justus Winter <justus@g10code.com>
Diffstat (limited to 'common/exechelp-posix.c')
-rw-r--r-- | common/exechelp-posix.c | 120 |
1 files changed, 77 insertions, 43 deletions
diff --git a/common/exechelp-posix.c b/common/exechelp-posix.c index 37abf55a1..6614eb7d6 100644 --- a/common/exechelp-posix.c +++ b/common/exechelp-posix.c @@ -522,60 +522,94 @@ gnupg_spawn_process_fd (const char *pgmname, const char *argv[], } -/* See exechelp.h for the description. */ +/* See exechelp.h for a description. */ gpg_error_t gnupg_wait_process (const char *pgmname, pid_t pid, int hang, int *r_exitcode) { - gpg_err_code_t ec; - int i, status; + return gnupg_wait_processes (&pgmname, &pid, 1, hang, r_exitcode); +} - if (r_exitcode) - *r_exitcode = -1; +/* See exechelp.h for a description. */ +gpg_error_t +gnupg_wait_processes (const char **pgmnames, pid_t *pids, size_t count, + int hang, int *r_exitcodes) +{ + gpg_err_code_t ec = 0; + size_t i, left; - if (pid == (pid_t)(-1)) - return gpg_error (GPG_ERR_INV_VALUE); + for (i = 0; i < count; i++) + { + if (r_exitcodes) + r_exitcodes[i] = -1; + + if (pids[i] == (pid_t)(-1)) + return gpg_error (GPG_ERR_INV_VALUE); + } + + left = count; + while (left > 0) + { + pid_t pid; + int status; #ifdef USE_NPTH - i = npth_waitpid (pid, &status, hang? 0:WNOHANG); + pid = npth_waitpid (-1, &status, hang ? 0 : WNOHANG); #else - while ((i=waitpid (pid, &status, hang? 0:WNOHANG)) == (pid_t)(-1) - && errno == EINTR); + while ((pid = waitpid (-1, &status, hang ? 0 : WNOHANG)) == (pid_t)(-1) + && errno == EINTR); #endif - if (i == (pid_t)(-1)) - { - ec = gpg_err_code_from_errno (errno); - log_error (_("waiting for process %d to terminate failed: %s\n"), - (int)pid, strerror (errno)); - } - else if (!i) - { - ec = GPG_ERR_TIMEOUT; /* Still running. */ - } - else if (WIFEXITED (status) && WEXITSTATUS (status) == 127) - { - log_error (_("error running '%s': probably not installed\n"), pgmname); - ec = GPG_ERR_CONFIGURATION; - } - else if (WIFEXITED (status) && WEXITSTATUS (status)) - { - if (!r_exitcode) - log_error (_("error running '%s': exit status %d\n"), pgmname, - WEXITSTATUS (status)); + if (pid == (pid_t)(-1)) + { + ec = gpg_err_code_from_errno (errno); + log_error (_("waiting for processes to terminate failed: %s\n"), + strerror (errno)); + break; + } + else if (!pid) + { + ec = GPG_ERR_TIMEOUT; /* Still running. */ + break; + } else - *r_exitcode = WEXITSTATUS (status); - ec = GPG_ERR_GENERAL; - } - else if (!WIFEXITED (status)) - { - log_error (_("error running '%s': terminated\n"), pgmname); - ec = GPG_ERR_GENERAL; - } - else - { - if (r_exitcode) - *r_exitcode = 0; - ec = 0; + { + for (i = 0; i < count; i++) + if (pid == pids[i]) + break; + + if (i == count) + /* No match, ignore this pid. */ + continue; + + /* Process PIDS[i] died. */ + left -= 1; + + if (WIFEXITED (status) && WEXITSTATUS (status) == 127) + { + log_error (_("error running '%s': probably not installed\n"), + pgmnames[i]); + ec = GPG_ERR_CONFIGURATION; + } + else if (WIFEXITED (status) && WEXITSTATUS (status)) + { + if (!r_exitcodes) + log_error (_("error running '%s': exit status %d\n"), + pgmnames[i], WEXITSTATUS (status)); + else + r_exitcodes[i] = WEXITSTATUS (status); + ec = GPG_ERR_GENERAL; + } + else if (!WIFEXITED (status)) + { + log_error (_("error running '%s': terminated\n"), pgmnames[i]); + ec = GPG_ERR_GENERAL; + } + else + { + if (r_exitcodes) + r_exitcodes[i] = 0; + } + } } return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec); |