我没有为我的GMainContext正确地减少ref_count。这里的示例程序是一个大型程序的小版本(使用线程,因此需要创建一个上下文并将其推送到线程上)。
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);
,一切都会按预期关闭。我不明白我在哪里获得这种所有权。
提前感谢您的帮助
答案 0 :(得分: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);
}
正确解析了我主要上下文中的引用次数。
愚蠢的错误。希望有人会至少找到一些我的帖子。
答案 1 :(得分:0)
g_main_context_new()
,g_main_loop_new()
和g_main_context_push_thread_default()
都引用了上下文。 g_main_context_pop_thread_default()
,g_main_loop_unref()
和g_main_context_unref()
都不对。所以你的直觉是合理的。
我会在gdb中使用一个观察点:watch ctx->ref_count
来找出添加额外引用的位置。