【发布时间】:2018-05-16 10:48:15
【问题描述】:
我正在学习 gstreamer,我有一个简单的程序,我想在 Linux 中按 CTRL+C 后优雅地结束流。为此,我阅读了 gst-launch 的源代码,并看到 g_unix_signal_add() 用于添加信号。在我的代码中,我添加了以下行:
signal_watch_intr_id = g_unix_signal_add (SIGINT,
(GSourceFunc) intr_handler, data.pipeline);
其中 data 是包含管道的结构。我的处理函数是:
static gboolean
intr_handler (gpointer user_data)
{
printf("handling interrupt.\n");
GstElement *pipeline = (GstElement *) user_data;
/* post an application specific message */
gst_element_post_message (GST_ELEMENT (pipeline),
gst_message_new_application (GST_OBJECT (pipeline),
gst_structure_new ("GstLaunchInterrupt",
"message", G_TYPE_STRING, "Pipeline interrupted", NULL)));
/* remove signal handler */
signal_watch_intr_id = 0;
return G_SOURCE_REMOVE;
}
我希望它打印“处理中断”。到控制台,使管道发送 GST_MESSAGE_APPLICATION 类型的消息,然后将处理该消息以停止管道。但是,应用程序现在在 SIGINT 之后什么也不做。因为它什么都不做,我知道它改变了默认句柄,但我不明白为什么它不调用处理函数。有人可以帮我做这个处理吗?
【问题讨论】:
-
请注意
printf不是要调用的 signal-safe 函数。 -
不仅
printf(),而且gst_element_post_message()、gst_message_new_application()或gst_structure_new()很可能非常非常非常异步信号-不安全,意味着你深陷未定义的行为。 -
请问为什么 gstreamer 库中包含的 gst-launch-1.0 使用 gst_element_post_message 呢?我在信号处理方面没有经验,我真的很好奇他们为什么使用它应该使用什么
-
使用
g_unix_signal_add()安装的信号处理程序是not libc 信号处理程序,因此您不必担心只在其中使用异步信号安全函数。非常粗略地说,g_unix_signal_add()的工作方式是安装一个设置标志的 libc 信号处理程序,并且该标志在GMainContext的下一次迭代中被拾取,而 that 是你的回调函数被调用。 -
所以我怀疑这不起作用,因为您没有运行
GMainLoop(或者,等效地,迭代GMainContext)。是这样吗?