About #123691 - Permission Change Crash



Hey,

there's a problem with the property dialog: It doesn't unregister/cancel
it's callbacks/operations. This leads to a crash when you close the
dialog before all operations are finished. If you e.g. select multiple
files, change the permissions and then quickly press alt-c or 'close',
you'll most likely crash in fm_properties_window_get_type() (expanded
from the FM_PROPERTIES_WINDOW cast macro in the callbacks).
I think this is also a problem for the rename and group/owner callbacks,
but much harder to trigger, because these changes aren't available for
multi-file property windows (if the fs is really slow though..).

Here are two patches for your consideration, but both suck a bit:
They both cancel pending permission changes when the window is
destroyed, which is probably not what you'd expect when you press a
button named 'close'. They also don't take into account that there may
be other callbacks besides change_permission() which need to be
cancelled (but the larger patch is intended to be expanded to do this -
though a Hashtable  probably won't do the trick, because there might be
multiple pending operations for one file). The more hackish (though less
intrusive) patch doesn't even try to find out which files may have
pending perm. ops, but cancels them for all.

I'd be thankful for any suggestions.

Martin

Index: src/file-manager/fm-properties-window.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/file-manager/fm-properties-window.c,v
retrieving revision 1.197
diff -u -p -r1.197 fm-properties-window.c
--- src/file-manager/fm-properties-window.c	27 Feb 2004 21:42:36 -0000	1.197
+++ src/file-manager/fm-properties-window.c	11 Mar 2004 00:28:53 -0000
@@ -3554,6 +3554,14 @@ real_destroy (GtkObject *object)
 	for (l = window->details->target_files; l != NULL; l = l->next) {
 		nautilus_file_monitor_remove (NAUTILUS_FILE (l->data), &window->details->target_files);
 	}
+
+	/* Cancel unfinished permission changes. This is a HACK. */
+	if (window->details->long_operation_underway != 0) {
+		for (l = window->details->target_files; l != NULL; l = l->next) {
+			nautilus_file_cancel (NAUTILUS_FILE (l->data), permission_change_callback, window);
+		}
+	}
+
 	nautilus_file_list_free (window->details->target_files);
 	window->details->target_files = NULL;
 
Index: src/file-manager/fm-properties-window.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/file-manager/fm-properties-window.c,v
retrieving revision 1.197
diff -u -p -r1.197 fm-properties-window.c
--- src/file-manager/fm-properties-window.c	27 Feb 2004 21:42:36 -0000	1.197
+++ src/file-manager/fm-properties-window.c	11 Mar 2004 00:18:31 -0000
@@ -128,6 +128,7 @@ struct FMPropertiesWindowDetails {	
 	GnomeVFSFileSize total_size;
 
 	guint long_operation_underway;
+	GHashTable *pending_operations;
 };
 
 enum {
@@ -2462,6 +2463,8 @@ permission_change_callback (NautilusFile
 		gdk_window_set_cursor (GTK_WIDGET (window)->window, NULL);
 	}
 	window->details->long_operation_underway--;
+
+	g_hash_table_remove (window->details->pending_operations, file);
 	
 	/* Report the error if it's an error. */
 	fm_report_error_setting_permissions (file, result, NULL);
@@ -2564,6 +2567,9 @@ permission_button_toggled (GtkToggleButt
 				(file, permissions,
 				 permission_change_callback,
 				 window);
+			
+			g_hash_table_insert (window->details->pending_operations,
+								 file, permission_change_callback);
 		}
 		
 	}
@@ -2583,6 +2589,9 @@ permission_button_toggled (GtkToggleButt
 				(file, permissions,
 				 permission_change_callback,
 				 window);
+			
+			g_hash_table_insert (window->details->pending_operations,
+								 file, permission_change_callback);
 		}
 	}	
 
@@ -3398,6 +3407,17 @@ cancel_call_when_ready_callback (gpointe
 }
 
 static void
+cancel_pending_operations (gpointer key,
+				 gpointer value,
+				 gpointer user_data)
+{
+	nautilus_file_cancel 
+		(NAUTILUS_FILE (key), 
+		 value, 
+		 user_data);
+}
+
+static void
 remove_pending (StartupData *startup_data,
 		gboolean cancel_call_when_ready,
 		gboolean cancel_timed_wait,
@@ -3554,6 +3574,16 @@ real_destroy (GtkObject *object)
 	for (l = window->details->target_files; l != NULL; l = l->next) {
 		nautilus_file_monitor_remove (NAUTILUS_FILE (l->data), &window->details->target_files);
 	}
+	
+    g_hash_table_foreach (window->details->pending_operations,
+						  cancel_pending_operations,
+						  window);
+	
+	if (window->details->pending_operations) {
+		g_hash_table_destroy (window->details->pending_operations);
+		window->details->pending_operations = NULL;
+	}
+
 	nautilus_file_list_free (window->details->target_files);
 	window->details->target_files = NULL;
 
@@ -3681,5 +3711,7 @@ fm_properties_window_instance_init (FMPr
 {
 	window->details = g_new0 (FMPropertiesWindowDetails, 1);
 
+	window->details->pending_operations = g_hash_table_new (NULL, NULL);
+
 	eel_gtk_window_set_up_close_accelerator (GTK_WINDOW (window));
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]