r15175 - gnucash/branches/2.0 - Fix bug #353450 - Crash on quit during save.

Derek Atkins warlord at cvs.gnucash.org
Sat Dec 2 21:03:11 EST 2006


Author: warlord
Date: 2006-12-02 21:03:10 -0500 (Sat, 02 Dec 2006)
New Revision: 15175
Trac: http://svn.gnucash.org/trac/changeset/15175

Modified:
   gnucash/branches/2.0/
   gnucash/branches/2.0/ChangeLog
   gnucash/branches/2.0/lib/libqof/qof/qofsession-p.h
   gnucash/branches/2.0/lib/libqof/qof/qofsession.c
   gnucash/branches/2.0/lib/libqof/qof/qofsession.h
   gnucash/branches/2.0/src/gnome-utils/gnc-file.c
Log:
	Fix bug #353450 - Crash on quit during save.

	Add a lock to the QofSession object, and use it in
	qof_session_save() to protect against re-entrance.

	The lock always starts at 1 and is 0 while inside
	qof_session_save().  If another call is made to qof_session_save()
	while one is in progress, the lock will momentarily drop below 0
	before returning to zero.

	Note: The per-session nature of the lock would make it appear that
	we support concurrent saving of different sessions.  In fact, we
	do not, because the file backend blocks the main process until the
	forked gzip process is finished, and it only knows how to keep
	track of one child pid at a time.

Merge from r15168



Property changes on: gnucash/branches/2.0
___________________________________________________________________
Name: svk:merge
   - 3889ce50-311e-0410-a464-f059747ec5d1:/local/gnucash/branches/2.0:697
d2ab10a8-8a95-4986-baff-8d511d9f15b2:/local/gnucash/branches/2.0:13659
d2ab10a8-8a95-4986-baff-8d511d9f15b2:/local/gnucash/trunk:13282
   + 3889ce50-311e-0410-a464-f059747ec5d1:/local/gnucash/branches/2.0:697
d2ab10a8-8a95-4986-baff-8d511d9f15b2:/local/gnucash/branches/2.0:13663
d2ab10a8-8a95-4986-baff-8d511d9f15b2:/local/gnucash/trunk:13282

Modified: gnucash/branches/2.0/ChangeLog
===================================================================
--- gnucash/branches/2.0/ChangeLog	2006-12-03 02:02:43 UTC (rev 15174)
+++ gnucash/branches/2.0/ChangeLog	2006-12-03 02:03:10 UTC (rev 15175)
@@ -1,3 +1,21 @@
+2006-12-02  Chris Shoemaker <chris.shoemaker at cox.net>
+
+	Fix bug #353450 - Crash on quit during save.
+
+	Add a lock to the QofSession object, and use it in
+	qof_session_save() to protect against re-entrance.
+
+	The lock always starts at 1 and is 0 while inside
+	qof_session_save().  If another call is made to qof_session_save()
+	while one is in progress, the lock will momentarily drop below 0
+	before returning to zero.
+
+	Note: The per-session nature of the lock would make it appear that
+	we support concurrent saving of different sessions.  In fact, we
+	do not, because the file backend blocks the main process until the
+	forked gzip process is finished, and it only knows how to keep
+	track of one child pid at a time.
+
 2006-12-01  Andreas Köhler  <andi5.py at gmx.net>
 
 	Save window size and position of the transfer dialog.

Modified: gnucash/branches/2.0/lib/libqof/qof/qofsession-p.h
===================================================================
--- gnucash/branches/2.0/lib/libqof/qof/qofsession-p.h	2006-12-03 02:02:43 UTC (rev 15174)
+++ gnucash/branches/2.0/lib/libqof/qof/qofsession-p.h	2006-12-03 02:03:10 UTC (rev 15175)
@@ -63,6 +63,7 @@
   /* Pointer to the backend that is actually used to move data
    * between the persistant store and the local engine.  */
   QofBackend *backend;
+  gint lock;
 };
 
 

