mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-07 17:28:15 +00:00
util: Set SIGPIPE to a no-op handler in virFork
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 set SIGPIPE to a dummy no-op handler before unmask signals in virFork(), and the handler will get reset to SIG_DFL when execve() runs. Now we can delete sigaction() call entirely in virExec(). Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Signed-off-by: Wang Yechao <wang.yechao255@zte.com.cn>
This commit is contained in:
parent
13ec827052
commit
ebd004299a
@ -217,6 +217,10 @@ virCommandFDSet(virCommandPtr cmd,
|
|||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
|
|
||||||
|
static void virDummyHandler(int sig G_GNUC_UNUSED)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* virFork:
|
* virFork:
|
||||||
*
|
*
|
||||||
@ -312,6 +316,14 @@ virFork(void)
|
|||||||
ignore_value(sigaction(i, &sig_action, NULL));
|
ignore_value(sigaction(i, &sig_action, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Code that runs between fork & execve might trigger
|
||||||
|
* SIG_PIPE, so we must explicitly set that to a no-op
|
||||||
|
* handler. This handler will get reset to SIG_DFL when
|
||||||
|
* execve() runs
|
||||||
|
*/
|
||||||
|
sig_action.sa_handler = virDummyHandler;
|
||||||
|
ignore_value(sigaction(SIGPIPE, &sig_action, NULL));
|
||||||
|
|
||||||
/* Unmask all signals in child, since we've no idea what the
|
/* Unmask all signals in child, since we've no idea what the
|
||||||
* caller's done with their signal mask and don't want to
|
* caller's done with their signal mask and don't want to
|
||||||
* propagate that to children */
|
* propagate that to children */
|
||||||
@ -550,7 +562,6 @@ virExec(virCommandPtr cmd)
|
|||||||
g_autofree char *binarystr = NULL;
|
g_autofree char *binarystr = NULL;
|
||||||
const char *binary = NULL;
|
const char *binary = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
struct sigaction waxon, waxoff;
|
|
||||||
g_autofree gid_t *groups = NULL;
|
g_autofree gid_t *groups = NULL;
|
||||||
int ngroups;
|
int ngroups;
|
||||||
|
|
||||||
@ -718,21 +729,6 @@ virExec(virCommandPtr cmd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* virFork reset all signal handlers to the defaults.
|
|
||||||
* This is good for the child process, but our hook
|
|
||||||
* risks running something that generates SIGPIPE,
|
|
||||||
* so we need to temporarily block that again
|
|
||||||
*/
|
|
||||||
memset(&waxoff, 0, sizeof(waxoff));
|
|
||||||
waxoff.sa_handler = SIG_IGN;
|
|
||||||
sigemptyset(&waxoff.sa_mask);
|
|
||||||
memset(&waxon, 0, sizeof(waxon));
|
|
||||||
if (sigaction(SIGPIPE, &waxoff, &waxon) < 0) {
|
|
||||||
virReportSystemError(errno, "%s",
|
|
||||||
_("Could not disable SIGPIPE"));
|
|
||||||
goto fork_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (virProcessSetMaxMemLock(0, cmd->maxMemLock) < 0)
|
if (virProcessSetMaxMemLock(0, cmd->maxMemLock) < 0)
|
||||||
goto fork_error;
|
goto fork_error;
|
||||||
if (virProcessSetMaxProcesses(0, cmd->maxProcesses) < 0)
|
if (virProcessSetMaxProcesses(0, cmd->maxProcesses) < 0)
|
||||||
@ -783,12 +779,6 @@ virExec(virCommandPtr cmd)
|
|||||||
if (virCommandHandshakeChild(cmd) < 0)
|
if (virCommandHandshakeChild(cmd) < 0)
|
||||||
goto fork_error;
|
goto fork_error;
|
||||||
|
|
||||||
if (sigaction(SIGPIPE, &waxon, NULL) < 0) {
|
|
||||||
virReportSystemError(errno, "%s",
|
|
||||||
_("Could not re-enable SIGPIPE"));
|
|
||||||
goto fork_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Close logging again to ensure no FDs leak to child */
|
/* Close logging again to ensure no FDs leak to child */
|
||||||
virLogReset();
|
virLogReset();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user