1
0
mirror of https://github.com/EDCD/EDMarketConnector.git synced 2025-04-17 01:22:19 +03:00

Merge pull request #840 from EDCD/fix/678-check-for-shutdown-when-tk-event-generate

Avoid Tk event_generate() calls during shutdown.
This commit is contained in:
Athanasius 2021-01-11 17:23:15 +00:00 committed by GitHub
commit 6831c45c59
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 72 additions and 13 deletions

View File

@ -1059,6 +1059,8 @@ class AppWindow(object):
self.status['text'] = str(e)
def onexit(self, event=None):
config.set_shutdown() # Signal we're in shutdown now.
# http://core.tcl.tk/tk/tktview/c84f660833546b1b84e7
if platform != 'darwin' or self.w.winfo_rooty() > 0:
x, y = self.w.geometry().split('+')[1:3] # e.g. '212x170+2881+1267'

View File

@ -117,6 +117,8 @@ class Config(object):
if platform=='darwin':
def __init__(self):
self.__in_shutdown = False # Is the application currently shutting down ?
self.app_dir = join(NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, True)[0], appname)
if not isdir(self.app_dir):
mkdir(self.app_dir)
@ -177,9 +179,17 @@ class Config(object):
self.save()
self.defaults = None
def set_shutdown(self):
self.__in_shutdown = True
@property
def shutting_down(self) -> bool:
return self.__in_shutdown
elif platform=='win32':
def __init__(self):
self.__in_shutdown = False # Is the application currently shutting down ?
self.app_dir = join(KnownFolderPath(FOLDERID_LocalAppData), appname)
if not isdir(self.app_dir):
@ -268,11 +278,19 @@ class Config(object):
RegCloseKey(self.hkey)
self.hkey = None
def set_shutdown(self):
self.__in_shutdown = True
@property
def shutting_down(self) -> bool:
return self.__in_shutdown
elif platform=='linux':
SECTION = 'config'
def __init__(self):
self.__in_shutdown = False # Is the application currently shutting down ?
# http://standards.freedesktop.org/basedir-spec/latest/ar01s03.html
self.app_dir = join(getenv('XDG_DATA_HOME', expanduser('~/.local/share')), appname)
@ -346,6 +364,13 @@ class Config(object):
self.save()
self.config = None
def set_shutdown(self):
self.__in_shutdown = True
@property
def shutting_down(self) -> bool:
return self.__in_shutdown
def _escape(self, val):
return str(val).replace(u'\\', u'\\\\').replace(u'\n', u'\\n').replace(u';', u'\\;')

View File

@ -115,6 +115,9 @@ class Dashboard(FileSystemEventHandler):
# Can be called either in watchdog thread or, if polling, in main thread.
def process(self, logfile=None):
if config.shutting_down:
return
try:
with open(join(self.currentdir, 'Status.json'), 'rb') as h:
data = h.read().strip()
@ -126,6 +129,7 @@ class Dashboard(FileSystemEventHandler):
self.status != entry):
self.status = entry
self.root.event_generate('<<DashboardEvent>>', when="tail")
except Exception:
logger.exception('Reading Status.json')

View File

@ -92,11 +92,15 @@ if platform == 'darwin':
self.observer = NSEvent.addGlobalMonitorForEventsMatchingMask_handler_(NSKeyDownMask, self._handler)
def _poll(self):
if config.shutting_down:
return
# No way of signalling to Tkinter from within the callback handler block that doesn't
# cause Python to crash, so poll.
if self.activated:
self.activated = False
self.root.event_generate('<<Invoke>>', when="tail")
if self.keycode or self.modifiers:
self.root.after(HotkeyMgr.POLL, self._poll)
@ -123,6 +127,9 @@ if platform == 'darwin':
self.acquire_state = HotkeyMgr.ACQUIRE_INACTIVE
def _acquire_poll(self):
if config.shutting_down:
return
# No way of signalling to Tkinter from within the monkey-patched event handler that doesn't
# cause Python to crash, so poll.
if self.acquire_state:
@ -316,7 +323,8 @@ elif platform == 'win32':
while GetMessage(ctypes.byref(msg), None, 0, 0) != 0:
if msg.message == WM_HOTKEY:
if config.getint('hotkey_always') or WindowTitle(GetForegroundWindow()).startswith('Elite - Dangerous'):
self.root.event_generate('<<Invoke>>', when="tail")
if not config.shutting_down:
self.root.event_generate('<<Invoke>>', when="tail")
else:
# Pass the key on
UnregisterHotKey(None, 1)

