Skip to content

Commit

Permalink
MainWindow: Mark inconsistent and non-deterministic aspects of closin…
Browse files Browse the repository at this point in the history
…g process
  • Loading branch information
davidfstr committed Sep 27, 2023
1 parent 055fd0a commit d7250d8
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 9 deletions.
9 changes: 8 additions & 1 deletion src/crystal/browser/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,9 +376,16 @@ def __exit__(self, exc_type, exc_value, exc_traceback) -> None:
# === File Menu: Events ===

def _on_close_project(self, event: wx.CommandEvent) -> None:
# TODO: Move these dispose operations inside _on_close_frame().
# But be careful! The last time this movement was attempted,
# various shutdown-related race conditions were triggered.
#
# Wait to perform movement until enough time to formalize
# a deterministic shutdown procedure.
self.entity_tree.dispose()
self.task_tree.dispose()
self._frame.Close()

self._frame.Close() # will trigger call to _on_close_frame()

def _on_quit(self, event: wx.CommandEvent) -> None:
if event.Id == wx.ID_EXIT:
Expand Down
6 changes: 5 additions & 1 deletion src/crystal/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -697,7 +697,11 @@ def _resource_group_did_instantiate(self, group: ResourceGroup) -> None:
# === Close ===

def close(self) -> None:
self.root_task.close()
# Stop scheduler thread soon
self.root_task.interrupt()
# (TODO: Actually wait for the scheduler thread to exit
# in a deterministic fashion, rather than relying on
# garbage collection to clean up objects.)

# Disable Write Ahead Log (WAL) mode when closing database
# in case the user decides to burn the project to read-only media,
Expand Down
9 changes: 5 additions & 4 deletions src/crystal/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -1299,8 +1299,6 @@ class RootTask(Task):
Access to this task's children list must be synchronized with the
foreground thread.
This task never completes.
"""
icon_name = None
scheduling_style = SCHEDULING_STYLE_ROUND_ROBIN
Expand Down Expand Up @@ -1365,8 +1363,11 @@ def fg_task() -> None:
# NOTE: Must synchronize access to RootTask.children with foreground thread
fg_call_and_wait(fg_task)

def close(self) -> None:
"""Stop all descendent tasks, asynchronously."""
def interrupt(self) -> None:
"""
Stop all descendent tasks, asynchronously,
by interrupting the scheduler thread.
"""
self.finish()

def __repr__(self) -> str:
Expand Down
4 changes: 1 addition & 3 deletions src/crystal/util/xthreading.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,9 +232,7 @@ def bg_call_later(callable: Callable[..., None], daemon: bool=False, *args) -> N
if True, forces the background thread to be a daemon,
and not prevent program termination while it is running.
"""
thread = threading.Thread(target=callable, args=args)
if daemon:
thread.daemon = True
thread = threading.Thread(target=callable, args=args, daemon=daemon)
thread.start()


Expand Down

0 comments on commit d7250d8

Please sign in to comment.