Opened 8 years ago

Closed 8 years ago

#650 closed enhancement (fixed)

Add shutdown to session.triggers

Reported by: Tristan Croll Owned by: Tom Goddard
Priority: major Milestone:
Component: Sessions Version:
Keywords: Cc: Tristan Croll
Blocked By: Blocking:
Notify when closed: Platform: all
Project: ChimeraX

Description

At the moment I can't find any way for a Python process to know when the ChimeraX session is shutting down, and clean itself up gracefully. This is mildly problematic for my haptic interface code, which has a C++ thread running to handle the device(s) and has some functions that should be run to close this and shut down the device gracefully. I've tried setting it up in a fashion that should theoretically do automatic cleanup:

class HapticHandler(QObject):
    def __init__(self, session):
        do stuff

    def __enter__(self):
        return self

    def __exit__(self, type, value, traceback):
        self.stopHaptics()


with HapticHandler.HapticHandler(session) as h:
    session.HapticHandler = h

... but I still need a way to trigger it by deleting the object on quit. At present, closing ChimeraX while the haptic interface is running leads to an inconsequential-but-ugly segmentation fault, and the LEDs on the haptic device remaining on. I'm sure there will be other situations where people will want to run functions on shutdown as well (e.g. automatic saving of the current state of their plugin).

Change History (4)

comment:1 by Tristan Croll, 8 years ago

Ok, I found I can make this work using the PyQt signal/slot framework:

self.session.ui.lastWindowClosed.connect(self._on_shutdown)

... but there is some care needed. At the time this is run, the session triggers are still active - so if my _on_shutdown() function deletes the Model holding the haptic device pointer, this activates the 'remove models' trigger, which leads to ISOLDE attempting to do things with no-longer-existing widgets, which leads to ChimeraX dumping a stack trace on exit. What seems a bit odd is that I have a cleanup in place (removing all ISOLDE trigger handlers) to run when the ISOLDE window closes:

self.gui.tool_window.ui_area.destroyed.connect(self._on_close)

... which one would logically think gets run before the lastWindowClosed signal fires.

comment:2 by Tristan Croll, 8 years ago

Cc: Tristan Croll added
Component: UnassignedSessions

comment:3 by Tom Goddard, 8 years ago

Type: defectenhancement

comment:4 by Tom Goddard, 8 years ago

Resolution: fixed
Status: assignedclosed

I added an "app quit" trigger invoked before quit closes all windows. Trigger data is None. Register a quit handler as follows.

def f(trigger_name, trigger_data):

# Do something before quit.

session.triggers.add_handler('app quit', f)

Note: See TracTickets for help on using tickets.