Libvirtd has set SIGPIPE to ignored, and virFork resets all signal
handlers to the defaults. But child process may write logs to
stderr/stdout, that may generate SIGPIPE if journald has stopped.
So block SIGPIPE in virFork, and unblock it before execve.
Signed-off-by: Wang Yechao <wang.yechao255(a)zte.com.cn>
---
v1 patch:
https://www.redhat.com/archives/libvir-list/2019-October/msg00720.html
Changes in v2:
- use pthread_sigmask to block SIGPIPE
Changes in v3:
- pass SIG_UNBLOCK(not SIG_SETMASK) to pthread_sigmask when unlock SIGPIPE
---
src/util/vircommand.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/src/util/vircommand.c b/src/util/vircommand.c
index 79e1e87..bd3a582 100644
--- a/src/util/vircommand.c
+++ b/src/util/vircommand.c
@@ -321,6 +321,15 @@ virFork(void)
virDispatchError(NULL);
_exit(EXIT_CANCELED);
}
+
+ sigemptyset(&newmask);
+ sigaddset(&newmask, SIGPIPE);
+ if (pthread_sigmask(SIG_BLOCK, &newmask, NULL) != 0) {
+ virReportSystemError(errno, "%s", _("cannot block
SIGPIPE"));
+ virDispatchError(NULL);
+ _exit(EXIT_CANCELED);
+ }
+
}
return pid;
}
@@ -553,6 +562,7 @@ virExec(virCommandPtr cmd)
struct sigaction waxon, waxoff;
VIR_AUTOFREE(gid_t *) groups = NULL;
int ngroups;
+ sigset_t set;
if (cmd->args[0][0] != '/') {
if (!(binary = binarystr = virFindFileInPath(cmd->args[0]))) {
@@ -792,6 +802,13 @@ virExec(virCommandPtr cmd)
/* Close logging again to ensure no FDs leak to child */
virLogReset();
+ sigemptyset(&set);
+ sigaddset(&set, SIGPIPE);
+ if (pthread_sigmask(SIG_UNBLOCK, &set, NULL) != 0) {
+ virReportSystemError(errno, "%s", _("cannot unblock
SIGPIPE"));
+ goto fork_error;
+ }
+
if (cmd->env)
execve(binary, cmd->args, cmd->env);
else
--
1.8.3.1