From 6e7e58b4f3a33bb5a02ed967893b8ec20c0f262f Mon Sep 17 00:00:00 2001
From: Guido Trotter <ultrotter@google.com>
Date: Tue, 1 Jun 2010 17:56:52 +0100
Subject: [PATCH] AsyncUDPSocket: fix IgnoreSignals usage and test

This bug was found in the asyncore master patch series, but actually
applies to 2.1 for AsyncUDPSocket as well.

Signed-off-by: Guido Trotter <ultrotter@google.com>
Reviewed-by: Michael Hanselmann <hansmi@google.com>
---
 lib/daemon.py                  | 10 ++++++----
 test/ganeti.daemon_unittest.py | 16 ++++++++++++++++
 2 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/lib/daemon.py b/lib/daemon.py
index d4989f7dd..7ed845f65 100644
--- a/lib/daemon.py
+++ b/lib/daemon.py
@@ -112,10 +112,12 @@ class AsyncUDPSocket(GanetiBaseAsyncoreDispatcher):
 
   # this method is overriding an asyncore.dispatcher method
   def handle_read(self):
-    payload, address = utils.IgnoreSignals(self.recvfrom,
-                                           constants.MAX_UDP_DATA_SIZE)
-    ip, port = address
-    self.handle_datagram(payload, ip, port)
+    recv_result = utils.IgnoreSignals(self.recvfrom,
+                                      constants.MAX_UDP_DATA_SIZE)
+    if recv_result is not None:
+      payload, address = recv_result
+      ip, port = address
+      self.handle_datagram(payload, ip, port)
 
   def handle_datagram(self, payload, ip, port):
     """Handle an already read udp datagram
diff --git a/test/ganeti.daemon_unittest.py b/test/ganeti.daemon_unittest.py
index 81912ee18..d00c89725 100755
--- a/test/ganeti.daemon_unittest.py
+++ b/test/ganeti.daemon_unittest.py
@@ -28,6 +28,7 @@ import socket
 import time
 
 from ganeti import daemon
+from ganeti import utils
 
 import testutils
 
@@ -170,10 +171,14 @@ class TestAsyncUDPSocket(testutils.GanetiTestCase):
     self.client = _MyAsyncUDPSocket()
     self.server.bind(("127.0.0.1", 0))
     self.port = self.server.getsockname()[1]
+    # Save utils.IgnoreSignals so we can do evil things to it...
+    self.saved_utils_ignoresignals = utils.IgnoreSignals
 
   def tearDown(self):
     self.server.close()
     self.client.close()
+    # ...and restore it as well
+    utils.IgnoreSignals = self.saved_utils_ignoresignals
     testutils.GanetiTestCase.tearDown(self)
 
   def testNoDoubleBind(self):
@@ -219,6 +224,17 @@ class TestAsyncUDPSocket(testutils.GanetiTestCase):
                       ["p1", "p2", "error", "p3", "error", "terminate"])
     self.assertEquals(self.server.error_count, 2)
 
+  def testSignaledWhileReceiving(self):
+    utils.IgnoreSignals = lambda fn, *args, **kwargs: None
+    self.client.enqueue_send("127.0.0.1", self.port, "p1")
+    self.client.enqueue_send("127.0.0.1", self.port, "p2")
+    self.server.handle_read()
+    self.assertEquals(self.server.received, [])
+    self.client.enqueue_send("127.0.0.1", self.port, "terminate")
+    utils.IgnoreSignals = self.saved_utils_ignoresignals
+    self.mainloop.Run()
+    self.assertEquals(self.server.received, ["p1", "p2", "terminate"])
+
 
 if __name__ == "__main__":
   testutils.GanetiTestProgram()
-- 
GitLab