在使用 Glibs GMainLoop 时,我遇到了一些文件描述符挂起的问题。我已将其缩小为一个具有一个事件的简单循环。
我在运行程序时正在监视文件描述符,并注意到有几个文件描述符永远不会关闭。
请看这个例子:
#include <stdio.h>
#include <glib.h>
#include <gio/gio.h>
#include <string.h>
#include <unistd.h>
static gboolean
timeout(gpointer user_data)
{
printf("## %s\n", __FUNCTION__);
g_main_loop_quit((GMainLoop*)user_data);
}
int
main(int argc, char **argv)
{
g_type_init();
printf("Check lsof now...\n");
sleep(10);
printf("--- time's up ---\n");
GMainContext *ctx = g_main_context_new();
GMainLoop *loop = g_main_loop_new(ctx, FALSE);
g_main_context_push_thread_default(ctx);
GSource *timer = g_timeout_source_new(2000);
g_source_set_callback(timer, timeout, loop, NULL);
g_source_attach(timer, ctx);
g_main_loop_run(loop);
g_main_context_pop_thread_default(ctx);
g_source_unref(timer);
g_main_loop_unref(loop);
g_main_context_unref(ctx);
printf("Check lsof now...\n");
sleep(10);
printf("--- time's up ---\n");
return 0;
}
在代码中标记的地方,我正在检查程序打开的文件描述符的数量。在第一个检查点有 3 个(忽略库等):
a.out 16333 hansm 0u CHR 136,43 0t0 46 /dev/pts/43
a.out 16333 hansm 1u CHR 136,43 0t0 46 /dev/pts/43
a.out 16333 hansm 2u CHR 136,43 0t0 46 /dev/pts/43
在第二个检查点有五个:
a.out 16873 hansm 0u CHR 136,43 0t0 46 /dev/pts/43
a.out 16873 hansm 1u CHR 136,43 0t0 46 /dev/pts/43
a.out 16873 hansm 2u CHR 136,43 0t0 46 /dev/pts/43
a.out 16873 hansm 5r FIFO 0,8 0t0 149228995 pipe
a.out 16873 hansm 6w FIFO 0,8 0t0 149228995 pipe
为什么这些管道没有关闭?
Valgrind 没有报告错误(除了一些“可能丢失的记忆”)。
fd(上面示例中的 5 和 6)在执行时打开
GMainContext *ctx = g_main_context_new();
而且显然从未关闭。我究竟做错了什么?