psppire-data-window: Delete dataset when closing window.
authorBen Pfaff <blp@cs.stanford.edu>
Sun, 8 Jul 2012 06:44:37 +0000 (23:44 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Mon, 9 Jul 2012 06:12:07 +0000 (23:12 -0700)
When the user closes the window it means that he wants to close the
underlying dataset also.  Otherwise the dataset essentially leaks
(in theory it's still there in the list of datasets but in practice
that takes a DATASET ACTIVATE <name> WINDOW=FRONT command to show
it).

This also fixes a Gtk-CRITICAL and following crash in the following
scenario brought up by John Darrington:
1. Start psppire
2. File | Open and load x.sav (dataset1)
3. File | New | Data (a new data window will appear: dataset2)
4. Using the window manager close the window for dataset1
5. In dataset2:  File | Open and load x.sav

I'm not 100% certain of the reason that this fixes it but I think
that there's some lingering association between the dataset and the
window that this change eliminates, by eliminating the dataset along
with the window.

The code added to psppire_data_window_dispose() in this commit
should probably go in a "finalize" function instead but there seems
to be a separate problem with references to PsppireVarSheet such
that if this new code is in "finalize" then dataset_destroy() will
call dict_clear() which will invoke the callbacks for PsppireDict
which will try to access the destroyed window.  On the other hand,
with this code in "dispose" the window isn't fully destroyed yet so
while the same code path gets followed it isn't fatal.

src/ui/gui/psppire-data-window.c

index c22f7bb293acb05ec957931a8f2a693db728b86e..2149a89dbd9213da3b0bff069ed726c5a130a92e 100644 (file)
@@ -1212,6 +1212,18 @@ psppire_data_window_dispose (GObject *object)
 {
   PsppireDataWindow *dw = PSPPIRE_DATA_WINDOW (object);
 
+  if (dw->dataset)
+    {
+      struct dataset *dataset = dw->dataset;
+      struct session *session = dataset_session (dataset);
+
+      dw->dataset = NULL;
+
+      dataset_set_callbacks (dataset, NULL, NULL);
+      session_set_active_dataset (session, NULL);
+      dataset_destroy (dataset);
+    }
+
   if (dw->builder != NULL)
     {
       g_object_unref (dw->builder);