rendered paste bodyFirst thread :
void osync_client_unref(OSyncClient *client)
{
osync_assert(client);
if (g_atomic_int_dec_and_test(&(client->ref_count))) {
osync_trace(TRACE_ENTRY, "%s(%p)", __func__, client);
if (client->incoming) {
if (osync_queue_is_connected(client->incoming))
osync_queue_disconnect(client->incoming, NULL);
osync_queue_remove(client->incoming, NULL);
osync_queue_free(client->incoming);
}
if (client->outgoing) {
if (osync_queue_is_connected(client->outgoing))
osync_queue_disconnect(client->outgoing, NULL);
osync_queue_free(client->outgoing);
}
if (client->plugin)
osync_plugin_unref(client->plugin);
if (client->thread)
osync_thread_free(client->thread);
g_free(client);
osync_trace(TRACE_EXIT, "%s", __func__);
}
}
Second thread :
static gboolean osyncClientDisconnectCallback(gpointer data)
{
OSyncClient *client = data;
osync_trace(TRACE_INTERNAL, "client disconnect callback %p", client);
/* First, we disconnect our incoming queue. This will generate a HUP on the remote
* side. We dont disconnect our outgoing queue yet, since we have to make sure that
* all data is read. Only the listener should disconnect a pipe! */
if(client->incoming && osync_queue_is_connected(client->incoming))
osync_queue_disconnect(client->incoming, NULL);
if (client->outgoing) {
osync_trace(TRACE_INTERNAL, "waiting for client outgoing queue");
/* We now wait until the other side disconnect our outgoing queue */
while (osync_queue_is_connected(client->outgoing)) { g_usleep(100); }
/* Gives some time if anyone wants to grab the HUP message from the outgoing part of the pipe */
g_usleep(200);
/* Now we can safely disconnect our outgoing queue */
//FIXME : find proper condition those are only tests
if( (client->syncloop && g_main_loop_is_running(client->syncloop)) || client->thread )
if(client->outgoing)
osync_queue_disconnect(client->outgoing, NULL);
}
osync_trace(TRACE_INTERNAL, "waiting for client outgoing queue DONE");
return FALSE;
}
gdb showing the context switch :
#1 0xb7f4a566 in osync_client_unref (client=0x8095ec8) at /home/prahal/tmp/opensync/opensync/opensync/client/opensync_client.c:1277
1277 osync_queue_free(client->incoming);
(gdb) next
560 osync_trace(TRACE_ENTRY, "%s(%p)", __func__, queue);
(gdb) next
[New Thread 0xb400cb90 (LWP 23823)]
563 GMutex * freeLock = g_mutex_new();
(gdb) next
565 g_mutex_lock(freeLock);
(gdb) next
566 g_mutex_free(queue->pendingLock);
(gdb) next
568 g_mutex_free(queue->disconnectLock);
(gdb) next
[Switching to Thread 0xb400cb90 (LWP 23823)]
Breakpoint 3, osyncClientDisconnectCallback (data=0x8095ec8) at /home/prahal/tmp/opensync/opensync/opensync/client/opensync_client.c:1382
1382 {
(gdb) list
1377 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
1378 return FALSE;
1379 }
1380
1381 static gboolean osyncClientDisconnectCallback(gpointer data)
1382 {
1383 OSyncClient *client = data;
1384
1385 osync_trace(TRACE_INTERNAL, "client disconnect callback %p", client);
1386 /* First, we disconnect our incoming queue. This will generate a HUP on the remote
Function called:
void osync_queue_free(OSyncQueue *queue)
{
osync_trace(TRACE_ENTRY, "%s(%p)", __func__, queue);
OSyncMessage *message = NULL;
OSyncPendingMessage *pending = NULL;
g_mutex_free(queue->pendingLock);
g_mutex_free(queue->disconnectLock);
g_main_context_unref(queue->context);
_osync_queue_stop_incoming(queue);
while ((message = g_async_queue_try_pop(queue->incoming))) {
osync_message_unref(message);
}
g_async_queue_unref(queue->incoming);
while ((message = g_async_queue_try_pop(queue->outgoing))) {
osync_message_unref(message);
}
g_async_queue_unref(queue->outgoing);
while (queue->pendingReplies) {
pending = queue->pendingReplies->data;
g_free(pending);
queue->pendingReplies = g_list_remove(queue->pendingReplies, pending);
}
if (queue->name)
g_free(queue->name);
g_free(queue);
queue = NULL;
osync_trace(TRACE_EXIT, "%s", __func__);
}
osync_bool osync_queue_disconnect(OSyncQueue *queue, OSyncError **error)
{
osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, queue, error);
osync_assert(queue);
g_mutex_lock(queue->disconnectLock);
(...)
queue->fd = -1;
queue->connected = FALSE;
g_mutex_unlock(queue->disconnectLock);
osync_trace(TRACE_EXIT, "%s", __func__);
return TRUE;
}