Skip to content
Snippets Groups Projects
Commit 2b4ca339 authored by Alexander Turenko's avatar Alexander Turenko Committed by Kirill Yukhin
Browse files

popen: add missed diag_set() in popen_new()


See the previous similar commits:

* popen: add missed diag_set() in popen IO functions
* popen: add missed diag_set in popen_signal/delete

Part of #4031

Acked-by: default avatarCyrill Gorcunov <gorcunov@gmail.com>
parent 667930de
No related branches found
No related tags found
No related merge requests found
...@@ -803,7 +803,18 @@ signal_reset(void) ...@@ -803,7 +803,18 @@ signal_reset(void)
* process will run with all files inherited from a parent. * process will run with all files inherited from a parent.
* *
* Returns pointer to a new popen handle on success, * Returns pointer to a new popen handle on success,
* otherwise NULL returned setting @a errno. * otherwise NULL returned and an error is set to the
* diagnostics area.
*
* Possible errors:
*
* - IllegalParams: a parameter check fails:
* - group signal is set, while setsid is not.
* - SystemError: dup(), fcntl(), pipe(), vfork() or close() fails
* in the parent process.
* - SystemError: (temporary restriction) one of std{in,out,err}
* is closed in the parent process.
* - OutOfMemory: unable to allocate handle.
*/ */
struct popen_handle * struct popen_handle *
popen_new(struct popen_opts *opts) popen_new(struct popen_opts *opts)
...@@ -972,6 +983,7 @@ popen_new(struct popen_opts *opts) ...@@ -972,6 +983,7 @@ popen_new(struct popen_opts *opts)
*/ */
handle->pid = vfork(); handle->pid = vfork();
if (handle->pid < 0) { if (handle->pid < 0) {
diag_set(SystemError, "vfork() fails");
goto out_err; goto out_err;
} else if (handle->pid == 0) { } else if (handle->pid == 0) {
/* /*
...@@ -1180,6 +1192,16 @@ popen_new(struct popen_opts *opts) ...@@ -1180,6 +1192,16 @@ popen_new(struct popen_opts *opts)
out_err: out_err:
diag_log(); diag_log();
saved_errno = errno; saved_errno = errno;
/*
* Save a reason of failure, because popen_delete() may
* clobber the diagnostics area.
*/
struct diag *diag = diag_get();
struct error *e = diag_last_error(diag);
assert(e != NULL);
error_ref(e);
popen_delete(handle); popen_delete(handle);
for (i = 0; i < lengthof(pfd); i++) { for (i = 0; i < lengthof(pfd); i++) {
if (pfd[i][0] != -1) if (pfd[i][0] != -1)
...@@ -1189,6 +1211,11 @@ popen_new(struct popen_opts *opts) ...@@ -1189,6 +1211,11 @@ popen_new(struct popen_opts *opts)
} }
if (log_fd >= 0) if (log_fd >= 0)
close(log_fd); close(log_fd);
/* Restore the diagnostics area entry. */
diag_set_error(diag, e);
error_unref(e);
errno = saved_errno; errno = saved_errno;
return NULL; return NULL;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment