BIND 10 trac642, updated. db92eedf80baf664de114dd04980cea7b8c3f85c Insure that we don't exit due to writing when we are shutting down.

BIND 10 source code commits bind10-changes at lists.isc.org
Wed Apr 20 11:27:55 UTC 2011


The branch, trac642 has been updated
       via  db92eedf80baf664de114dd04980cea7b8c3f85c (commit)
      from  49deb2642865c1db3e65e6066949b6fa8dbcbe26 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit db92eedf80baf664de114dd04980cea7b8c3f85c
Author: Shane Kerr <shane at isc.org>
Date:   Wed Apr 20 13:21:44 2011 +0200

    Insure that we don't exit due to writing when we are shutting down.

-----------------------------------------------------------------------

Summary of changes:
 src/bin/bind10/bind10.py.in            |   78 +++++++++++++++++++++++--------
 src/bin/bind10/tests/bind10_test.py.in |   28 +++++++++++-
 2 files changed, 84 insertions(+), 22 deletions(-)

-----------------------------------------------------------------------
diff --git a/src/bin/bind10/bind10.py.in b/src/bin/bind10/bind10.py.in
index f72f314..59e764b 100755
--- a/src/bin/bind10/bind10.py.in
+++ b/src/bin/bind10/bind10.py.in
@@ -667,10 +667,15 @@ class BoB:
 
     def shutdown(self):
         """Stop the BoB instance."""
+        # Note that we try harder than usual to continue in the face of
+        # errors.
         if self.verbose:
-            sys.stdout.write("[bind10] Stopping the server.\n")
-        # first try using the BIND 10 request to stop
+            try:
+                sys.stdout.write("[bind10] Stopping the server.\n")
+            except:
+                pass
         try:
+            # first try using the BIND 10 request to stop
             self.stop_all_processes()
         except:
             pass
@@ -683,10 +688,14 @@ class BoB:
         processes_to_stop = list(self.processes.values())
         for proc_info in processes_to_stop:
             if self.verbose:
-                sys.stdout.write("[bind10] Sending SIGTERM to %s (PID %d).\n" % 
-                                 (proc_info.name, proc_info.pid))
+                try:
+                    sys.stdout.write("[bind10] Sending SIGTERM to %s (PID %d).\n" % 
+                                     (proc_info.name, proc_info.pid))
+                except:
+                    pass
             try:
-                proc_info.process.terminate()
+                if proc_info.process:
+                    proc_info.process.terminate()
             except OSError:
                 # ignore these (usually ESRCH because the child
                 # finally exited)
@@ -699,16 +708,26 @@ class BoB:
             processes_to_stop = list(self.processes.values())
             for proc_info in processes_to_stop:
                 if self.verbose:
-                    sys.stdout.write("[bind10] Sending SIGKILL to %s (PID %d).\n" % 
-                                     (proc_info.name, proc_info.pid))
+                    try:
+                        sys.stdout.write("[bind10] Sending SIGKILL to %s (PID %d).\n" % 
+                                         (proc_info.name, proc_info.pid))
+                    except:
+                        pass
                 try:
-                    proc_info.process.kill()
+                    if proc_info.process:
+                        proc_info.process.kill()
                 except OSError:
                     # ignore these (usually ESRCH because the child
                     # finally exited)
                     pass
         if self.verbose:
-            sys.stdout.write("[bind10] All processes ended, server done.\n")
+            try:
+                sys.stdout.write("[bind10] All processes ended, server done.\n")
+            except:
+                pass
+
+    def wait_on_child(self):
+        return os.waitpid(-1, os.WNOHANG)
 
     def reap_children(self):
         """Check to see if any of our child processes have exited, 
@@ -716,7 +735,7 @@ class BoB:
         """
         while True:
             try:
-                (pid, exit_status) = os.waitpid(-1, os.WNOHANG)
+                (pid, exit_status) = self.wait_on_child()
             except OSError as o:
                 if o.errno == errno.ECHILD: break
                 # XXX: should be impossible to get any other error here
@@ -734,21 +753,36 @@ class BoB:
                 # elsewhere.
                 if self.runnable:
                     if exit_status is None:
-                        sys.stdout.write(
-                            "[bind10] Process %s (PID %d) died: exit status not available" % 
-                            (proc_info.name, proc_info.pid))
+                        try:
+                            sys.stdout.write(
+                                "[bind10] Process %s (PID %d) died: exit status not available" % 
+                                (proc_info.name, proc_info.pid))
+                        except:
+                            # Error writing - shutdown
+                            self.runnable = False
                     else:
