On 3/18/24 09:38, Daniel Ding wrote: > > >> 2024年3月16日 上午9:17,Ilya Maximets <[email protected] >> <mailto:[email protected]>> 写道: >> >> On 2/23/24 04:37, Daniel Ding wrote: >>> 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] >>> <mailto:[email protected]>> >>> --- >>> python/ovs/fatal_signal.py | 24 +++++++++++++----------- >>> utilities/ovs-tcpdump.in <http://ovs-tcpdump.in> | 38 >>> +++++++++++++++++--------------------- >>> 2 files changed, 30 insertions(+), 32 deletions(-) >> >> Sorry for the late response. Thanks for v2! >> >> I did some testing and it seem to fix the problem, though in case the ovsdb >> connection is no longer available for some reason, we would block forever in >> the handler waiting for the server to reply while the signals are blocked. >> So, it's getting harder to kill the ovs-tcpdump in this situation. But I >> don't really have a solution for this. We will have either this problem or >> lingering ports and mirrors as long as we're trying to communicate with the >> external process in the signal handler. >> >> I think, it's an OK trade-off to make. Double Ctrl+C seems like a more >> frequent event than paused or stuck ovsdb-server, so I think it's OK to have >> this patch. >> >> See a few minor comments below. >> > > Please help me review the following patch again, Thanks! > >> Best regards, Ilya Maximets. >> >>> >>> 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) >> >> The indentation here is incorrect: >> >> python/ovs/fatal_signal.py:134:8: E114 indentation is not a multiple of 4 >> (comment) >> python/ovs/fatal_signal.py:135:8: E114 indentation is not a multiple of 4 >> (comment) >> python/ovs/fatal_signal.py:136:8: E111 indentation is not a multiple of 4 >> python/ovs/fatal_signal.py:137:8: E111 indentation is not a multiple of 4 > > Done > >> >>> + >>> >>> _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 <http://ovs-tcpdump.in> >>> b/utilities/ovs-tcpdump.in <http://ovs-tcpdump.in> >>> index 4cbd9a5d3..0731b4ac8 100755 >>> --- a/utilities/ovs-tcpdump.in <http://ovs-tcpdump.in> >>> +++ b/utilities/ovs-tcpdump.in <http://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. >> >> I'm not sure if we need this comment. >> The code below will not be executed after Ctrl+C. We will go >> directly to the signal handler, execute hooks and raise the >> signal that will terminate the program. >> >> The only way we can end up here is if underlying tcpdump exited >> for some reason and we're in the process of graceful termination. >> >> I think, we should keep the code below, but it seems that the >> comment lost its meaning. >> >> Does that make sense? >> > > OK, I removed the comment and keep the code bellow. > >> >>> 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 >> >> And here the indentation is not right: >> >> utilities/ovs-tcpdump.in:550 <http://ovs-tcpdump.in:550/>:8: E111 >> indentation is not a multiple of 4 >> utilities/ovs-tcpdump.in:552 <http://ovs-tcpdump.in:552/>:8: E111 >> indentation is not a multiple of 4 >> >>> >>> - sys.exit(0) >>> + if pipes.poll() is None: >>> + pipes.terminate() >>> >>> >>> if __name__ == '__main__’: > > > 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 was not > registered to the signal handler. When received CTRL+C again, the program > was broken, and calling hook could not be executed completely. > > Signed-off-by: Daniel Ding <[email protected] > <mailto:[email protected]>> > --- > python/ovs/fatal_signal.py | 24 +++++++++++++----------- > utilities/ovs-tcpdump.in <http://ovs-tcpdump.in> | 32 > +++++++++++--------------------- > 2 files changed, 24 insertions(+), 32 deletions(-)
Thanks! This seems correct to me. Could you send it as a new PATCH v3 ? Best regards, Ilya Maximets. > > diff --git a/python/ovs/fatal_signal.py b/python/ovs/fatal_signal.py > index cb2e99e87..16a7e78a0 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 <http://ovs-tcpdump.in> > b/utilities/ovs-tcpdump.in <http://ovs-tcpdump.in> > index 4cbd9a5d3..eada803bb 100755 > --- a/utilities/ovs-tcpdump.in <http://ovs-tcpdump.in> > +++ b/utilities/ovs-tcpdump.in <http://ovs-tcpdump.in> > @@ -534,29 +534,19 @@ def main(): > ovsdb.close_idl() > > pipes = _doexec(*([dump_cmd, '-i', mirror_interface] + tcpdargs)) > - 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 > + while pipes.poll() is None: > + data = pipes.stdout.readline().strip(b'\n') > + if len(data) == 0: > + break > + print(data.decode('utf-8')) > > - if pipes.poll() is None: > - pipes.terminate() > + try: > + sys.stdout.close() > + except IOError: > + pass > > - sys.exit(0) > + if pipes.poll() is None: > + pipes.terminate() > > > if __name__ == '__main__': > -- > 2.43.0 > > > > Regards, > Daniel Ding > > > _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
