]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Ensure pid file is removed when metadata ns daemon receives SIGTERM
authorDarragh O'Reilly <dara2002-openstack@yahoo.com>
Tue, 10 Sep 2013 09:06:28 +0000 (09:06 +0000)
committerDarragh O'Reilly <dara2002-openstack@yahoo.com>
Tue, 10 Sep 2013 09:06:28 +0000 (09:06 +0000)
These files from the metadata namespace proxy are not being removed
because delete_pid() is registered with atexit. This means it only runs
when a process exits normally and won't run when a process receives a
signal.

This patch registers a signal handler for SIGTERM that calls exit()
to make the process exit normally so delete_pid() gets called.

Fixes bug: 1223250

Change-Id: I6309802e2109359560ccc084559ec8e4d310cce2

neutron/agent/linux/daemon.py
neutron/tests/unit/test_linux_daemon.py

index 2825679a3a7f38b6ea6acfa4452fc200b1e94af3..3df12d580e8ecb9428360fc5772f61c9ae5457be 100644 (file)
@@ -19,6 +19,7 @@
 import atexit
 import fcntl
 import os
+import signal
 import sys
 
 from neutron.agent.linux import utils
@@ -123,11 +124,15 @@ class Daemon(object):
 
         # write pidfile
         atexit.register(self.delete_pid)
+        signal.signal(signal.SIGTERM, self.handle_sigterm)
         self.pidfile.write(os.getpid())
 
     def delete_pid(self):
         os.remove(str(self.pidfile))
 
+    def handle_sigterm(self, signum, frame):
+        sys.exit(0)
+
     def start(self):
         """Start the daemon."""
 
index 2fc27a4aab1d0c86b7747d0df6c728f41cb78d87..c4cf3223ce39361f77e7f015c8e4ebc764afb8ff 100644 (file)
@@ -160,13 +160,16 @@ class TestDaemon(base.BaseTestCase):
         d = daemon.Daemon('pidfile')
         with mock.patch.object(d, '_fork') as fork:
             with mock.patch.object(daemon, 'atexit') as atexit:
-                with mock.patch.object(daemon, 'sys') as sys:
-                    sys.stdin.fileno.return_value = 0
-                    sys.stdout.fileno.return_value = 1
-                    sys.stderr.fileno.return_value = 2
-                    d.daemonize()
-                    atexit.register.assert_called_once_with(d.delete_pid)
-
+                with mock.patch.object(daemon, 'signal') as signal:
+                    signal.SIGTERM = 15
+                    with mock.patch.object(daemon, 'sys') as sys:
+                        sys.stdin.fileno.return_value = 0
+                        sys.stdout.fileno.return_value = 1
+                        sys.stderr.fileno.return_value = 2
+                        d.daemonize()
+
+                    signal.signal.assert_called_once_with(15, d.handle_sigterm)
+                atexit.register.assert_called_once_with(d.delete_pid)
             fork.assert_has_calls([mock.call(), mock.call()])
 
         self.os.assert_has_calls([
@@ -185,6 +188,12 @@ class TestDaemon(base.BaseTestCase):
         d.delete_pid()
         self.os.remove.assert_called_once_with('pidfile')
 
+    def test_handle_sigterm(self):
+        d = daemon.Daemon('pidfile')
+        with mock.patch.object(daemon, 'sys') as sys:
+            d.handle_sigterm(15, 1234)
+            sys.exit.assert_called_once_with(0)
+
     def test_start(self):
         self.pidfile.return_value.is_running.return_value = False
         d = daemon.Daemon('pidfile')