-                        sys.stdout.write(
-                            "[bind10] Process %s (PID %d) terminated, exit status = %d\n" % 
-                            (proc_info.name, proc_info.pid, exit_status))
+                        try:
+                            sys.stdout.write(
+                                "[bind10] Process %s (PID %d) terminated, exit status = %d\n" % 
+                                (proc_info.name, proc_info.pid, exit_status))
+                        except:
+                            # Error writing - shutdown
+                            self.runnable = False
 
                     # Was it a special process?
                     if proc_info.name == "b10-msgq":
-                        sys.stdout.write(
-                                 "[bind10] The b10-msgq process died, shutting down.\n")
+                        try:
+                            sys.stdout.write(
+                                     "[bind10] The b10-msgq process died, shutting down.\n")
+                        except:
+                            pass
                         self.runnable = False
             else:
-                sys.stdout.write("[bind10] Unknown child pid %d exited.\n" % pid)
+                try:
+                    sys.stdout.write("[bind10] Unknown child pid %d exited.\n" % pid)
+                except:
+                    # Error writing - shutdown
+                    self.runnable = False
 
     def restart_processes(self):
         """
@@ -1054,7 +1088,11 @@ def main():
     sys.stdout.write("[bind10] BIND 10 started\n")
     report_boot_time()
     main_loop(wakeup_pipe)
-    sys.stdout.write("[bind10] BIND 10 exiting\n");
+    try:
+        sys.stdout.write("[bind10] BIND 10 exiting\n");
+    except:
+        # do not let failure to write cause problems here!
+        pass
     shutdown()
 
 if __name__ == "__main__":
diff --git a/src/bin/bind10/tests/bind10_test.py.in b/src/bin/bind10/tests/bind10_test.py.in
index 2178724..63d3f4f 100644
--- a/src/bin/bind10/tests/bind10_test.py.in
+++ b/src/bin/bind10/tests/bind10_test.py.in
@@ -28,6 +28,7 @@ import sys
 import os
 import signal
 import socket
+import errno
 from isc.net.addr import IPAddr
 from isc.testutils.parse_args import TestOptParser, OptsError
 
@@ -263,6 +264,13 @@ class MockBob(BoB):
             del self.processes[11]
         self.cmdctl = False
 
+    def wait_on_child(self):
+        if self.processes:
+            pid = list(self.processes.keys())[0]
+            return (pid, 0)
+        else:
+            raise OSError(errno.ECHILD, 'No child processes')
+
 class TestStartStopProcessesBob(unittest.TestCase):
     """
     Check that the start_all_processes method starts the right combination
@@ -669,6 +677,7 @@ class TestTTYDisconnect(unittest.TestCase):
     # Here we check what happens if the TTY we are outputting go goes 
     # away. 
     def test_tty_disconnect(self):
+        # some setup for the test, putting our test harness in place
         self.save_bob_class = bind10.BoB
         self.save_stdout = sys.stdout
         self.save_stderr = sys.stderr
@@ -676,19 +685,34 @@ class TestTTYDisconnect(unittest.TestCase):
         bind10.BoB = MockBob
         sys.stdout = open("/dev/null", "w")
         self.wakeup_pipe = os.pipe()
+
+        # now set up
         bind10.setup(self.wakeup_pipe)
 
+        # close the output and see what happens
         sys.stdout.close()
         sys.stderr = open("/dev/null", "w")
         bind10.main_loop(self.wakeup_pipe)
 
+        # restore our file descriptors so we can see if we caused problems
         sys.stderr = self.save_stderr
         sys.stdout = self.save_stdout
-        os.close(self.wakeup_pipe[0])
-        os.close(self.wakeup_pipe[1])
 
+        # make sure we are supposed to stop now
         self.assertFalse(bind10.boss_of_bind.runnable)
 
+        # try our shutdown (turn on verbose to insure failure)
+        sys.stdout = open("/dev/null", "w")
+        sys.stdout.close()
+        bind10.boss_of_bind.verbose = True
+        bind10.shutdown()
+
+        # cleanup
+        sys.stderr = self.save_stderr
+        sys.stdout = self.save_stdout
+        os.close(self.wakeup_pipe[0])
+        os.close(self.wakeup_pipe[1])
+
         bind10.BoB = self.save_bob_class
         
 




More information about the bind10-changes mailing list