Modified: gnucash/branches/2.0/lib/libqof/qof/qofsession.c
===================================================================
--- gnucash/branches/2.0/lib/libqof/qof/qofsession.c	2006-12-03 02:02:43 UTC (rev 15174)
+++ gnucash/branches/2.0/lib/libqof/qof/qofsession.c	2006-12-03 02:03:10 UTC (rev 15175)
@@ -196,6 +196,7 @@
   session->books = g_list_append (NULL, qof_book_new ());
   session->book_id = NULL;
   session->backend = NULL;
+  session->lock = 1;
 
   qof_session_clear_error (session);
 }
@@ -1180,8 +1181,10 @@
 	int err;
 	gint num;
 	char *msg, *book_id;
-	
+
 	if (!session) return;
+	if (!g_atomic_int_dec_and_test(&session->lock))
+	    goto leave;
 	ENTER ("sess=%p book_id=%s", 
 		 session, session->book_id ? session->book_id : "(null)");
 	/* Partial book handling. */
@@ -1247,7 +1250,7 @@
 						session->book_id = NULL;
 						qof_session_push_error (session, err, msg);
 						LEAVE("changed backend error %d", err);
-						return;
+						goto leave;
 					}
 					if (msg != NULL) 
 					{
@@ -1267,11 +1270,11 @@
 				p = p->next;
 			}
 		}
-		if(!session->backend) 
+		if(!session->backend)
 		{
 			msg = g_strdup_printf("failed to load backend");
 			qof_session_push_error(session, ERR_BACKEND_NO_HANDLER, msg);
-			return;
+			goto leave;
 		}
 	}
 	/* If there is a backend, and the backend is reachable
@@ -1295,7 +1298,8 @@
 			if (be->sync)
 			{
 				(be->sync)(be, abook);
-				if (save_error_handler(be, session)) return;
+				if (save_error_handler(be, session)) 
+                                    goto leave;
 			}
 		}
 		/* If we got to here, then the backend saved everything 
@@ -1303,7 +1307,7 @@
 		/* Return the book_id to previous value. */
 		qof_session_clear_error (session);
 		LEAVE("Success");
-		return;
+		goto leave;
 	}
 	else
 	{
@@ -1311,9 +1315,17 @@
 		qof_session_push_error(session, ERR_BACKEND_NO_HANDLER, msg);
 	}
 	LEAVE("error -- No backend!");
+ leave:
+	g_atomic_int_inc(&session->lock);
+	return;
 }
 
 /* ====================================================================== */
+gboolean
+qof_session_save_in_progress(QofSession *session)
+{
+    return (session && g_atomic_int_get(&session->lock) != 1);
+}
 
 void
 qof_session_end (QofSession *session)

Modified: gnucash/branches/2.0/lib/libqof/qof/qofsession.h
===================================================================
--- gnucash/branches/2.0/lib/libqof/qof/qofsession.h	2006-12-03 02:02:43 UTC (rev 15174)
+++ gnucash/branches/2.0/lib/libqof/qof/qofsession.h	2006-12-03 02:03:10 UTC (rev 15175)
@@ -222,6 +222,7 @@
  *    if any data in the session hasn't been saved to long-term storage.
  */
 gboolean qof_session_not_saved(QofSession *session);
+gboolean qof_session_save_in_progress(QofSession *session);
 
 /** Allows the backend to warn the user if a dataset already exists. */
 gboolean qof_session_save_may_clobber_data (QofSession *session);

Modified: gnucash/branches/2.0/src/gnome-utils/gnc-file.c
===================================================================
--- gnucash/branches/2.0/src/gnome-utils/gnc-file.c	2006-12-03 02:02:43 UTC (rev 15174)
+++ gnucash/branches/2.0/src/gnome-utils/gnc-file.c	2006-12-03 02:03:10 UTC (rev 15175)
@@ -1169,5 +1169,6 @@
 gboolean
 gnc_file_save_in_progress (void)
 {
-  return (save_in_progress > 0);
+    QofSession *session = gnc_get_current_session();
+    return (qof_session_save_in_progress(session) || save_in_progress > 0);
 }



More information about the gnucash-changes mailing list