diff options
Diffstat (limited to 'common/exechelp-w32.c')
-rw-r--r-- | common/exechelp-w32.c | 109 |
1 files changed, 60 insertions, 49 deletions
diff --git a/common/exechelp-w32.c b/common/exechelp-w32.c index 4616bec33..297f6f854 100644 --- a/common/exechelp-w32.c +++ b/common/exechelp-w32.c @@ -382,7 +382,7 @@ gnupg_spawn_process (const char *pgmname, const char *argv[], int cr_flags; char *cmdline; int fd, fdout, rp[2]; - HANDLE nullhd[]; + HANDLE nullhd[2]; int i; (void)preexec; @@ -428,7 +428,7 @@ gnupg_spawn_process (const char *pgmname, const char *argv[], } nullhd[0] = fd == -1? w32_open_null (0) : INVALID_HANDLE_VALUE; - nullhd[1] = outfd == -1? w32_open_null (1) : INVALID_HANDLE_VALUE; + nullhd[1] = fdout == -1? w32_open_null (1) : INVALID_HANDLE_VALUE; /* Start the process. Note that we can't run the PREEXEC function because this would change our own environment. */ @@ -437,7 +437,7 @@ gnupg_spawn_process (const char *pgmname, const char *argv[], si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE; si.hStdInput = fd == -1? nullhd[0] : fd_to_handle (fd); - si.hStdOutput = outfd == -1? nullhd[1] : fd_to_handle (fdout); + si.hStdOutput = fdout == -1? nullhd[1] : fd_to_handle (fdout); si.hStdError = fd_to_handle (rp[1]); cr_flags = (CREATE_DEFAULT_ERROR_MODE @@ -599,22 +599,17 @@ gnupg_spawn_process_fd (const char *pgmname, const char *argv[], } -/* Wait for the process identified by PID to terminate. PGMNAME should - be the same as supplied to the spawn function and is only used for - diagnostics. Returns 0 if the process succeeded, GPG_ERR_GENERAL - for any failures of the spawned program or other error codes. If - EXITCODE is not NULL the exit code of the process is stored at this - address or -1 if it could not be retrieved. */ +/* See exechelp.h for a description. */ gpg_error_t -gnupg_wait_process (const char *pgmname, pid_t pid, int *exitcode) +gnupg_wait_process (const char *pgmname, pid_t pid, int hang, int *r_exitcode) { gpg_err_code_t ec; HANDLE proc = fd_to_handle (pid); int code; DWORD exc; - if (exitcode) - *exitcode = -1; + if (r_exitcode) + *r_exitcode = -1; if (pid == (pid_t)(-1)) return gpg_error (GPG_ERR_INV_VALUE); @@ -622,50 +617,66 @@ gnupg_wait_process (const char *pgmname, pid_t pid, int *exitcode) /* FIXME: We should do a pth_waitpid here. However this has not yet been implemented. A special W32 pth system call would even be better. */ - code = WaitForSingleObject (proc, INFINITE); + code = WaitForSingleObject (proc, hang? INFINITE : 0); switch (code) { - case WAIT_FAILED: - log_error (_("waiting for process %d to terminate failed: %s\n"), - (int)pid, w32_strerror (-1)); - ec = GPG_ERR_GENERAL; - break; - - case WAIT_OBJECT_0: - if (!GetExitCodeProcess (proc, &exc)) - { - log_error (_("error getting exit code of process %d: %s\n"), - (int)pid, w32_strerror (-1) ); - ec = GPG_ERR_GENERAL; - } - else if (exc) - { - log_error (_("error running `%s': exit status %d\n"), - pgmname, (int)exc ); - if (exitcode) - *exitcode = (int)exc; - ec = GPG_ERR_GENERAL; - } - else - { - if (exitcode) - *exitcode = 0; - ec = 0; - } - CloseHandle (proc); - break; - - default: - log_error ("WaitForSingleObject returned unexpected " - "code %d for pid %d\n", code, (int)pid ); - ec = GPG_ERR_GENERAL; - break; + case WAIT_TIMEOUT: + ec = GPG_ERR_TIMEOUT; + break; + + case WAIT_FAILED: + log_error (_("waiting for process %d to terminate failed: %s\n"), + (int)pid, w32_strerror (-1)); + ec = GPG_ERR_GENERAL; + break; + + case WAIT_OBJECT_0: + if (!GetExitCodeProcess (proc, &exc)) + { + log_error (_("error getting exit code of process %d: %s\n"), + (int)pid, w32_strerror (-1) ); + ec = GPG_ERR_GENERAL; + } + else if (exc) + { + log_error (_("error running `%s': exit status %d\n"), + pgmname, (int)exc ); + if (r_exitcode) + *r_exitcode = (int)exc; + ec = GPG_ERR_GENERAL; + } + else + { + if (r_exitcode) + *r_exitcode = 0; + ec = 0; + } + break; + + default: + log_error ("WaitForSingleObject returned unexpected " + "code %d for pid %d\n", code, (int)pid ); + ec = GPG_ERR_GENERAL; + break; } - + return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec); } + +void +gnupg_release_process (pid_t pid) +{ + if (pid != (pid_t)INVALID_HANDLE_VALUE) + { + HANDLE process = (HANDLE)pid; + + CloseHandle (process); + } +} + + /* Spawn a new process and immediatley detach from it. The name of the program to exec is PGMNAME and its arguments are in ARGV (the programname is automatically passed as first argument). |