如何在 gst_object_unref() 之后调试带有泄漏文件描述符的 gstreamer 管道?

How to debug gstreamer pipeline with leaking file descriptors after gst_object_unref()?

我有一个在 gstreamer 中看起来大致像这样的自定义管道 shorthand:

gst-launch-1.0 rtspsrc location=rtsp://<url-for-stream> ! rtph264depay ! h264parse ! imxvpudec ! *any-sink*

这种类型的管道在 gst-launch-1.0 中运行良好,因为它不需要正确清理自身,但我需要使用直接 GST API 在我的 C++ 应用程序中使用它。这意味着我使用 myPipeline = gst_pipeline_new("custom-pipeline"),然后按名称分配每个插件,link 它们,以及 运行 管道。我后来有一个要求停止管道并调用 gst_object_unref(myPipeline)。这样做时,我观察到文件描述符被遗忘。稍后我需要重新启动管道,因此泄漏更加严重。这需要经常发生,以至于泄漏的描述符给我一个例外:

GLib-ERROR **: Creating pipes for GWakeup: Too many open files

我可以使用 lsof...

分析打开的文件
lsof +E -aUc myGstApplication        
lsof: netlink UNIX socket msg peer info error
COMMAND    PID USER   FD   TYPE     DEVICE SIZE/OFF     NODE NAME
myGstApplication 5943 root    3u  unix 0xabfb6c00      0t0 11200335 type=STREAM
myGstApplication 5943 root   11u  unix 0xd9d47180      0t0 11207020 type=STREAM

...更多,具体取决于 运行s...

myGstApplication 5943 root   50u  unix 0xabe99080      0t0 11211987 type=STREAM

每次我取消引用()并重建管道时,我似乎都会得到两个新的 'type=STREAM' 文件描述符。

在 lsof 中看到描述符很好,但我不知道如何在代码中追踪这些文件的来源。例如,是否有任何 lsof 输出实际上引导我获得更好的调试信息? .我如何追踪这些泄漏的真正来源并阻止它们?有更好的方法……对吗?

我怀疑 rtspsrc gstreamer 管道元素与此有关,但 rtspsrc 本身就是底层 gstreamer 实现(udpsrcs、demuxers 等)的泥潭。我不相信它是rtspsrc 中的一个错误,因为很多其他人似乎都在使用这个而没有复制相同的东西。我可以在我的应用程序代码中做一些可以以不明显的方式导致这种行为的事情吗?

非常感谢任何帮助,谢谢!

经过深入研究和有趣的问题!

根据 lsof 输出,泄漏的文件描述符似乎源自 socketpair 系统调用。你用 strace 确认:

strace -fe socketpair myGstApplication

在此之后,您可以省略对 socketpair sycall 的过滤,并查看完整的 strace 输出,试图了解这些 FD 的用途。我用 gst-launch-1.0 试过这个,结果没有定论。这些 FD 似乎在两端都设置为只读,并且从未传输过任何内容...因此它们必须仅用于同一应用程序的多个 threads/subprocesses 之间的 control/coodination。

下一个尝试是 gdb:

gdb -ex 'break socketpair' -ex run myGstApplication

当它在断点处停止时,使用 bt 命令查看堆栈跟踪。可能安装 gstreamer 的调试包是获得更具可读性的堆栈跟踪的好主意。

HTH:)