From f212e2cbea8c492f43f998df6b8da08d28ccd4d7 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sun, 26 Nov 2017 15:35:25 +0000 Subject: [PATCH] Change order of cleanup in delete_inst. If you close a session window with an associated SSH back end, the back end may call back to notify_remote_exit() from ssh_free(), which queues a new top-level callback citing the inst structure we were about to delete. We could fix this by introducing a special 'moribund' flag which inhibits notify_remote_exit from queueing a callback, but far easier is to move the delete_callbacks_for_context() call to _after_ all subsidiary things have been cleaned up, so that any last-minute callbacks they might schedule will be promptly unscheduled again before they do any damage. --- unix/gtkwin.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/unix/gtkwin.c b/unix/gtkwin.c index 00e07485..81182362 100644 --- a/unix/gtkwin.c +++ b/unix/gtkwin.c @@ -2039,7 +2039,6 @@ void notify_remote_exit(void *frontend) static void delete_inst(struct gui_data *inst) { - delete_callbacks_for_context(inst); if (inst->reconfigure_dialog) { gtk_widget_destroy(inst->reconfigure_dialog); inst->reconfigure_dialog = NULL; @@ -2077,6 +2076,17 @@ static void delete_inst(struct gui_data *inst) log_free(inst->logctx); inst->logctx = NULL; } + + /* + * Delete any top-level callbacks associated with inst, which + * would otherwise become stale-pointer dereferences waiting to + * happen. We do this last, because some of the above cleanups + * (notably shutting down the backend) might themelves queue such + * callbacks, so we need to make sure they don't do that _after_ + * we're supposed to have cleaned everything up. + */ + delete_callbacks_for_context(inst); + sfree(inst); }