2012-04-11 12 views
0

我沒有得到ref_count正確減少我的GMainContext。這裏的示例程序是大型程序的小版本(使用線程,因此需要創建上下文並將其推送到線程上)。GMainContext的ref_count> 0後unref

GMainLoop *loop; 
GMainContext *ctx; 

struct conn 
{ 
    GSocketClient *client; 

    GSocketConnection *conn; 
    GInputStream *in; 
    GOutputStream *out; 

    gchar data[8192]; 
    unsigned int count; 
}; 

static void 
read_done_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) 
{ 
    struct conn *c = (struct conn *)user_data; 
    gssize len = g_input_stream_read_finish(c->in, res, NULL); 

    g_input_stream_read_async(c->in, c->data, sizeof c->data/sizeof *c->data, G_PRIORITY_DEFAULT, NULL, read_done_cb, c); 
    if (c->count++ == 1) { 
     printf("End of life as I know it...\n"); 
     g_main_loop_quit(loop); 
    } 
} 

static void 
write_done_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) 
{ 
} 

static void 
connect_done_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) 
{ 
    printf("## %s\n", __FUNCTION__); 

    struct conn *c = (struct conn *)user_data; 
    c->conn = g_socket_client_connect_to_host_finish(c->client, res, NULL); 

    c->in = g_io_stream_get_input_stream(G_IO_STREAM(c->conn)); 
    c->out = g_io_stream_get_output_stream(G_IO_STREAM(c->conn)); 

    char *data = "GET /axis-cgi/mjpg/video.cgi HTTP/1.0\r\n\r\n"; 

    g_output_stream_write_async(c->out, data, strlen(data), G_PRIORITY_DEFAULT, NULL, write_done_cb, c); 
    g_input_stream_read_async(c->in, c->data, sizeof c->data/sizeof *c->data, G_PRIORITY_DEFAULT, NULL, read_done_cb, c); 
} 

int 
main(int argc, char **argv) 
{ 
    g_type_init(); 

    struct conn *c = g_malloc0(sizeof *c); 
    ctx = g_main_context_new(); 
    loop = g_main_loop_new(ctx, FALSE); 
    g_main_context_push_thread_default(ctx); 

    c->client = g_socket_client_new(); 
    g_socket_client_connect_to_host_async(c->client, "10.85.25.20", 80, NULL, connect_done_cb, c); 

    g_main_loop_run(loop); 

    g_io_stream_close(G_IO_STREAM(c->conn), NULL, NULL); 
    g_object_unref(c->client); 
    g_object_unref(c->conn); 
    g_main_context_pop_thread_default(ctx); 
    g_main_loop_unref(loop); 
    g_main_context_unref(ctx); 

    return 0; 
} 

用gdb,剛剛返回之前插入斷點,我可以看到,CTX還有一個引用計數:

(gdb) p ctx->ref_count 
$2 = 1 

如果我做的是另g_main_context_unref(ctx);一切關閉預期。儘管我不明白我擁有這個所有權。

在此先感謝您的幫助

回答

1

我發現了錯誤。我read_done_cb我發出了另一個g_input_stream_read_async並立即退出主循環。 g_input_stream_read_async上調了ref_count,但GMainLoop從來沒有機會返回到我的回調(並減少我的GMainContext上的ref_count)。

移動呼叫g_input_stream_read_async在我的回調下面的if語句

static void 
read_done_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) 
{ 
    struct conn *c = (struct conn *)user_data; 
    gssize len = g_input_stream_read_finish(c->in, res, NULL); 

    if (c->count++ == 1) { 
     printf("End of life as I know it...\n"); 
     g_main_loop_quit(loop); 
    } 

    g_input_stream_read_async(c->in, c->data, sizeof c->data/sizeof *c->data, G_PRIORITY_DEFAULT, NULL, read_done_cb, c); 

} 

正確解決我的主要背景裁判的計數的數目。

愚蠢的錯誤。希望至少有人會發現我的帖子有些用處。

0

g_main_context_new()g_main_loop_new()g_main_context_push_thread_default()所有REF的上下文。 g_main_context_pop_thread_default(),g_main_loop_unref()g_main_context_unref()都沒有。所以你的直覺是健全的。

我會在gdb中使用一個觀察點:watch ctx->ref_count來找出額外引用的添加位置。