All pastes #818149 Raw Edit

Unnamed

public text v1 · immutable
·published 2007-12-16 02:54 UTC
rendered paste body
First 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;
}