The Windows platform does not have the signal handling support we need, so it must be disabled in several parts of the codebase. Signed-off-by: Daniel P. Berrangé <berrange@xxxxxxxxxx> --- src/rpc/virnetclient.c | 33 ++++++++++++++++++++++-------- src/rpc/virnetdaemon.c | 35 +++++++++++++++++++++++++++++--- src/rpc/virnetdaemon.h | 4 ++++ tools/virsh-domain.c | 46 +++++++++++++++++++++++++++++++++++++----- tools/vsh.c | 12 ++++++++++- 5 files changed, 113 insertions(+), 17 deletions(-) diff --git a/src/rpc/virnetclient.c b/src/rpc/virnetclient.c index 50489b754c..eac02282e6 100644 --- a/src/rpc/virnetclient.c +++ b/src/rpc/virnetclient.c @@ -845,16 +845,19 @@ int virNetClientSetTLSSession(virNetClientPtr client, char buf[1]; int len; struct pollfd fds[1]; + +# ifndef WIN32 sigset_t oldmask, blockedsigs; sigemptyset(&blockedsigs); -# ifdef SIGWINCH +# ifdef SIGWINCH sigaddset(&blockedsigs, SIGWINCH); -# endif -# ifdef SIGCHLD +# endif +# ifdef SIGCHLD sigaddset(&blockedsigs, SIGCHLD); -# endif +# endif sigaddset(&blockedsigs, SIGPIPE); +# endif /* !WIN32 */ virObjectLock(client); @@ -880,19 +883,23 @@ int virNetClientSetTLSSession(virNetClientPtr client, else fds[0].events = POLLOUT; +# ifndef WIN32 /* Block SIGWINCH from interrupting poll in curses programs, * then restore the original signal mask again immediately * after the call (RHBZ#567931). Same for SIGCHLD and SIGPIPE * at the suggestion of Paolo Bonzini and Daniel Berrange. */ ignore_value(pthread_sigmask(SIG_BLOCK, &blockedsigs, &oldmask)); +# endif /* !WIN32 */ repoll: ret = poll(fds, G_N_ELEMENTS(fds), -1); if (ret < 0 && (errno == EAGAIN || errno == EINTR)) goto repoll; +# ifndef WIN32 ignore_value(pthread_sigmask(SIG_SETMASK, &oldmask, NULL)); +# endif /* !WIN32 */ } ret = virNetTLSContextCheckCertificate(tls, client->tls); @@ -908,15 +915,19 @@ int virNetClientSetTLSSession(virNetClientPtr client, fds[0].revents = 0; fds[0].events = POLLIN; +# ifndef WIN32 /* Block SIGWINCH from interrupting poll in curses programs */ ignore_value(pthread_sigmask(SIG_BLOCK, &blockedsigs, &oldmask)); +# endif /* !WIN32 */ repoll2: ret = poll(fds, G_N_ELEMENTS(fds), -1); if (ret < 0 && (errno == EAGAIN || errno == EINTR)) goto repoll2; +# ifndef WIN32 ignore_value(pthread_sigmask(SIG_SETMASK, &oldmask, NULL)); +# endif /* !WIN32 */ len = virNetTLSSessionRead(client->tls, buf, 1); if (len < 0 && errno != ENOMSG) { @@ -1574,7 +1585,9 @@ static int virNetClientIOEventLoop(virNetClientPtr client, for (;;) { char ignore; +#ifndef WIN32 sigset_t oldmask, blockedsigs; +#endif /* !WIN32 */ int timeout = -1; virNetMessagePtr msg = NULL; @@ -1615,27 +1628,31 @@ static int virNetClientIOEventLoop(virNetClientPtr client, * can stuff themselves on the queue */ virObjectUnlock(client); +#ifndef WIN32 /* Block SIGWINCH from interrupting poll in curses programs, * then restore the original signal mask again immediately * after the call (RHBZ#567931). Same for SIGCHLD and SIGPIPE * at the suggestion of Paolo Bonzini and Daniel Berrange. */ sigemptyset(&blockedsigs); -#ifdef SIGWINCH +# ifdef SIGWINCH sigaddset(&blockedsigs, SIGWINCH); -#endif -#ifdef SIGCHLD +# endif +# ifdef SIGCHLD sigaddset(&blockedsigs, SIGCHLD); -#endif +# endif sigaddset(&blockedsigs, SIGPIPE); ignore_value(pthread_sigmask(SIG_BLOCK, &blockedsigs, &oldmask)); +#endif /* !WIN32 */ repoll: ret = poll(fds, G_N_ELEMENTS(fds), timeout); if (ret < 0 && (errno == EAGAIN || errno == EINTR)) goto repoll; +#ifndef WIN32 ignore_value(pthread_sigmask(SIG_SETMASK, &oldmask, NULL)); +#endif /* !WIN32 */ virObjectLock(client); diff --git a/src/rpc/virnetdaemon.c b/src/rpc/virnetdaemon.c index 570930436a..9634e93b52 100644 --- a/src/rpc/virnetdaemon.c +++ b/src/rpc/virnetdaemon.c @@ -45,6 +45,7 @@ VIR_LOG_INIT("rpc.netdaemon"); +#ifndef WIN32 typedef struct _virNetDaemonSignal virNetDaemonSignal; typedef virNetDaemonSignal *virNetDaemonSignalPtr; @@ -54,17 +55,20 @@ struct _virNetDaemonSignal { virNetDaemonSignalFunc func; void *opaque; }; +#endif /* !WIN32 */ struct _virNetDaemon { virObjectLockable parent; bool privileged; +#ifndef WIN32 size_t nsignals; virNetDaemonSignalPtr *signals; int sigread; int sigwrite; int sigwatch; +#endif /* !WIN32 */ virHashTablePtr servers; virJSONValuePtr srvObject; @@ -84,10 +88,9 @@ static void virNetDaemonDispose(void *obj) { virNetDaemonPtr dmn = obj; +#ifndef WIN32 size_t i; - VIR_FORCE_CLOSE(dmn->autoShutdownInhibitFd); - for (i = 0; i < dmn->nsignals; i++) { sigaction(dmn->signals[i]->signum, &dmn->signals[i]->oldaction, NULL); VIR_FREE(dmn->signals[i]); @@ -97,6 +100,9 @@ virNetDaemonDispose(void *obj) VIR_FORCE_CLOSE(dmn->sigwrite); if (dmn->sigwatch > 0) virEventRemoveHandle(dmn->sigwatch); +#endif /* !WIN32 */ + + VIR_FORCE_CLOSE(dmn->autoShutdownInhibitFd); virHashFree(dmn->servers); @@ -119,7 +125,9 @@ virNetDaemonPtr virNetDaemonNew(void) { virNetDaemonPtr dmn; +#ifndef WIN32 struct sigaction sig_action; +#endif /* !WIN32 */ if (virNetDaemonInitialize() < 0) return NULL; @@ -130,16 +138,21 @@ virNetDaemonNew(void) if (!(dmn->servers = virHashCreate(5, virObjectFreeHashData))) goto error; +#ifndef WIN32 dmn->sigwrite = dmn->sigread = -1; +#endif /* !WIN32 */ + dmn->privileged = geteuid() == 0; dmn->autoShutdownInhibitFd = -1; if (virEventRegisterDefaultImpl() < 0) goto error; +#ifndef WIN32 memset(&sig_action, 0, sizeof(sig_action)); sig_action.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sig_action, NULL); +#endif /* !WIN32 */ return dmn; @@ -587,7 +600,7 @@ virNetDaemonRemoveShutdownInhibition(virNetDaemonPtr dmn) } - +#ifndef WIN32 static sig_atomic_t sigErrors; static int sigLastErrno; static int sigWrite = -1; @@ -689,6 +702,7 @@ virNetDaemonSignalSetup(virNetDaemonPtr dmn) return -1; } + int virNetDaemonAddSignalHandler(virNetDaemonPtr dmn, int signum, @@ -731,6 +745,21 @@ virNetDaemonAddSignalHandler(virNetDaemonPtr dmn, return -1; } +#else /* WIN32 */ + +int +virNetDaemonAddSignalHandler(virNetDaemonPtr dmn G_GNUC_UNUSED, + int signum G_GNUC_UNUSED, + virNetDaemonSignalFunc func G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", + _("Signal handling not available on this platform")); + return -1; +} + +#endif /* WIN32 */ + static void virNetDaemonAutoShutdownTimer(int timerid G_GNUC_UNUSED, diff --git a/src/rpc/virnetdaemon.h b/src/rpc/virnetdaemon.h index 5a9842bee6..c2c7767037 100644 --- a/src/rpc/virnetdaemon.h +++ b/src/rpc/virnetdaemon.h @@ -55,6 +55,10 @@ void virNetDaemonAutoShutdown(virNetDaemonPtr dmn, void virNetDaemonAddShutdownInhibition(virNetDaemonPtr dmn); void virNetDaemonRemoveShutdownInhibition(virNetDaemonPtr dmn); +#ifdef WIN32 +# define siginfo_t void +#endif + typedef void (*virNetDaemonSignalFunc)(virNetDaemonPtr dmn, siginfo_t *info, void *opaque); int virNetDaemonAddSignalHandler(virNetDaemonPtr dmn, diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index e64e08e5da..df4a03290f 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -1697,12 +1697,14 @@ virshPrintJobProgress(const char *label, unsigned long long remaining, static volatile sig_atomic_t intCaught; +#ifndef WIN32 static void virshCatchInt(int sig G_GNUC_UNUSED, siginfo_t *siginfo G_GNUC_UNUSED, void *context G_GNUC_UNUSED) { intCaught = 1; } +#endif /* !WIN32 */ typedef struct _virshBlockJobWaitData virshBlockJobWaitData; @@ -1842,11 +1844,11 @@ virshBlockJobWait(virshBlockJobWaitDataPtr data) * the event to the given block job we will wait for the number of retries * before claiming that we entered synchronised phase */ unsigned int retries = 5; - +#ifndef WIN32 struct sigaction sig_action; struct sigaction old_sig_action; sigset_t sigmask, oldsigmask; - +#endif /* !WIN32 */ unsigned long long start = 0; unsigned long long curr = 0; @@ -1861,6 +1863,7 @@ virshBlockJobWait(virshBlockJobWaitDataPtr data) if (data->async_abort) abort_flags |= VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC; +#ifndef WIN32 sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); @@ -1869,6 +1872,7 @@ virshBlockJobWait(virshBlockJobWaitDataPtr data) sig_action.sa_flags = SA_SIGINFO; sigemptyset(&sig_action.sa_mask); sigaction(SIGINT, &sig_action, &old_sig_action); +#endif /* !WIN32 */ if (data->timeout && virTimeMillisNow(&start) < 0) { vshSaveLibvirtError(); @@ -1878,9 +1882,13 @@ virshBlockJobWait(virshBlockJobWaitDataPtr data) last.cur = last.end = 0; while (true) { +#ifndef WIN32 pthread_sigmask(SIG_BLOCK, &sigmask, &oldsigmask); +#endif /* !WIN32 */ result = virDomainGetBlockJobInfo(data->dom, data->dev, &info, 0); +#ifndef WIN32 pthread_sigmask(SIG_SETMASK, &oldsigmask, NULL); +#endif /* !WIN32 */ if (result < 0) { vshError(data->ctl, _("failed to query job for disk %s"), data->dev); @@ -1944,7 +1952,9 @@ virshBlockJobWait(virshBlockJobWaitDataPtr data) virshPrintJobProgress(data->job_name, 0, 1); cleanup: +#ifndef WIN32 sigaction(SIGINT, &old_sig_action, NULL); +#endif /* !WIN32 */ return ret; } @@ -4226,12 +4236,14 @@ doSave(void *opaque) unsigned int flags = 0; const char *xmlfile = NULL; char *xml = NULL; +#ifndef WIN32 sigset_t sigmask, oldsigmask; sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); if (pthread_sigmask(SIG_BLOCK, &sigmask, &oldsigmask) < 0) goto out_sig; +#endif /* !WIN32 */ if (vshCommandOptStringReq(ctl, cmd, "file", &to) < 0) goto out; @@ -4265,8 +4277,10 @@ doSave(void *opaque) ret = '0'; out: +#ifndef WIN32 pthread_sigmask(SIG_SETMASK, &oldsigmask, NULL); out_sig: +#endif /* !WIN32 */ virshDomainFree(dom); VIR_FREE(xml); ignore_value(safewrite(data->writefd, &ret, sizeof(ret))); @@ -4285,8 +4299,11 @@ virshWatchJob(vshControl *ctl, void *opaque, const char *label) { +#ifndef WIN32 struct sigaction sig_action; struct sigaction old_sig_action; + sigset_t sigmask, oldsigmask; +#endif /* !WIN32 */ struct pollfd pollfd[2] = {{.fd = pipe_fd, .events = POLLIN, .revents = 0}, {.fd = STDIN_FILENO, .events = POLLIN, .revents = 0}}; unsigned long long start_us, curr_us; @@ -4294,10 +4311,10 @@ virshWatchJob(vshControl *ctl, int ret = -1; char retchar; bool functionReturn = false; - sigset_t sigmask, oldsigmask; bool jobStarted = false; nfds_t npollfd = 2; +#ifndef WIN32 sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); @@ -4306,6 +4323,7 @@ virshWatchJob(vshControl *ctl, sig_action.sa_flags = SA_SIGINFO; sigemptyset(&sig_action.sa_mask); sigaction(SIGINT, &sig_action, &old_sig_action); +#endif /* !WIN32 */ /* don't poll on STDIN if we are not using a terminal */ if (!vshTTYAvailable(ctl)) @@ -4355,9 +4373,13 @@ virshWatchJob(vshControl *ctl, } if (verbose || !jobStarted) { +#ifndef WIN32 pthread_sigmask(SIG_BLOCK, &sigmask, &oldsigmask); +#endif /* !WIN32 */ ret = virDomainGetJobInfo(dom, &jobinfo); +#ifndef WIN32 pthread_sigmask(SIG_SETMASK, &oldsigmask, NULL); +#endif /* !WIN32 */ if (ret == 0) { if (verbose && jobinfo.dataTotal > 0) virshPrintJobProgress(label, jobinfo.dataRemaining, @@ -4378,7 +4400,9 @@ virshWatchJob(vshControl *ctl, functionReturn = true; cleanup: +#ifndef WIN32 sigaction(SIGINT, &old_sig_action, NULL); +#endif /* !WIN32 */ vshTTYRestore(ctl); return functionReturn; } @@ -4662,12 +4686,14 @@ doManagedsave(void *opaque) virDomainPtr dom = NULL; const char *name; unsigned int flags = 0; +#ifndef WIN32 sigset_t sigmask, oldsigmask; sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); if (pthread_sigmask(SIG_BLOCK, &sigmask, &oldsigmask) < 0) goto out_sig; +#endif /* !WIN32 */ if (vshCommandOptBool(cmd, "bypass-cache")) flags |= VIR_DOMAIN_SAVE_BYPASS_CACHE; @@ -4686,8 +4712,10 @@ doManagedsave(void *opaque) ret = '0'; out: +#ifndef WIN32 pthread_sigmask(SIG_SETMASK, &oldsigmask, NULL); out_sig: +#endif /* !WIN32 */ virshDomainFree(dom); ignore_value(safewrite(data->writefd, &ret, sizeof(ret))); } @@ -5340,17 +5368,19 @@ doDump(void *opaque) vshControl *ctl = data->ctl; const vshCmd *cmd = data->cmd; virDomainPtr dom = NULL; - sigset_t sigmask, oldsigmask; const char *name = NULL; const char *to = NULL; unsigned int flags = 0; const char *format = NULL; unsigned int dumpformat = VIR_DOMAIN_CORE_DUMP_FORMAT_RAW; +#ifndef WIN32 + sigset_t sigmask, oldsigmask; sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); if (pthread_sigmask(SIG_BLOCK, &sigmask, &oldsigmask) < 0) goto out_sig; +#endif /* !WIN32 */ if (vshCommandOptStringReq(ctl, cmd, "file", &to) < 0) goto out; @@ -5407,8 +5437,10 @@ doDump(void *opaque) ret = '0'; out: +#ifndef WIN32 pthread_sigmask(SIG_SETMASK, &oldsigmask, NULL); out_sig: +#endif /* !WIN32 */ if (dom) virshDomainFree(dom); ignore_value(safewrite(data->writefd, &ret, sizeof(ret))); @@ -10601,7 +10633,6 @@ doMigrate(void *opaque) virshCtrlData *data = opaque; vshControl *ctl = data->ctl; const vshCmd *cmd = data->cmd; - sigset_t sigmask, oldsigmask; virTypedParameterPtr params = NULL; int nparams = 0; int maxparams = 0; @@ -10609,11 +10640,14 @@ doMigrate(void *opaque) unsigned long long ullOpt = 0; int rv; virConnectPtr dconn = data->dconn; +#ifndef WIN32 + sigset_t sigmask, oldsigmask; sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); if (pthread_sigmask(SIG_BLOCK, &sigmask, &oldsigmask) < 0) goto out_sig; +#endif /* !WIN32 */ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) goto out; @@ -10881,8 +10915,10 @@ doMigrate(void *opaque) } out: +#ifndef WIN32 pthread_sigmask(SIG_SETMASK, &oldsigmask, NULL); out_sig: +#endif /* !WIN32 */ virTypedParamsFree(params, nparams); virshDomainFree(dom); ignore_value(safewrite(data->writefd, &ret, sizeof(ret))); diff --git a/tools/vsh.c b/tools/vsh.c index 949c8dad7b..39bb75f192 100644 --- a/tools/vsh.c +++ b/tools/vsh.c @@ -2013,6 +2013,7 @@ vshEventLoop(void *opaque) /* We want to use SIGINT to cancel a wait; but as signal handlers * don't have an opaque argument, we have to use static storage. */ +#ifndef WIN32 static int vshEventFd = -1; static struct sigaction vshEventOldAction; @@ -2027,6 +2028,7 @@ vshEventInt(int sig G_GNUC_UNUSED, if (vshEventFd >= 0) ignore_value(safewrite(vshEventFd, &reason, 1)); } +#endif /* !WIN32 */ /* Event loop handler used to limit length of waiting for any other event. */ @@ -2057,10 +2059,13 @@ vshEventTimeout(int timer G_GNUC_UNUSED, int vshEventStart(vshControl *ctl, int timeout_ms) { +#ifndef WIN32 struct sigaction action; + assert(vshEventFd == -1); +#endif /* !WIN32 */ assert(ctl->eventPipe[0] == -1 && ctl->eventPipe[1] == -1 && - vshEventFd == -1 && ctl->eventTimerId >= 0); + ctl->eventTimerId >= 0); if (pipe2(ctl->eventPipe, O_CLOEXEC) < 0) { char ebuf[1024]; @@ -2068,12 +2073,15 @@ vshEventStart(vshControl *ctl, int timeout_ms) virStrerror(errno, ebuf, sizeof(ebuf))); return -1; } + +#ifndef WIN32 vshEventFd = ctl->eventPipe[1]; action.sa_sigaction = vshEventInt; action.sa_flags = SA_SIGINFO; sigemptyset(&action.sa_mask); sigaction(SIGINT, &action, &vshEventOldAction); +#endif /* !WIN32 */ if (timeout_ms) virEventUpdateTimeout(ctl->eventTimerId, timeout_ms); @@ -2140,10 +2148,12 @@ vshEventWait(vshControl *ctl) void vshEventCleanup(vshControl *ctl) { +#ifndef WIN32 if (vshEventFd >= 0) { sigaction(SIGINT, &vshEventOldAction, NULL); vshEventFd = -1; } +#endif /* !WIN32 */ VIR_FORCE_CLOSE(ctl->eventPipe[0]); VIR_FORCE_CLOSE(ctl->eventPipe[1]); virEventUpdateTimeout(ctl->eventTimerId, -1); -- 2.24.1