From 30dadd5c04be1f88c5fa6ab7f32b7573a9eee981 Mon Sep 17 00:00:00 2001 From: наб Date: Wed, 19 May 2021 13:56:24 +0200 Subject: libzfs: run_process: set O_NONBLOCK on lines pipe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Brian Behlendorf Signed-off-by: Ahelenia Ziemiańska Closes #12082 --- lib/libzfs/libzfs_util.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib') 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); -- cgit v1.2.3