diff options
author | наб <[email protected]> | 2021-05-19 13:56:24 +0200 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2021-05-21 09:47:53 -0700 |
commit | 30dadd5c04be1f88c5fa6ab7f32b7573a9eee981 (patch) | |
tree | 3975bf4a297fb2f662ffb91037118b062dd423cd /lib | |
parent | e72383825bbd48524bef19feb9893cdb05107f15 (diff) |
libzfs: run_process: set O_NONBLOCK on lines pipe
Without this, we can deadlock: the child is stuck writing to the pipe,
and we are stuck waiting on the child
With this, we the child fills up the pipe (a few hundred kBish)
and starts getting EAGAINs, which allows it to either crash
or ignore them
libzfs_run_process_get_stdout*() is used only by zpool -c scripts,
which output short runs of K=V pairs, so the likelihood of losing
legitimate data there is relatively low
Reviewed-by: John Kennedy <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: Ahelenia Ziemiańska <[email protected]>
Closes #12082
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libzfs/libzfs_util.c | 5 |
1 files changed, 3 insertions, 2 deletions
diff --git a/lib/libzfs/libzfs_util.c b/lib/libzfs/libzfs_util.c index fdb574651..d348bf8f5 100644 --- a/lib/libzfs/libzfs_util.c +++ b/lib/libzfs/libzfs_util.c @@ -889,7 +889,7 @@ libzfs_run_process_impl(const char *path, char *argv[], char *env[], int flags, * Setup a pipe between our child and parent process if we're * reading stdout. */ - if ((lines != NULL) && pipe2(link, O_CLOEXEC) == -1) + if (lines != NULL && pipe2(link, O_NONBLOCK | O_CLOEXEC) == -1) return (-EPIPE); pid = vfork(); @@ -928,7 +928,8 @@ libzfs_run_process_impl(const char *path, char *argv[], char *env[], int flags, int status; while ((error = waitpid(pid, &status, 0)) == -1 && - errno == EINTR) { } + errno == EINTR) + ; if (error < 0 || !WIFEXITED(status)) return (-1); |