After running ovs-tcpdump and inputs multiple CTRL+C, the program will
raise the following exception.

Error in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "/usr/bin/ovs-tcpdump", line 421, in cleanup_mirror
    ovsdb = OVSDB(db_sock)
  File "/usr/bin/ovs-tcpdump", line 168, in __init__
    OVSDB.wait_for_db_change(self._idl_conn)  # Initial Sync with DB
  File "/usr/bin/ovs-tcpdump", line 155, in wait_for_db_change
    while idl.change_seqno == seq and not idl.run():

The default handler of SIGINT is default_int_handler, so it not
register the signal handler successfully. When received CTRL+C again,
the program be break, and calling hook can't execute completely.

Signed-off-by: Daniel Ding <[email protected]>
---
 python/ovs/fatal_signal.py | 24 +++++++++++++-----------
 utilities/ovs-tcpdump.in   | 38 +++++++++++++++++---------------------
 2 files changed, 30 insertions(+), 32 deletions(-)

diff --git a/python/ovs/fatal_signal.py b/python/ovs/fatal_signal.py
index cb2e99e87..077f50dd5 100644
--- a/python/ovs/fatal_signal.py
+++ b/python/ovs/fatal_signal.py
@@ -16,6 +16,7 @@ import atexit
 import os
 import signal
 import sys
+import threading
 
 import ovs.vlog
 
@@ -112,29 +113,29 @@ def _unlink(file_):
 def _signal_handler(signr, _):
     _call_hooks(signr)
 
-    # Re-raise the signal with the default handling so that the program
-    # termination status reflects that we were killed by this signal.
-    signal.signal(signr, signal.SIG_DFL)
-    os.kill(os.getpid(), signr)
-
 
 def _atexit_handler():
     _call_hooks(0)
 
 
-recurse = False
+mutex = threading.Lock()
 
 
 def _call_hooks(signr):
-    global recurse
-    if recurse:
+    global mutex
+    if not mutex.acquire(blocking=False):
         return
-    recurse = True
 
     for hook, cancel, run_at_exit in _hooks:
         if signr != 0 or run_at_exit:
             hook()
 
+    if signr != 0:
+       # Re-raise the signal with the default handling so that the program
+       # termination status reflects that we were killed by this signal.
+       signal.signal(signr, signal.SIG_DFL)
+       os.kill(os.getpid(), signr)
+
 
 _inited = False
 
@@ -150,7 +151,9 @@ def _init():
                        signal.SIGALRM]
 
         for signr in signals:
-            if signal.getsignal(signr) == signal.SIG_DFL:
+            handler = signal.getsignal(signr)
+            if (handler == signal.SIG_DFL or
+                handler == signal.default_int_handler):
                 signal.signal(signr, _signal_handler)
         atexit.register(_atexit_handler)
 
@@ -165,7 +168,6 @@ def signal_alarm(timeout):
 
     if sys.platform == "win32":
         import time
-        import threading
 
         class Alarm (threading.Thread):
             def __init__(self, timeout):
diff --git a/utilities/ovs-tcpdump.in b/utilities/ovs-tcpdump.in
index 4cbd9a5d3..0731b4ac8 100755
--- a/utilities/ovs-tcpdump.in
+++ b/utilities/ovs-tcpdump.in
@@ -534,29 +534,25 @@ def main():
     ovsdb.close_idl()
 
     pipes = _doexec(*([dump_cmd, '-i', mirror_interface] + tcpdargs))
+    while pipes.poll() is None:
+        data = pipes.stdout.readline().strip(b'\n')
+        if len(data) == 0:
+            break
+        print(data.decode('utf-8'))
+
+    # If there is a pipe behind ovs-tcpdump (such as ovs-tcpdump
+    # -i eth0 | grep "192.168.1.1"), the pipe is no longer available
+    # after received Ctrl+C.
+    # If we write data to an unavailable pipe, a pipe error will be
+    # reported, so we turn off stdout to avoid subsequent flushing
+    # of data into the pipe.
     try:
-        while pipes.poll() is None:
-            data = pipes.stdout.readline().strip(b'\n')
-            if len(data) == 0:
-                raise KeyboardInterrupt
-            print(data.decode('utf-8'))
-        raise KeyboardInterrupt
-    except KeyboardInterrupt:
-        # If there is a pipe behind ovs-tcpdump (such as ovs-tcpdump
-        # -i eth0 | grep "192.168.1.1"), the pipe is no longer available
-        # after received Ctrl+C.
-        # If we write data to an unavailable pipe, a pipe error will be
-        # reported, so we turn off stdout to avoid subsequent flushing
-        # of data into the pipe.
-        try:
-            sys.stdout.close()
-        except IOError:
-            pass
-
-        if pipes.poll() is None:
-            pipes.terminate()
+       sys.stdout.close()
+    except IOError:
+       pass
 
-    sys.exit(0)
+    if pipes.poll() is None:
+        pipes.terminate()
 
 
 if __name__ == '__main__':
-- 
2.43.0

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to