Hi,

I like time zone differences, I go to bed with a problem and wake up to a
nice patch (or two) to read over breakfast :-) so here's one for you.

The only real solution to potential corruption is to make the writes to
shared config files atomic.  The patch uses the good old fashioned exclusive
lock file method. IIUC this should also work on windows, but may need
registry settings to be correct, I'm not sure.  Nothing else I researched
seemed to be portable.

In race conditions this patch doesn't say which write will win, but it is
intended to guarantee that whichever does will be written atomically and not
corrupted.

In general there is no way Geany can know which write should win, the user
has to do that themselves by closing instances manually in the right order
so the last wins.

The patch has both yours and mine in the one.

Your patches stop new_instances upsetting geany.conf and mine handles shared
project files and geany.conf in the case of multiple main instances.

Lets see if anyone else can get it to fail.

Cheers
Lex

On 21 May 2010 23:52, Dimitar Zhekov <hams...@mbox.contact.bg> wrote:

> There is one more case when geany.conf may be modified by a secondary
> instance: saving the project-less file list on Project -> New / Open.
> Patch attached.
>
> --
> E-gards: Jimmy
>
> _______________________________________________
> Geany-devel mailing list
> Geany-devel@uvena.de
> http://lists.uvena.de/cgi-bin/mailman/listinfo/geany-devel
>
>
Index: callbacks.c
===================================================================
--- callbacks.c	(revision 4917)
+++ callbacks.c	(working copy)
@@ -117,7 +117,8 @@
 /* should only be called from on_exit_clicked */
 static void quit_app(void)
 {
-	configuration_save();
+	if (!cl_options.new_instance)
+		configuration_save();
 
 	if (app->project != NULL)
 		project_close(FALSE);	/* save project session files */
Index: keyfile.c
===================================================================
--- keyfile.c	(revision 4917)
+++ keyfile.c	(working copy)
@@ -330,8 +330,14 @@
 }
 
 
-static void save_dialog_prefs(GKeyFile *config)
+void configuration_save_dialog_prefs(void)
 {
+	gchar *data;
+	GKeyFile *config = g_key_file_new();
+	gchar *configfile = g_strconcat(app->configdir, G_DIR_SEPARATOR_S, "geany.conf", NULL);
+	
+	g_key_file_load_from_file(config, configfile, G_KEY_FILE_NONE, NULL);
+	
 	/* new settings should be added in init_pref_groups() */
 	settings_action(config, SETTING_WRITE);
 
@@ -475,6 +481,17 @@
 		g_key_file_set_string(config, "VTE", "last_dir", vte_info.dir);
 	}
 #endif
+	/* write the file */
+	data = g_key_file_to_data(config, NULL, NULL);
+	if (utils_lock(configfile) >= 0)
+	{
+		utils_write_file(configfile, data);
+		utils_unlock(configfile);
+	}
+	g_free(data);
+	
+	g_key_file_free(config);
+	g_free(configfile);
 }
 
 
@@ -540,7 +557,6 @@
 	/* this signal can be used e.g. to prepare any settings before Stash code reads them below */
 	g_signal_emit_by_name(geany_object, "save-settings", config);
 
-	save_dialog_prefs(config);
 	save_ui_prefs(config);
 	project_save_prefs(config);	/* save project filename, etc. */
 	save_recent_files(config, ui_prefs.recent_queue, "recent_files");
@@ -551,7 +567,11 @@
 
 	/* write the file */
 	data = g_key_file_to_data(config, NULL, NULL);
-	utils_write_file(configfile, data);
+	if (utils_lock(configfile) >= 0)
+	{
+		utils_write_file(configfile, data);
+		utils_unlock(configfile);
+	}
 	g_free(data);
 
 	g_key_file_free(config);
@@ -899,7 +919,11 @@
 
 	/* write the file */
 	data = g_key_file_to_data(config, NULL, NULL);
-	utils_write_file(configfile, data);
+	if (utils_lock(configfile) >= 0)
+	{
+		utils_write_file(configfile, data);
+		utils_unlock(configfile);
+	}
 	g_free(data);
 
 	g_key_file_free(config);
Index: keyfile.h
===================================================================
--- keyfile.h	(revision 4917)
+++ keyfile.h	(working copy)
@@ -37,6 +37,8 @@
 
 void configuration_add_pref_group(struct StashGroup *group, gboolean for_prefs_dialog);
 
+void configuration_save_dialog_prefs(void);
+
 void configuration_save(void);
 
 gboolean configuration_load(void);
Index: prefs.c
===================================================================
--- prefs.c	(revision 4917)
+++ prefs.c	(working copy)
@@ -1164,7 +1164,7 @@
 		ui_update_view_editor_menu_items();
 
 		/* store all settings */
-		configuration_save();
+		configuration_save_dialog_prefs();
 	}
 
 	if (response != GTK_RESPONSE_APPLY)
Index: project.c
===================================================================
--- project.c	(revision 4917)
+++ project.c	(working copy)
@@ -999,7 +999,8 @@
 	if (project_prefs.project_session)
 	{
 		/* save current (non-project) session (it could has been changed since program startup) */
-		configuration_save_default_session();
+		if (!cl_options.new_instance)
+			configuration_save_default_session();
 		/* now close all open files */
 		document_close_all();
 		/* read session files so they can be opened with configuration_open_files() */
@@ -1068,7 +1069,11 @@
 	}
 	/* write the file */
 	data = g_key_file_to_data(config, NULL, NULL);
-	ret = (utils_write_file(filename, data) == 0);
+	if (utils_lock(filename) >= 0)
+	{
+		ret = (utils_write_file(filename, data) == 0);
+		utils_unlock(filename);
+	}
 
 	g_free(data);
 	g_free(filename);
Index: utils.c
===================================================================
--- utils.c	(revision 4917)
+++ utils.c	(working copy)
@@ -35,6 +35,9 @@
 #include <errno.h>
 #include <stdarg.h>
 
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
 #ifdef HAVE_SYS_STAT_H
 # include <sys/stat.h>
 #endif
@@ -2007,3 +2010,21 @@
 }
 
 
+/* NB int not gint see g_open */
+int utils_lock(const gchar *file)
+{
+	gchar *lock = g_strconcat(file, "_lock", NULL);
+	int ret = g_open(lock, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+	if (ret >= 0) close(ret);
+	g_free(lock);
+	return ret;
+};
+
+
+void utils_unlock(const gchar *file)
+{
+	gchar *lock = g_strconcat(file, "_lock", NULL);
+	g_unlink(lock);
+	g_free(lock);
+};
+
Index: utils.h
===================================================================
--- utils.h	(revision 4917)
+++ utils.h	(working copy)
@@ -108,6 +108,11 @@
 	for (char_ptr = string; *char_ptr; char_ptr++)
 
 
+/* NB int not gint see g_open */
+int utils_lock(const gchar *file);
+
+void utils_unlock(const gchar *file);
+
 void utils_open_browser(const gchar *uri);
 
 gint utils_get_line_endings(const gchar* buffer, glong size);
_______________________________________________
Geany-devel mailing list
Geany-devel@uvena.de
http://lists.uvena.de/cgi-bin/mailman/listinfo/geany-devel

Reply via email to