1313import logging
1414import os
1515import random
16- # import signal
16+ import signal
1717from sys import version as python_version , version_info , platform
1818from os .path import join , basename , getmtime , getsize
1919from os import remove
@@ -183,6 +183,7 @@ def ll(self, msg):
183183 logger .error ('DE p REGISTER_MODE: {0}, {1}, {2}' .format (* self .playlist_selections [2 ]))
184184
185185 def __init__ (self , pyradio_config , play = False , req_player = '' , theme = '' ):
186+ self ._system_asked_to_terminate = False
186187 self ._cnf = pyradio_config
187188 self ._theme = PyRadioTheme (self ._cnf )
188189 if theme :
@@ -694,6 +695,7 @@ def __displayBodyLine(self, lineNum, pad, station):
694695 self .bodyWin .chgat (lineNum , n , 1 , sep_col )
695696
696697 def run (self ):
698+ self ._register_signals_handlers ()
697699 if self .ws .operation_mode == self .ws .NO_PLAYER_ERROR_MODE :
698700 if self .requested_player :
699701 if ',' in self .requested_player :
@@ -707,7 +709,6 @@ def run(self):
707709 except KeyboardInterrupt :
708710 pass
709711 else :
710- self ._register_windows_handlers ()
711712
712713 # start update detection and notification thread
713714 if CAN_CHECK_FOR_UPDATES :
@@ -751,7 +752,7 @@ def run(self):
751752 return
752753 except KeyboardInterrupt :
753754 if logger .isEnabledFor (logging .DEBUG ):
754- logger .debug ('Ctrl-C pressed... Exiting ...' )
755+ logger .debug ('Ctrl-C pressed... Terminating ...' )
755756 self .player .ctrl_c_pressed = True
756757 self .ctrl_c_handler (0 , 0 )
757758 break
@@ -2894,7 +2895,7 @@ def to_time(secs):
28942895 clean_date_files (files , - 1 )
28952896 create_tadays_date_file (a_path )
28962897 if logger .isEnabledFor (logging .INFO ):
2897- logger .info ('detectUpdateThread: No update found. Will check again in {} days. Exiting ...' .format (check_days ))
2898+ logger .info ('detectUpdateThread: No update found. Will check again in {} days. Terminating ...' .format (check_days ))
28982899 break
28992900 else :
29002901 # PROGRAM DEBUG: set program's version
@@ -2962,7 +2963,7 @@ def to_time(secs):
29622963 connection_fail_count += 1
29632964 if connection_fail_count > 4 :
29642965 if logger .isEnabledFor (logging .ERROR ):
2965- logger .error ('detectUpdateThread: Error: Too many connection failures. Exiting ...' )
2966+ logger .error ('detectUpdateThread: Error: Too many connection failures. Terminating ...' )
29662967 break
29672968 delay (60 , stop )
29682969
@@ -3222,6 +3223,12 @@ def _fix_playlist_highlight_after_rename(self, old_file, new_file, copy_file, op
32223223 return ret
32233224
32243225 def keypress (self , char ):
3226+ if self ._system_asked_to_terminate :
3227+ """ Make sure we exit when signal received """
3228+ if logger .isEnabledFor (logging .debug ):
3229+ logger .debug ('keypress: Asked to stop. Stoping...' )
3230+ return - 1
3231+
32253232 if char in (ord ('#' ), curses .KEY_RESIZE ):
32263233 self ._normal_mode_resize ()
32273234 self ._do_display_notify ()
@@ -4019,7 +4026,7 @@ def keypress(self, char):
40194026 char not in self ._chars_to_bypass and \
40204027 char not in self ._chars_to_bypass_for_search and \
40214028 char not in (ord ('T' ),)):
4022- logger .error ('DE \n \n Exiting theme selector?\n \n ' )
4029+ logger .error ('DE \n \n Terminating theme selector?\n \n ' )
40234030 theme_id , save_theme = self ._theme_selector .keypress (char )
40244031
40254032 #if self._cnf.theme_not_supported:
@@ -5426,7 +5433,7 @@ def _show_http_connection(self):
54265433 """''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
54275434 Windows only section
54285435 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''"""
5429- def _register_windows_handlers (self ):
5436+ def _register_signals_handlers (self ):
54305437 if platform .startswith ('win' ):
54315438 """ disable close button """
54325439 import win32console , win32gui , win32con , win32api
@@ -5436,8 +5443,12 @@ def _register_windows_handlers(self):
54365443 if hMenu :
54375444 try :
54385445 win32gui .DeleteMenu (hMenu , win32con .SC_CLOSE , win32con .MF_BYCOMMAND )
5446+ if logger .isEnabledFor (logging .DEBUG ):
5447+ logger .debug ('SetConsoleCtrlHandler: close button disabled' )
54395448 except :
5440- pass
5449+ if logger .isEnabledFor (logging .DEBUG ):
5450+ logger .debug ('SetConsoleCtrlHandler: failed to disable close button' )
5451+
54415452 """ install handlers for exit / close signals"""
54425453 try :
54435454 result = win32api .SetConsoleCtrlHandler (self ._windows_signal_handler , True )
@@ -5451,37 +5462,91 @@ def _register_windows_handlers(self):
54515462 logger .debug ('SetConsoleCtrlHandler: Failed to register (with Exception)!!!' )
54525463 # Trying to catch Windows log-ogg, reboot, halt
54535464 # No luck....
5454- #import signal
5455- #try:
5456- # signal.signal(signal.SIGINT, self._windows_signal_handler)
5457- #except:
5458- # if logger.isEnabledFor(logging.DEBUG):
5459- # logger.debug('SetConsoleCtrlHandler: Signal SIGINT failed to register (with Exception)!!!')
5460-
5461- #try:
5462- # signal.signal(signal.SIGINT, self._windows_signal_handler)
5463- #except:
5464- # if logger.isEnabledFor(logging.DEBUG):
5465- # logger.debug('SetConsoleCtrlHandler: Signal SIGINT failed to register (with Exception)!!!')
5465+ # import signal
5466+ # try:
5467+ # signal.signal(signal.SIGINT, self._windows_signal_handler)
5468+ # except:
5469+ # if logger.isEnabledFor(logging.DEBUG):
5470+ # logger.debug('SetConsoleCtrlHandler: Signal SIGINT failed to register (with Exception)!!!')
5471+
5472+ # try:
5473+ # signal.signal(signal.SIGINT, self._windows_signal_handler)
5474+ # except:
5475+ # if logger.isEnabledFor(logging.DEBUG):
5476+ # logger.debug('SetConsoleCtrlHandler: Signal SIGINT failed to register (with Exception)!!!')
5477+
5478+ else :
5479+ self .handled_signals = {
5480+ 'SIGHUP' : signal .SIGHUP ,
5481+ 'SIGTERM' : signal .SIGTERM ,
5482+ 'SIGKIL' : signal .SIGKILL ,
5483+ }
5484+ self .def_signal_handlers = {}
5485+ try :
5486+ for a_sig in self .handled_signals .keys ():
5487+ self .def_signal_handlers [a_sig ] = signal .signal (
5488+ self .handled_signals [a_sig ],
5489+ self ._linux_signal_handler
5490+ )
5491+ if logger .isEnabledFor (logging .DEBUG ):
5492+ logger .debug ('SetConsoleCtrlHandler: Handler for signal {} registered' .format (a_sig ))
5493+ except :
5494+ if logger .isEnabledFor (logging .DEBUG ):
5495+ logger .debug ('SetConsoleCtrlHandler: Failed to register handler for signal {}' .format (a_sig ))
5496+
5497+ def _linux_signal_handler (self , a_signal , a_frame ):
5498+ if self ._system_asked_to_terminate :
5499+ return
5500+ self ._system_asked_to_terminate = True
5501+ if logger .isEnabledFor (logging .INFO ):
5502+ # logger.info('System asked me to terminate (signal: {})!!!'.format(list(self.handled_signals.keys())[list(self.handled_signals.values()).index(a_signal)]))
5503+ logger .info ('My terminal got closed... Terminating...' )
5504+ self ._force_exit = True
5505+ self .stop_update_notification_thread = True
5506+ self .player .stop_timeout_counter_thread = True
5507+ if self .ws .operation_mode != self .ws .PLAYLIST_MODE :
5508+ if self ._cnf .dirty_playlist :
5509+ self ._cnf .save_playlist_file ()
5510+ self .player .close ()
5511+ self ._cnf .save_config ()
5512+ #self._wait_for_threads()
5513+ self ._cnf .remove_session_lock_file ()
5514+ for a_sig in self .handled_signals .keys ():
5515+ try :
5516+ signal .signal (
5517+ self .handled_signals [a_sig ],
5518+ self .def_signal_handlers [a_sig ]
5519+ )
5520+ except :
5521+ pass
54665522
54675523 def _windows_signal_handler (self , event ):
54685524 """ windows signal handler
54695525 https://danielkaes.wordpress.com/2009/06/04/how-to-catch-kill-events-with-python/
54705526 """
5471- import win32con , win32api , signal
5527+ import win32con , win32api
54725528 if event in (win32con .CTRL_C_EVENT ,
5473- win32con .CTRL_LOGOFF_EVENT ,
5474- win32con .CTRL_BREAK_EVENT ,
5475- win32con .CTRL_SHUTDOWN_EVENT ,
5476- win32con .CTRL_CLOSE_EVENT ,
5477- signal .SIGINT ,
5478- signal .SIGBREAK ):
5529+ win32con .CTRL_LOGOFF_EVENT ,
5530+ win32con .CTRL_BREAK_EVENT ,
5531+ win32con .CTRL_SHUTDOWN_EVENT ,
5532+ win32con .CTRL_CLOSE_EVENT ,
5533+ signal .SIGINT ,
5534+ signal .SIGBREAK ):
5535+ if self ._system_asked_to_terminate :
5536+ return
5537+ self ._system_asked_to_terminate = True
5538+ if logger .isEnabledFor (logging .INFO ):
5539+ logger .info ('My console window got closed... Terminating...' )
54795540 self ._force_exit = True
5480- self .ctrl_c_handler (0 ,0 )
5481- if logger .isEnabledFor (logging .DEBUG ):
5482- logger .debug ('Windows asked me to terminate!!' )
5541+ self .player .close_from_windows ()
5542+ self ._cnf .save_config ()
5543+ self ._wait_for_threads ()
5544+ self ._cnf .remove_session_lock_file ()
5545+ if self .ws .operation_mode != self .ws .PLAYLIST_MODE :
5546+ if self ._cnf .dirty_playlist :
5547+ self ._cnf .save_playlist_file ()
54835548 try :
5484- result = win32api .SetConsoleCtrlHandler (self ._windows_signal_handler , False )
5549+ win32api .SetConsoleCtrlHandler (self ._windows_signal_handler , False )
54855550 except :
54865551 pass
54875552 return False
0 commit comments