[libvirt] [PATCH] Prevent overfilling of self-pipe in python event loop

If the event loop takes a very long time todo something, it is possible for the 'self pipe' buffer to become full at which point the entire event loop + remote driver deadlock. Use a boolean flag to ensure we have strict one-in, one-out behaviour on writes/reads of the 'self pipe' --- examples/domain-events/events-python/event-test.py | 10 +++++++++- 1 files changed, 9 insertions(+), 1 deletions(-) diff --git a/examples/domain-events/events-python/event-test.py b/examples/domain-events/events-python/event-test.py index 903f934..c149ed9 100644 --- a/examples/domain-events/events-python/event-test.py +++ b/examples/domain-events/events-python/event-test.py @@ -92,6 +92,8 @@ class virEventLoopPure: def __init__(self): self.poll = select.poll() self.pipetrick = os.pipe() + self.pendingWakeup = False + self.runningPoll = False self.nextHandleID = 1 self.nextTimerID = 1 self.handles = [] @@ -166,6 +168,7 @@ class virEventLoopPure: # these pointless repeated tiny sleeps. def run_once(self): sleep = -1 + self.runningPoll = True next = self.next_timeout() debug("Next timeout due at %d" % next) if next > 0: @@ -184,6 +187,7 @@ class virEventLoopPure: # telling us to wakup. if so, then discard # the data just continue if fd == self.pipetrick[0]: + self.pendingWakeup = False data = os.read(fd, 1) continue @@ -206,6 +210,8 @@ class virEventLoopPure: t.set_last_fired(now) t.dispatch() + self.runningPoll = False + # Actually the event loop forever def run_loop(self): @@ -214,7 +220,9 @@ class virEventLoopPure: self.run_once() def interrupt(self): - os.write(self.pipetrick[1], 'c') + if self.runningPoll and not self.pendingWakeup: + self.pendingWakeup = True + os.write(self.pipetrick[1], 'c') # Registers a new file handle 'fd', monitoring for 'events' (libvirt -- 1.7.3.4

On Thu, Jan 27, 2011 at 12:56:24PM +0000, Daniel P. Berrange wrote:
If the event loop takes a very long time todo something, it is possible for the 'self pipe' buffer to become full at which point the entire event loop + remote driver deadlock. Use a boolean flag to ensure we have strict one-in, one-out behaviour on writes/reads of the 'self pipe' --- examples/domain-events/events-python/event-test.py | 10 +++++++++- 1 files changed, 9 insertions(+), 1 deletions(-)
diff --git a/examples/domain-events/events-python/event-test.py b/examples/domain-events/events-python/event-test.py index 903f934..c149ed9 100644 --- a/examples/domain-events/events-python/event-test.py +++ b/examples/domain-events/events-python/event-test.py @@ -92,6 +92,8 @@ class virEventLoopPure: def __init__(self): self.poll = select.poll() self.pipetrick = os.pipe() + self.pendingWakeup = False + self.runningPoll = False self.nextHandleID = 1 self.nextTimerID = 1 self.handles = [] @@ -166,6 +168,7 @@ class virEventLoopPure: # these pointless repeated tiny sleeps. def run_once(self): sleep = -1 + self.runningPoll = True next = self.next_timeout() debug("Next timeout due at %d" % next) if next > 0: @@ -184,6 +187,7 @@ class virEventLoopPure: # telling us to wakup. if so, then discard # the data just continue if fd == self.pipetrick[0]: + self.pendingWakeup = False data = os.read(fd, 1) continue
@@ -206,6 +210,8 @@ class virEventLoopPure: t.set_last_fired(now) t.dispatch()
+ self.runningPoll = False +
# Actually the event loop forever def run_loop(self): @@ -214,7 +220,9 @@ class virEventLoopPure: self.run_once()
def interrupt(self): - os.write(self.pipetrick[1], 'c') + if self.runningPoll and not self.pendingWakeup: + self.pendingWakeup = True + os.write(self.pipetrick[1], 'c')
# Registers a new file handle 'fd', monitoring for 'events' (libvirt
ACK, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/
participants (2)
-
Daniel P. Berrange
-
Daniel Veillard