使用gst-rtsp-server调用gst_rtsp_client_close()时程序偶发无响应及断言失败求助
解决gst-rtsp-server调用gst_rtsp_client_close()时的断言失败与无响应问题
我之前也碰到过一模一样的问题,核心原因基本都是线程安全违规和GMainContext引用计数管理混乱。结合你修改test-uri示例的场景,给你几个具体的解决思路:
1. 绝对不要在非客户端线程直接调用gst_rtsp_client_close()
GstRTSPClient的所有操作都绑定在它专属的GMainContext线程上(通常是RTSP服务器的IO线程),如果你的定时器回调是在主线程或者其他独立线程执行的,直接调用close会触发线程冲突,进而导致引用计数的断言失败。
解决方法是用g_main_context_invoke()把关闭操作调度到客户端关联的线程中执行,示例代码如下:
static gboolean close_client_timeout(gpointer data) { GstRTSPClient *client = GST_RTSP_CLIENT(data); // 将close操作调度到client对应的GMainContext线程执行 g_main_context_invoke( gst_rtsp_client_get_main_context(client), (GSourceFunc) gst_rtsp_client_close, client ); // 释放之前给client添加的引用(下文会解释) gst_object_unref(client); return G_SOURCE_REMOVE; }
2. 正确管理Client的引用计数
当你在客户端连接时创建定时器,一定要给client手动增加一个引用——否则可能在定时器触发前,client已经被服务器自动销毁,导致悬空指针和引用计数错误:
static gboolean client_connected(GstRTSPServer *server, GstRTSPClient *client, gpointer user_data) { g_print("新客户端已连接\n"); // 增加引用,确保定时器回调时client依然有效 gst_object_ref(client); // 设置5秒后自动关闭客户端 g_timeout_add_seconds(5, close_client_timeout, client); return TRUE; }
3. 调用close前先检查客户端状态
如果客户端已经主动断开连接,它的GMainContext可能已经被unref,这时候再调用close必然触发断言。建议在执行关闭操作前先判断状态:
static gboolean close_client_timeout(gpointer data) { GstRTSPClient *client = GST_RTSP_CLIENT(data); if (!gst_rtsp_client_is_closed(client)) { g_main_context_invoke( gst_rtsp_client_get_main_context(client), (GSourceFunc) gst_rtsp_client_close, client ); } gst_object_unref(client); return G_SOURCE_REMOVE; }
4. 调试断言失败的技巧
如果你想进一步定位问题细节,可以启用GLib的致命警告模式,让程序在断言失败时直接崩溃,然后用gdb查看调用堆栈:
G_DEBUG=fatal-warnings ./your-modified-test-uri
启动后用gdb attach或直接运行程序,触发问题后输入bt命令查看堆栈,就能精准定位到哪个调用路径导致了g_main_context_unref的引用计数错误。
按照这个思路修改你的test-uri示例,应该就能彻底解决无响应和断言失败的问题了。
内容的提问来源于stack exchange,提问作者Hammar
相关产品推荐
相关产品推荐

