mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-21 20:15:17 +00:00
Ignore SIGWINCH in remote client call to poll(2) (RHBZ#567931).
In bug 567931 we found that virt-top would exit occasionally when the terminal window was resized. Tracking this down it turned out that SIGWINCH was being delivered to the process at exactly the point where the libvirt remote driver was calling poll(2) waiting for a reply from libvirtd. This caused the poll(2) call to be interrupted (returning errno EINTR). However handling EINTR the same way as EAGAIN was not the solution to this problem since we found previously that this would break Ctrl-C handling (commit 47fec8eac2bb3). The correct solution is to mask out SIGWINCH for the duration of the poll(2) system call. The per-thread mask is changed and restored immediately after the call. Since we are using pthread_sigmask, this should not affect other threads, and since we restore the signal mask immediately afterwards it should not affect the current thread visibly either. Other possibly problematic signals are SIGCHLD and SIGPIPE and these are masked too. Note use of ignore_value: It's not fatal if we cannot mask out SIGWINCH, and in any case pthread_sigmask never fails on Linux as long as you supply the correct arguments. I tested this patch and it cures the original problem with virt-top.
This commit is contained in:
parent
c7b85e3710
commit
f4a43df52b
@ -87,6 +87,7 @@
|
||||
#include "memory.h"
|
||||
#include "util.h"
|
||||
#include "event.h"
|
||||
#include "ignore-value.h"
|
||||
|
||||
#define VIR_FROM_THIS VIR_FROM_REMOTE
|
||||
|
||||
@ -8386,6 +8387,7 @@ remoteIOEventLoop(virConnectPtr conn,
|
||||
struct remote_thread_call *tmp = priv->waitDispatch;
|
||||
struct remote_thread_call *prev;
|
||||
char ignore;
|
||||
sigset_t oldmask, blockedsigs;
|
||||
|
||||
fds[0].events = fds[0].revents = 0;
|
||||
fds[1].events = fds[1].revents = 0;
|
||||
@ -8407,10 +8409,24 @@ remoteIOEventLoop(virConnectPtr conn,
|
||||
* can stuff themselves on the queue */
|
||||
remoteDriverUnlock(priv);
|
||||
|
||||
/* 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);
|
||||
sigaddset (&blockedsigs, SIGWINCH);
|
||||
sigaddset (&blockedsigs, SIGCHLD);
|
||||
sigaddset (&blockedsigs, SIGPIPE);
|
||||
ignore_value (pthread_sigmask(SIG_BLOCK, &blockedsigs, &oldmask));
|
||||
|
||||
repoll:
|
||||
ret = poll(fds, ARRAY_CARDINALITY(fds), -1);
|
||||
if (ret < 0 && errno == EAGAIN)
|
||||
goto repoll;
|
||||
|
||||
ignore_value (pthread_sigmask(SIG_SETMASK, &oldmask, NULL));
|
||||
|
||||
remoteDriverLock(priv);
|
||||
|
||||
if (fds[1].revents) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user