[evolution-patches] Addressbook e-book thread-safety patch
- From: Hans Petter Jansson <hpj ximian com>
- To: evolution-patches ximian com
- Subject: [evolution-patches] Addressbook e-book thread-safety patch
- Date: Fri, 16 Jul 2004 23:07:03 +0200
I was able to consistently trigger the race conditions in e-book, and
have expanded on toshok's earlier fixes, eliminating a lot of races.
--
Hans Petter
? e-book.patch
? log.diff
? out.diff
? libebook/new
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution-data-server/addressbook/ChangeLog,v
retrieving revision 1.178
diff -u -p -r1.178 ChangeLog
--- ChangeLog 16 Jul 2004 08:08:53 -0000 1.178
+++ ChangeLog 16 Jul 2004 20:58:42 -0000
@@ -1,3 +1,40 @@
+2004-07-16 Hans Petter Jansson <hpj ximian com>
+
+ Really fixes #61052, #61466, #61160. Tested.
+
+ * libebook/e-book.c (e_book_op_remove): Don't lock the book's
+ mutex here, for symmetry with e_book_new_op ().
+ (do_add_contact): Lock book around op removal.
+ (do_commit_contact): Ditto.
+ (do_get_supported_fields): Ditto.
+ (do_get_supported_auth_methods): Ditto.
+ (do_authenticate_user): Ditto.
+ (do_get_contact): Ditto.
+ (do_get_contacts): Ditto.
+ (do_get_changes): Ditto.
+ (do_open): Ditto.
+ (do_remove): Ditto.
+ (emit_async_add_contact_response): Widen the scope of the
+ book's lock.
+ (emit_async_elist_response): Ditto.
+ (emit_async_get_contact_response): Ditto.
+ (emit_async_get_book_view_response): Ditto.
+ (emit_async_get_contacts_response): Ditto.
+ (emit_async_get_changes_response): Ditto.
+ (emit_async_generic_response): Ditto.
+ (emit_async_open_response): Ditto.
+ (e_book_response_add_contact): Lock book around op manipulation,
+ widen scope.
+ (e_book_response_get_supported_fields): Ditto.
+ (e_book_response_get_supported_auth_methods): Ditto.
+ (e_book_response_get_contact): Ditto.
+ (e_book_response_get_book_view): Ditto.
+ (e_book_response_get_contacts): Ditto.
+ (e_book_response_get_changes): Ditto.
+ (e_book_response_generic): Ditto.
+ (e_book_response_open): Ditto.
+ (e_book_response_remove): Ditto.
+
2004-07-16 Chris Toshok <toshok ximian com>
[ fixes #61052 ]
Index: libebook/e-book.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/addressbook/libebook/e-book.c,v
retrieving revision 1.38
diff -u -p -r1.38 e-book.c
--- libebook/e-book.c 16 Jul 2004 08:08:53 -0000 1.38
+++ libebook/e-book.c 16 Jul 2004 20:58:42 -0000
@@ -193,10 +193,8 @@ static void
e_book_op_remove (EBook *book,
EBookOp *op)
{
- g_mutex_lock (book->priv->mutex);
g_hash_table_remove (book->priv->id_to_op,
&op->opid);
- g_mutex_unlock (book->priv->mutex);
}
static void
@@ -273,7 +271,9 @@ do_add_contact (gboolean sync,
if (ev._major != CORBA_NO_EXCEPTION) {
+ g_mutex_lock (book->priv->mutex);
e_book_clear_op (book, our_op);
+ g_mutex_unlock (book->priv->mutex);
CORBA_exception_free (&ev);
@@ -300,7 +300,9 @@ do_add_contact (gboolean sync,
e_contact_set (contact, E_CONTACT_UID, our_op->id);
g_free (our_op->id);
+ g_mutex_lock (book->priv->mutex);
e_book_clear_op (book, our_op);
+ g_mutex_unlock (book->priv->mutex);
E_BOOK_CHECK_STATUS (status, error);
}
@@ -359,15 +361,16 @@ emit_async_add_contact_response (gpointe
if (op->cb.id)
op->cb.id (book, op->status, op->id, op->closure);
+ g_mutex_lock (book->priv->mutex);
+
g_free (op->id);
- g_mutex_lock (book->priv->mutex);
book->priv->pending_idles = g_list_remove (book->priv->pending_idles,
GINT_TO_POINTER (op->idle_id));
- g_mutex_unlock (book->priv->mutex);
e_book_clear_op (book, op);
+ g_mutex_unlock (book->priv->mutex);
g_object_unref (book);
return FALSE;
@@ -383,9 +386,12 @@ e_book_response_add_contact (EBook
d(printf ("e_book_response_add_contact\n"));
+ g_mutex_lock (book->priv->mutex);
+
op = e_book_get_op (book, opid);
if (op == NULL) {
+ g_mutex_unlock (book->priv->mutex);
g_warning ("e_book_response_add_contact: Cannot find operation ");
return;
}
@@ -405,11 +411,11 @@ e_book_response_add_contact (EBook
op->book = g_object_ref (book);
op->idle_id = g_idle_add (emit_async_add_contact_response, op);
- g_mutex_lock (book->priv->mutex);
book->priv->pending_idles = g_list_prepend (book->priv->pending_idles,
GINT_TO_POINTER (op->idle_id));
- g_mutex_unlock (book->priv->mutex);
}
+
+ g_mutex_unlock (book->priv->mutex);
}
@@ -471,7 +477,9 @@ do_commit_contact (gboolean sync,
if (ev._major != CORBA_NO_EXCEPTION) {
+ g_mutex_lock (book->priv->mutex);
e_book_clear_op (book, our_op);
+ g_mutex_unlock (book->priv->mutex);
CORBA_exception_free (&ev);
@@ -499,7 +507,9 @@ do_commit_contact (gboolean sync,
g_free (our_op->id);
/* remove the op from the book's hash of operations */
+ g_mutex_lock (book->priv->mutex);
e_book_clear_op (book, our_op);
+ g_mutex_unlock (book->priv->mutex);
E_BOOK_CHECK_STATUS (status, error);
}
@@ -579,6 +589,7 @@ do_get_supported_fields (gboolean
g_mutex_unlock (book->priv->mutex);
g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
_("book busy"));
+ return FALSE;
}
our_op = e_book_new_op (book, sync);
@@ -598,7 +609,9 @@ do_get_supported_fields (gboolean
if (ev._major != CORBA_NO_EXCEPTION) {
+ g_mutex_lock (book->priv->mutex);
e_book_clear_op (book, our_op);
+ g_mutex_unlock (book->priv->mutex);
CORBA_exception_free (&ev);
@@ -620,13 +633,15 @@ do_get_supported_fields (gboolean
if (sync) {
/* wait for something to happen (both cancellation and a
- successful response will notity us via our cv */
+ successful response will notify us via our cv */
g_cond_wait (our_op->cond, our_op->mutex);
status = our_op->status;
*fields = our_op->list;
+ g_mutex_lock (book->priv->mutex);
e_book_clear_op (book, our_op);
+ g_mutex_unlock (book->priv->mutex);
E_BOOK_CHECK_STATUS (status, error);
}
@@ -680,15 +695,16 @@ emit_async_elist_response (gpointer data
if (op->cb.elist)
op->cb.elist (book, op->status, op->elist, op->closure);
+ g_mutex_lock (book->priv->mutex);
+
g_object_unref (op->elist);
- g_mutex_lock (book->priv->mutex);
book->priv->pending_idles = g_list_remove (book->priv->pending_idles,
GINT_TO_POINTER (op->idle_id));
- g_mutex_unlock (book->priv->mutex);
e_book_clear_op (book, op);
+ g_mutex_unlock (book->priv->mutex);
g_object_unref (book);
return FALSE;
@@ -702,9 +718,12 @@ e_book_response_get_supported_fields (EB
{
EBookOp *op;
+ g_mutex_lock (book->priv->mutex);
+
op = e_book_get_op (book, opid);
if (op == NULL) {
+ g_mutex_unlock (book->priv->mutex);
g_warning ("e_book_response_get_supported_fields: Cannot find operation ");
return;
}
@@ -734,11 +753,11 @@ e_book_response_get_supported_fields (EB
op->elist = efields;
op->idle_id = g_idle_add (emit_async_elist_response, op);
- g_mutex_lock (book->priv->mutex);
book->priv->pending_idles = g_list_prepend (book->priv->pending_idles,
GINT_TO_POINTER (op->idle_id));
- g_mutex_unlock (book->priv->mutex);
}
+
+ g_mutex_unlock (book->priv->mutex);
}
@@ -796,7 +815,9 @@ do_get_supported_auth_methods (gboolean
if (ev._major != CORBA_NO_EXCEPTION) {
+ g_mutex_lock (book->priv->mutex);
e_book_clear_op (book, our_op);
+ g_mutex_unlock (book->priv->mutex);
CORBA_exception_free (&ev);
@@ -821,7 +842,9 @@ do_get_supported_auth_methods (gboolean
status = our_op->status;
*auth_methods = our_op->list;
+ g_mutex_lock (book->priv->mutex);
e_book_clear_op (book, our_op);
+ g_mutex_unlock (book->priv->mutex);
E_BOOK_CHECK_STATUS (status, error);
}
@@ -874,9 +897,12 @@ e_book_response_get_supported_auth_metho
{
EBookOp *op;
+ g_mutex_lock (book->priv->mutex);
+
op = e_book_get_op (book, opid);
if (op == NULL) {
+ g_mutex_unlock (book->priv->mutex);
g_warning ("e_book_response_get_supported_auth_methods: Cannot find operation ");
return;
}
@@ -904,11 +930,11 @@ e_book_response_get_supported_auth_metho
op->elist = emethods;
op->idle_id = g_idle_add (emit_async_elist_response, op);
- g_mutex_lock (book->priv->mutex);
book->priv->pending_idles = g_list_prepend (book->priv->pending_idles,
GINT_TO_POINTER (op->idle_id));
- g_mutex_unlock (book->priv->mutex);
}
+
+ g_mutex_unlock (book->priv->mutex);
}
@@ -971,7 +997,9 @@ do_authenticate_user (gboolean sy
if (ev._major != CORBA_NO_EXCEPTION) {
+ g_mutex_lock (book->priv->mutex);
e_book_clear_op (book, our_op);
+ g_mutex_unlock (book->priv->mutex);
CORBA_exception_free (&ev);
@@ -995,7 +1023,9 @@ do_authenticate_user (gboolean sy
status = our_op->status;
+ g_mutex_lock (book->priv->mutex);
e_book_clear_op (book, our_op);
+ g_mutex_unlock (book->priv->mutex);
E_BOOK_CHECK_STATUS (status, error);
}
@@ -1109,7 +1139,9 @@ do_get_contact (gboolean sync,
if (ev._major != CORBA_NO_EXCEPTION) {
+ g_mutex_lock (book->priv->mutex);
e_book_clear_op (book, our_op);
+ g_mutex_unlock (book->priv->mutex);
CORBA_exception_free (&ev);
@@ -1135,7 +1167,9 @@ do_get_contact (gboolean sync,
status = our_op->status;
*contact = our_op->contact;
+ g_mutex_lock (book->priv->mutex);
e_book_clear_op (book, our_op);
+ g_mutex_unlock (book->priv->mutex);
E_BOOK_CHECK_STATUS (status, error);
}
@@ -1194,15 +1228,16 @@ emit_async_get_contact_response (gpointe
if (op->cb.contact)
op->cb.contact (book, op->status, op->contact, op->closure);
+ g_mutex_lock (book->priv->mutex);
+
g_object_unref (op->contact);
- g_mutex_lock (book->priv->mutex);
book->priv->pending_idles = g_list_remove (book->priv->pending_idles,
GINT_TO_POINTER (op->idle_id));
- g_mutex_unlock (book->priv->mutex);
e_book_clear_op (book, op);
+ g_mutex_unlock (book->priv->mutex);
g_object_unref (book);
return FALSE;
@@ -1218,9 +1253,12 @@ e_book_response_get_contact (EBook
d(printf ("e_book_response_get_contact\n"));
+ g_mutex_lock (book->priv->mutex);
+
op = e_book_get_op (book, opid);
if (op == NULL) {
+ g_mutex_unlock (book->priv->mutex);
g_warning ("e_book_response_get_contact: Cannot find operation ");
return;
}
@@ -1239,11 +1277,11 @@ e_book_response_get_contact (EBook
op->book = g_object_ref (book);
op->idle_id = g_idle_add (emit_async_get_contact_response, op);
- g_mutex_lock (book->priv->mutex);
book->priv->pending_idles = g_list_prepend (book->priv->pending_idles,
GINT_TO_POINTER (op->idle_id));
- g_mutex_unlock (book->priv->mutex);
}
+
+ g_mutex_unlock (book->priv->mutex);
}
@@ -1620,15 +1658,16 @@ emit_async_get_book_view_response (gpoin
if (op->cb.book_view)
op->cb.book_view (book, op->status, op->view, op->closure);
+ g_mutex_lock (book->priv->mutex);
+
g_object_unref (op->view);
- g_mutex_lock (book->priv->mutex);
book->priv->pending_idles = g_list_remove (book->priv->pending_idles,
GINT_TO_POINTER (op->idle_id));
- g_mutex_unlock (book->priv->mutex);
e_book_clear_op (book, op);
+ g_mutex_unlock (book->priv->mutex);
g_object_unref (book);
return FALSE;
@@ -1645,9 +1684,12 @@ e_book_response_get_book_view (EBook
d(printf ("e_book_response_get_book_view\n"));
+ g_mutex_lock (book->priv->mutex);
+
op = e_book_get_op (book, opid);
if (op == NULL) {
+ g_mutex_unlock (book->priv->mutex);
g_warning ("e_book_response_get_book_view: Cannot find operation ");
return;
}
@@ -1668,11 +1710,11 @@ e_book_response_get_book_view (EBook
op->book = g_object_ref (book);
op->idle_id = g_idle_add (emit_async_get_book_view_response, op);
- g_mutex_lock (book->priv->mutex);
book->priv->pending_idles = g_list_prepend (book->priv->pending_idles,
GINT_TO_POINTER (op->idle_id));
- g_mutex_unlock (book->priv->mutex);
}
+
+ g_mutex_unlock (book->priv->mutex);
}
@@ -1734,7 +1776,9 @@ do_get_contacts (gboolean sync,
if (ev._major != CORBA_NO_EXCEPTION) {
+ g_mutex_lock (book->priv->mutex);
e_book_clear_op (book, our_op);
+ g_mutex_unlock (book->priv->mutex);
CORBA_exception_free (&ev);
@@ -1761,7 +1805,9 @@ do_get_contacts (gboolean sync,
status = our_op->status;
*contacts = our_op->list;
+ g_mutex_lock (book->priv->mutex);
e_book_clear_op (book, our_op);
+ g_mutex_unlock (book->priv->mutex);
E_BOOK_CHECK_STATUS (status, error);
}
@@ -1819,16 +1865,18 @@ emit_async_get_contacts_response (gpoint
if (op->cb.list)
op->cb.list (book, op->status, op->list, op->closure);
+
+ g_mutex_lock (book->priv->mutex);
+
g_list_foreach (op->list, (GFunc)g_object_unref, NULL);
g_list_free (op->list);
- g_mutex_lock (book->priv->mutex);
book->priv->pending_idles = g_list_remove (book->priv->pending_idles,
GINT_TO_POINTER (op->idle_id));
- g_mutex_unlock (book->priv->mutex);
e_book_clear_op (book, op);
+ g_mutex_unlock (book->priv->mutex);
g_object_unref (book);
return FALSE;
@@ -1844,9 +1892,12 @@ e_book_response_get_contacts (EBook
EBookOp *op;
+ g_mutex_lock (book->priv->mutex);
+
op = e_book_get_op (book, opid);
if (op == NULL) {
+ g_mutex_unlock (book->priv->mutex);
g_warning ("e_book_response_get_contacts: Cannot find operation ");
return;
}
@@ -1867,11 +1918,11 @@ e_book_response_get_contacts (EBook
op->book = g_object_ref (book);
op->status = status;
op->idle_id = g_idle_add (emit_async_get_contacts_response, op);
- g_mutex_lock (book->priv->mutex);
book->priv->pending_idles = g_list_prepend (book->priv->pending_idles,
GINT_TO_POINTER (op->idle_id));
- g_mutex_unlock (book->priv->mutex);
}
+
+ g_mutex_unlock (book->priv->mutex);
}
@@ -1927,7 +1978,9 @@ do_get_changes (gboolean sync,
if (ev._major != CORBA_NO_EXCEPTION) {
+ g_mutex_lock (book->priv->mutex);
e_book_clear_op (book, our_op);
+ g_mutex_unlock (book->priv->mutex);
CORBA_exception_free (&ev);
@@ -1954,7 +2007,9 @@ do_get_changes (gboolean sync,
status = our_op->status;
*changes = our_op->list;
+ g_mutex_lock (book->priv->mutex);
e_book_clear_op (book, our_op);
+ g_mutex_unlock (book->priv->mutex);
E_BOOK_CHECK_STATUS (status, error);
}
@@ -2000,15 +2055,17 @@ emit_async_get_changes_response (gpointe
if (op->cb.list)
op->cb.list (book, op->status, op->list, op->closure);
- e_book_free_change_list (op->list);
g_mutex_lock (book->priv->mutex);
+
+ e_book_free_change_list (op->list);
+
book->priv->pending_idles = g_list_remove (book->priv->pending_idles,
GINT_TO_POINTER (op->idle_id));
- g_mutex_unlock (book->priv->mutex);
e_book_clear_op (book, op);
+ g_mutex_unlock (book->priv->mutex);
g_object_unref (book);
return FALSE;
@@ -2023,9 +2080,12 @@ e_book_response_get_changes (EBook
EBookOp *op;
+ g_mutex_lock (book->priv->mutex);
+
op = e_book_get_op (book, opid);
if (op == NULL) {
+ g_mutex_unlock (book->priv->mutex);
g_warning ("e_book_response_get_changes: Cannot find operation ");
return;
}
@@ -2043,11 +2103,11 @@ e_book_response_get_changes (EBook
else {
op->book = g_object_ref (book);
op->idle_id = g_idle_add (emit_async_get_changes_response, op);
- g_mutex_lock (book->priv->mutex);
book->priv->pending_idles = g_list_prepend (book->priv->pending_idles,
GINT_TO_POINTER (op->idle_id));
- g_mutex_unlock (book->priv->mutex);
}
+
+ g_mutex_unlock (book->priv->mutex);
}
void
@@ -2076,12 +2136,13 @@ emit_async_generic_response (gpointer da
op->cb.status (book, op->status, op->closure);
g_mutex_lock (book->priv->mutex);
+
book->priv->pending_idles = g_list_remove (book->priv->pending_idles,
GINT_TO_POINTER (op->idle_id));
- g_mutex_unlock (book->priv->mutex);
e_book_clear_op (book, op);
+ g_mutex_unlock (book->priv->mutex);
g_object_unref (book);
return FALSE;
@@ -2094,9 +2155,12 @@ e_book_response_generic (EBook *bo
{
EBookOp *op;
+ g_mutex_lock (book->priv->mutex);
+
op = e_book_get_op (book, opid);
if (op == NULL) {
+ g_mutex_unlock (book->priv->mutex);
g_warning ("e_book_response_generic: Cannot find operation ");
return;
}
@@ -2114,11 +2178,11 @@ e_book_response_generic (EBook *bo
op->book = g_object_ref (book);
op->status = status;
op->idle_id = g_idle_add (emit_async_generic_response, op);
- g_mutex_lock (book->priv->mutex);
book->priv->pending_idles = g_list_prepend (book->priv->pending_idles,
GINT_TO_POINTER (op->idle_id));
- g_mutex_unlock (book->priv->mutex);
}
+
+ g_mutex_unlock (book->priv->mutex);
}
/**
@@ -2252,7 +2316,9 @@ do_open (gboolean sync,
if (ev._major != CORBA_NO_EXCEPTION) {
+ g_mutex_lock (book->priv->mutex);
e_book_clear_op (book, our_op);
+ g_mutex_unlock (book->priv->mutex);
CORBA_exception_free (&ev);
@@ -2278,7 +2344,9 @@ do_open (gboolean sync,
status = our_op->status;
+ g_mutex_lock (book->priv->mutex);
e_book_clear_op (book, our_op);
+ g_mutex_unlock (book->priv->mutex);
if (status == E_BOOK_ERROR_CANCELLED) {
/* Cancelled */
@@ -2343,21 +2411,26 @@ emit_async_open_response (gpointer data)
printf ("in async_open_response\n");
+ g_mutex_lock (book->priv->mutex);
+
if (op->status == E_BOOK_ERROR_OK)
book->priv->load_state = E_BOOK_SOURCE_LOADED;
else
book->priv->load_state = E_BOOK_SOURCE_NOT_LOADED;
+ g_mutex_unlock (book->priv->mutex);
+
if (op->cb.status)
op->cb.status (book, op->status, op->closure);
g_mutex_lock (book->priv->mutex);
+
book->priv->pending_idles = g_list_remove (book->priv->pending_idles,
GINT_TO_POINTER (op->idle_id));
- g_mutex_unlock (book->priv->mutex);
e_book_clear_op (book, op);
+ g_mutex_unlock (book->priv->mutex);
g_object_unref (book);
return FALSE;
@@ -2372,9 +2445,12 @@ e_book_response_open (EBook *book,
printf ("in e_book_response_open\n");
+ g_mutex_lock (book->priv->mutex);
+
op = e_book_get_op (book, opid);
if (op == NULL) {
+ g_mutex_unlock (book->priv->mutex);
g_warning ("e_book_response_open: Cannot find operation ");
return;
}
@@ -2392,11 +2468,11 @@ e_book_response_open (EBook *book,
op->book = g_object_ref (book);
op->status = status;
op->idle_id = g_idle_add (emit_async_open_response, op);
- g_mutex_lock (book->priv->mutex);
book->priv->pending_idles = g_list_prepend (book->priv->pending_idles,
GINT_TO_POINTER (op->idle_id));
- g_mutex_unlock (book->priv->mutex);
}
+
+ g_mutex_unlock (book->priv->mutex);
}
@@ -2436,7 +2512,9 @@ do_remove (gboolean sync,
if (ev._major != CORBA_NO_EXCEPTION) {
+ g_mutex_lock (book->priv->mutex);
e_book_clear_op (book, our_op);
+ g_mutex_unlock (book->priv->mutex);
CORBA_exception_free (&ev);
@@ -2462,7 +2540,9 @@ do_remove (gboolean sync,
status = our_op->status;
+ g_mutex_lock (book->priv->mutex);
e_book_clear_op (book, our_op);
+ g_mutex_unlock (book->priv->mutex);
E_BOOK_CHECK_STATUS (status, error);
}
@@ -2515,9 +2595,12 @@ e_book_response_remove (EBook *boo
d(printf ("e_book_response_remove\n"));
+ g_mutex_lock (book->priv->mutex);
+
op = e_book_get_op (book, opid);
if (op == NULL) {
+ g_mutex_unlock (book->priv->mutex);
g_warning ("e_book_response_remove: Cannot find operation ");
return;
}
@@ -2535,11 +2618,11 @@ e_book_response_remove (EBook *boo
op->book = g_object_ref (book);
op->status = status;
op->idle_id = g_idle_add (emit_async_generic_response, op);
- g_mutex_lock (book->priv->mutex);
book->priv->pending_idles = g_list_prepend (book->priv->pending_idles,
GINT_TO_POINTER (op->idle_id));
- g_mutex_unlock (book->priv->mutex);
}
+
+ g_mutex_unlock (book->priv->mutex);
}
static gboolean
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]