Race condition bug(s) in new GIOP timeout code
- From: Jules Colding <colding omesc com>
- To: ORBit2 <orbit-list gnome org>
- Cc: Michael Meeks <mmeeks novell com>, "Gustavo J. A. M. Carneiro" <gjc inescporto pt>
- Subject: Race condition bug(s) in new GIOP timeout code
- Date: Tue, 14 Aug 2007 14:39:08 +0200
Hi,
I did it again :-(
Please see:
http://bugzilla.gnome.org/show_bug.cgi?id=466574
The patch below will fix these issues. Any objections?
Best regards,
jules
Index: src/orb/GIOP/giop-recv-buffer.c
===================================================================
--- src/orb/GIOP/giop-recv-buffer.c (revision 2016)
+++ src/orb/GIOP/giop-recv-buffer.c (working copy)
@@ -736,6 +736,7 @@
link_io_thread_remove_timeout (ent->cnx->parent.timeout_source_id);
ent->cnx->parent.timeout_source_id = 0;
ent->cnx->parent.timeout_status = LINK_TIMEOUT_NO;
+ g_object_unref (&ent->cnx->parent); // we remove the source so we must unref the connection
} else if (ent->cnx->parent.timeout_status == LINK_TIMEOUT_YES)
*timeout = TRUE;
g_mutex_unlock (ent->cnx->parent.timeout_mutex);
@@ -1355,17 +1356,12 @@
return TRUE;
}
-struct timeout_thread_data {
- GIOPThread *tdata;
- LinkConnection *lcnx;
-};
-
static gboolean
-giop_timeout(gpointer data)
+giop_timeout (gpointer data)
{
gboolean retv = FALSE;
- LinkConnection *lcnx = ((struct timeout_thread_data*)data)->lcnx;
- GIOPThread *tdata = ((struct timeout_thread_data*)data)->tdata;
+ LinkConnection *lcnx = (LinkConnection*)data;
+ GIOPThread *tdata = (GIOPThread *)lcnx->tdata;
g_assert (lcnx->timeout_mutex);
@@ -1386,27 +1382,29 @@
giop_incoming_signal_T (tdata, GIOP_CLOSECONNECTION);
g_mutex_unlock (tdata->lock); /* ent_lock */
-out:
- g_object_unref (lcnx);
- g_free (data);
+ g_object_unref (lcnx); // we remove the source so we must unref lcnx
+out:
return retv;
}
void
-giop_timeout_add(GIOPConnection *cnx)
+giop_timeout_add (GIOPConnection *cnx)
{
- struct timeout_thread_data *data = NULL;
+ static GStaticMutex static_mutex = G_STATIC_MUTEX_INIT;
LinkConnection *lcnx = LINK_CONNECTION (cnx);
- GSource *timeout_source = NULL;
if (!giop_thread_io ())
return;
if (!lcnx->timeout_msec)
return;
- g_object_ref (lcnx);
+ g_static_mutex_lock (&static_mutex);
+ if (lcnx->timeout_source_id)
+ goto out;
+ g_object_ref (lcnx); // to be unref'ed by the one who removes the timeout source
+
if (!lcnx->timeout_mutex)
lcnx->timeout_mutex = g_mutex_new ();
@@ -1414,11 +1412,12 @@
lcnx->timeout_status = LINK_TIMEOUT_UNKNOWN;
g_mutex_unlock (lcnx->timeout_mutex);
- data = g_new0 (struct timeout_thread_data, 1);
- data->tdata = giop_thread_self ();
- data->lcnx = lcnx;
+ lcnx->tdata = giop_thread_self ();
- lcnx->timeout_source_id = link_io_thread_add_timeout (lcnx->timeout_msec, giop_timeout, data);
+ lcnx->timeout_source_id = link_io_thread_add_timeout (lcnx->timeout_msec, giop_timeout, (gpointer)lcnx);
+
+out:
+ g_static_mutex_unlock (&static_mutex);
}
GIOPRecvBuffer *
Index: src/orb/GIOP/giop-send-buffer.c
===================================================================
--- src/orb/GIOP/giop-send-buffer.c (revision 2016)
+++ src/orb/GIOP/giop-send-buffer.c (working copy)
@@ -456,6 +456,7 @@
if (g_thread_supported ()
&& lcnx->timeout_msec
+ && !lcnx->timeout_source_id
&& !giop_send_buffer_is_oneway (buf)) {
giop_timeout_add (cnx);
}
Index: linc2/include/linc/linc-connection.h
===================================================================
--- linc2/include/linc/linc-connection.h (revision 2016)
+++ linc2/include/linc/linc-connection.h (working copy)
@@ -67,6 +67,7 @@
guint timeout_msec;
guint timeout_source_id; // protected by timeout_mutex
LinkTimeoutStatus timeout_status; // protected by timeout_mutex
+ void *tdata; // "do not pollute the namespace"-hack (it's a GIOPThread*)
} LinkConnection;
typedef struct {
Index: linc2/src/linc-connection.c
===================================================================
--- linc2/src/linc-connection.c (revision 2016)
+++ linc2/src/linc-connection.c (working copy)
@@ -1269,11 +1269,9 @@
if (cnx->timeout_mutex)
g_mutex_free (cnx->timeout_mutex);
-
- if (cnx->timeout_source_id)
+ if (cnx->timeout_source_id)
link_io_thread_remove_timeout (cnx->timeout_source_id);
-
#ifdef G_ENABLE_DEBUG
g_assert (g_list_find(cnx_list, cnx) == NULL);
#endif
@@ -1294,6 +1292,7 @@
cnx->timeout_msec = 0;
cnx->timeout_source_id = 0;
cnx->timeout_status = LINK_TIMEOUT_UNKNOWN;
+ cnx->tdata = NULL;
#ifdef CONNECTION_DEBUG
cnx->priv->total_read_bytes = 0;
Index: linc2/ChangeLog
===================================================================
--- linc2/ChangeLog (revision 2016)
+++ linc2/ChangeLog (working copy)
@@ -1,3 +1,11 @@
+2007-08-14 Jules Colding <colding omesc com>
+
+ * src/linc-connection.c (link_connection_init): Initialize new
+ data member in connection struct
+
+ * include/linc/linc-connection.h (struct): Add void member
+ to hold a GIOPThread*
+
2007-08-07 Tor Lillqvist <tml novell com>
* src/linc-connection.c (link_connection_from_fd_T): Ifdef
Index: configure.in
===================================================================
--- configure.in (revision 2016)
+++ configure.in (working copy)
@@ -1,6 +1,6 @@
m4_define([orbit_major_version],[2])
m4_define([orbit_minor_version],[14])
-m4_define([orbit_micro_version],[9])
+m4_define([orbit_micro_version],[8])
m4_define([orbit_version],[orbit_major_version.orbit_minor_version.orbit_micro_version])
dnl Process this file with autoconf to produce a configure script.
Index: ChangeLog
===================================================================
--- ChangeLog (revision 2016)
+++ ChangeLog (working copy)
@@ -1,3 +1,18 @@
+2007-08-14 Jules Colding <colding omesc com>
+
+ * src/orb/GIOP/giop-send-buffer.c (giop_send_buffer_write): Do
+ not enter giop_timeout_add() if a timeout is already present. This
+ check is not thread safe, but the additional check in giop_timeout_add()
+ is.
+
+ * src/orb/GIOP/giop-recv-buffer.c (giop_timeout_add): Fix
+ race when creating the timeout mutex.
+ Do not depend on the dynamically created "struct timeout_thread_data".
+ The right thing to do is to pass the connection directly and add an
+ additional member to the LincConnection to hold the GIOPThread.
+ (giop_timeout): Correct to use new input data (LincConnection*).
+ (giop_recv_buffer_get): Fix memory leak.
+
2007-08-07 Tor Lillqvist <tml novell com>
* test/timeout_impl.c (impl_Timeout_ping): Use g_usleep() instead
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]