2525"""
2626
2727import curses
28+ import signal
2829import threading
2930from threading import Lock
3031import time
@@ -42,7 +43,7 @@ class GreenwaveNcursesFrontend(Node):
4243 def __init__ (self ):
4344 super ().__init__ ('greenwave_ncurses_frontend' )
4445
45- self .running = False
46+ self .running = True
4647 self .selected_row = 0
4748 self .scroll_offset = 0
4849 self .ui_adaptor : Optional [GreenwaveUiAdaptor ] = None
@@ -158,7 +159,7 @@ def curses_main(stdscr, node):
158159 curses .init_pair (COLOR_STATUS_MSG , curses .COLOR_BLUE , curses .COLOR_BLACK )
159160 curses .init_pair (COLOR_STALE , curses .COLOR_CYAN , curses .COLOR_BLACK )
160161
161- while rclpy .ok ():
162+ while rclpy .ok () and node . running :
162163 current_time = time .time ()
163164
164165 # Always check for input
@@ -264,6 +265,7 @@ def curses_main(stdscr, node):
264265 start_idx + visible_height )
265266 selected_row = min (len (node .visible_topics ) - 1 , selected_row + visible_height )
266267 elif key == ord ('q' ) or key == ord ('Q' ):
268+ node .running = False
267269 break
268270 elif key == ord ('\n ' ) or key == ord (' ' ):
269271 if 0 <= selected_row < len (node .visible_topics ):
@@ -447,14 +449,26 @@ def curses_main(stdscr, node):
447449def main (args = None ):
448450 rclpy .init (args = args )
449451 node = GreenwaveNcursesFrontend ()
452+ thread = None
453+
454+ def signal_handler (signum , frame ):
455+ """Handle shutdown signals gracefully."""
456+ node .running = False
457+
458+ # Register signal handlers
459+ signal .signal (signal .SIGINT , signal_handler )
460+ signal .signal (signal .SIGTERM , signal_handler )
450461
451462 try :
452- thread = threading .Thread (target = rclpy .spin , args = (node ,), daemon = True )
463+ thread = threading .Thread (target = rclpy .spin , args = (node ,), daemon = False )
453464 thread .start ()
454465 curses .wrapper (curses_main , node )
455466 except KeyboardInterrupt :
456- pass
467+ node . running = False
457468 finally :
469+ node .running = False
470+ if thread is not None and thread .is_alive ():
471+ thread .join (timeout = 0.5 )
458472 node .destroy_node ()
459473 rclpy .shutdown ()
460474
0 commit comments