13
13
import logging
14
14
import os
15
15
import random
16
- # import signal
16
+ import signal
17
17
from sys import version as python_version , version_info , platform
18
18
from os .path import join , basename , getmtime , getsize
19
19
from os import remove
@@ -183,6 +183,7 @@ def ll(self, msg):
183
183
logger .error ('DE p REGISTER_MODE: {0}, {1}, {2}' .format (* self .playlist_selections [2 ]))
184
184
185
185
def __init__ (self , pyradio_config , play = False , req_player = '' , theme = '' ):
186
+ self ._system_asked_to_terminate = False
186
187
self ._cnf = pyradio_config
187
188
self ._theme = PyRadioTheme (self ._cnf )
188
189
if theme :
@@ -694,6 +695,7 @@ def __displayBodyLine(self, lineNum, pad, station):
694
695
self .bodyWin .chgat (lineNum , n , 1 , sep_col )
695
696
696
697
def run (self ):
698
+ self ._register_signals_handlers ()
697
699
if self .ws .operation_mode == self .ws .NO_PLAYER_ERROR_MODE :
698
700
if self .requested_player :
699
701
if ',' in self .requested_player :
@@ -707,7 +709,6 @@ def run(self):
707
709
except KeyboardInterrupt :
708
710
pass
709
711
else :
710
- self ._register_windows_handlers ()
711
712
712
713
# start update detection and notification thread
713
714
if CAN_CHECK_FOR_UPDATES :
@@ -751,7 +752,7 @@ def run(self):
751
752
return
752
753
except KeyboardInterrupt :
753
754
if logger .isEnabledFor (logging .DEBUG ):
754
- logger .debug ('Ctrl-C pressed... Exiting ...' )
755
+ logger .debug ('Ctrl-C pressed... Terminating ...' )
755
756
self .player .ctrl_c_pressed = True
756
757
self .ctrl_c_handler (0 , 0 )
757
758
break
@@ -2894,7 +2895,7 @@ def to_time(secs):
2894
2895
clean_date_files (files , - 1 )
2895
2896
create_tadays_date_file (a_path )
2896
2897
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 ))
2898
2899
break
2899
2900
else :
2900
2901
# PROGRAM DEBUG: set program's version
@@ -2962,7 +2963,7 @@ def to_time(secs):
2962
2963
connection_fail_count += 1
2963
2964
if connection_fail_count > 4 :
2964
2965
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 ...' )
2966
2967
break
2967
2968
delay (60 , stop )
2968
2969
@@ -3222,6 +3223,12 @@ def _fix_playlist_highlight_after_rename(self, old_file, new_file, copy_file, op
3222
3223
return ret
3223
3224
3224
3225
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
+
3225
3232
if char in (ord ('#' ), curses .KEY_RESIZE ):
3226
3233
self ._normal_mode_resize ()
3227
3234
self ._do_display_notify ()
@@ -4019,7 +4026,7 @@ def keypress(self, char):
4019
4026
char not in self ._chars_to_bypass and \
4020
4027
char not in self ._chars_to_bypass_for_search and \
4021
4028
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 ' )
4023
4030
theme_id , save_theme = self ._theme_selector .keypress (char )
4024
4031
4025
4032
#if self._cnf.theme_not_supported:
@@ -5426,7 +5433,7 @@ def _show_http_connection(self):
5426
5433
"""''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
5427
5434
Windows only section
5428
5435
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''"""
5429
- def _register_windows_handlers (self ):
5436
+ def _register_signals_handlers (self ):
5430
5437
if platform .startswith ('win' ):
5431
5438
""" disable close button """
5432
5439
import win32console , win32gui , win32con , win32api
@@ -5436,8 +5443,12 @@ def _register_windows_handlers(self):
5436
5443
if hMenu :
5437
5444
try :
5438
5445
win32gui .DeleteMenu (hMenu , win32con .SC_CLOSE , win32con .MF_BYCOMMAND )
5446
+ if logger .isEnabledFor (logging .DEBUG ):
5447
+ logger .debug ('SetConsoleCtrlHandler: close button disabled' )
5439
5448
except :
5440
- pass
5449
+ if logger .isEnabledFor (logging .DEBUG ):
5450
+ logger .debug ('SetConsoleCtrlHandler: failed to disable close button' )
5451
+
5441
5452
""" install handlers for exit / close signals"""
5442
5453
try :
5443
5454
result = win32api .SetConsoleCtrlHandler (self ._windows_signal_handler , True )
@@ -5451,37 +5462,91 @@ def _register_windows_handlers(self):
5451
5462
logger .debug ('SetConsoleCtrlHandler: Failed to register (with Exception)!!!' )
5452
5463
# Trying to catch Windows log-ogg, reboot, halt
5453
5464
# 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
5466
5522
5467
5523
def _windows_signal_handler (self , event ):
5468
5524
""" windows signal handler
5469
5525
https://danielkaes.wordpress.com/2009/06/04/how-to-catch-kill-events-with-python/
5470
5526
"""
5471
- import win32con , win32api , signal
5527
+ import win32con , win32api
5472
5528
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...' )
5479
5540
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 ()
5483
5548
try :
5484
- result = win32api .SetConsoleCtrlHandler (self ._windows_signal_handler , False )
5549
+ win32api .SetConsoleCtrlHandler (self ._windows_signal_handler , False )
5485
5550
except :
5486
5551
pass
5487
5552
return False
0 commit comments