View File

@ -337,7 +337,8 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
self.event_queue.append(line)
if self.event_queue:
self.root.event_generate('<<JournalEvent>>', when="tail")
if not config.shutting_down:
self.root.event_generate('<<JournalEvent>>', when="tail")
log_pos = loghandle.tell()
@ -355,7 +356,9 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
'{{ "timestamp":"{}", "event":"ShutDown" }}'.format(strftime('%Y-%m-%dT%H:%M:%SZ', gmtime()))
)
self.root.event_generate('<<JournalEvent>>', when="tail")
if not config.shutting_down:
self.root.event_generate('<<JournalEvent>>', when="tail")
self.game_was_running = False
else:

View File

@ -366,9 +366,16 @@ def notify_newdata(data, is_beta):
def show_error(err):
"""
Display an error message in the status line of the main window.
Will be NOP during shutdown to avoid Tk hang.
:param err:
.. versionadded:: 2.3.7
"""
if config.shutting_down:
logger.info(f'Called during shutdown: "{str(err)}"')
return
if err and last_error['root']:
last_error['msg'] = str(err)
last_error['root'].event_generate('<<PluginError>>', when="tail")

View File

@ -598,8 +598,10 @@ def worker() -> None:
if not closing and e['event'] in ('StartUp', 'Location', 'FSDJump', 'CarrierJump'):
# Update main window's system status
this.lastlookup = r
# calls update_status in main thread
this.system_link.event_generate('<<EDSMStatus>>', when="tail")
if not config.shutting_down:
# calls update_status in main thread
this.system_link.event_generate('<<EDSMStatus>>', when="tail")
if r['msgnum'] // 100 != 1:
logger.warning(f'EDSM event with not-1xx status:\n{r["msgnum"]}\n{r["msg"]}\n'

View File

@ -1290,13 +1290,17 @@ def send_data(url: str, data: Mapping[str, Any]) -> bool:
'setCommanderTravelLocation'
):
this.lastlocation = reply_event.get('eventData', {})
# calls update_location in main thread
this.system_link.event_generate('<<InaraLocation>>', when="tail")
if not config.shutting_down:
# calls update_location in main thread
this.system_link.event_generate('<<InaraLocation>>', when="tail")
elif data_event['eventName'] in ['addCommanderShip', 'setCommanderShip']:
this.lastship = reply_event.get('eventData', {})
# calls update_ship in main thread
this.system_link.event_generate('<<InaraShip>>', when="tail")
if not config.shutting_down:
# calls update_ship in main thread
this.system_link.event_generate('<<InaraShip>>', when="tail")
return True # regardless of errors above, we DID manage to send it, therefore inform our caller as such

View File

@ -1157,4 +1157,5 @@ class PreferencesDialog(tk.Toplevel):
except Exception:
AXIsProcessTrustedWithOptions({kAXTrustedCheckOptionPrompt: True})
self.parent.event_generate('<<Quit>>', when="tail")
if not config.shutting_down:
self.parent.event_generate('<<Quit>>', when="tail")

View File

@ -32,7 +32,9 @@ class GenericProtocolHandler(object):
def event(self, url):
self.lastpayload = url
self.master.event_generate('<<CompanionAuthEvent>>', when="tail")
if not config.shutting_down:
self.master.event_generate('<<CompanionAuthEvent>>', when="tail")
if sys.platform == 'darwin' and getattr(sys, 'frozen', False):

View File

@ -40,7 +40,8 @@ class Updater(object):
Receive (Win)Sparkle shutdown request and send it to parent.
:rtype: None
"""
self.root.event_generate('<<Quit>>', when="tail")
if not config.shutting_down:
self.root.event_generate('<<Quit>>', when="tail")
def use_internal(self) -> bool:
"""
@ -208,4 +209,4 @@ class Updater(object):
:return: None
"""
pass
pass