SRS的错误处理SrsCplxError—SRS源码分析

作者:罗上文,微信:Loken1,公众号:FFmpeg弦外之音

SrsCplxError 是 SRS 的错误处理类,可以发现,大部分函数,它的返回值都是 SrsCplxError 结构的,如下:

1-1

srs_error_tSrsCplxError* 的别名。


SrsCplxError 类的使用是比较简单的,下面介绍一下类里面的字段与方法。

1,int code

code 是错误码,你可以用 srs_error_create() 函数来设置这个错误码。


2,SrsCplxError* wrapped

这个是嵌套 的 SrsCplxError 类,这样可以记录两层返回错误,如下:

1-2

第一层 SrsCplxErrorfw->open() 函数返回的,记录的是 open() 内部哪里出了问题,而第二层 是 srs_error_wrap() 返回的,记录的是当前的函数哪里出了问题。

srs_error_wrap() 函数是一个宏来的,他里面用了 __FUNCTION__ 等特性来记录函数名,文件名,代码行数等信息,如下:

#define srs_error_wrap(err, fmt, ...) SrsCplxError::wrap(__FUNCTION__, __FILE__, __LINE__, err, fmt, ##__VA_ARGS__)

SrsCplxError* wrapped 不仅仅可以嵌套两层,可以套多层,只要遍历这个东西,就能很方便遍展示 出问题的函数调用链条。

SRS 的宏函数是小写的,我一开始看有点奇怪,不过 clion 有颜色区分,看着看着发现小写也挺舒服的。虽然习惯是用大写来命名宏函数。


3,std::string msg

这个 msg 是我们调用 srs_error_new() 的时候自己设置进去的,如下:

srs_error_new(ERROR_STREAM_CASTER_PORT, "invalid port=%d", port);

上面的 invalid port=%d 就会赋值给 msg 字段。


4,std::string funcstd::string fileint line

func 记录是哪个函数发生的错误,file 记录的是哪个文件发生的错误,而 line 记录的是文件的哪一行发生的错误。


5,SrsContextId cid

你可以把 cid 理解成协程的 ID,每个协程都有自己独立的 ID,cid 是一个 8 字节长度的字符串。SRS 是每一个链接,就用一个协程来处理。因此记录这个 ID,可以方便排查问题。

关于 协程上下文ID 是如何生成,请阅读《SRS的协程ID-SrsContextId


6,std::string desc

根据 SrsCplxError 的各个字段的信息,生成一个详细的描述,如下:

thread [51445][u923y9l1]: do_main() [./src/main/srs_main_server.cpp:248][errno=13]
thread [51445][u923y9l1]: run_directly_or_daemon() [./src/main/srs_main_server.cpp:496][errno=13]
thread [51445][u923y9l1]: run_in_thread_pool() [./src/main/srs_main_server.cpp:513][errno=13]
thread [51445][u923y9l1]: initialize() [./src/app/srs_app_threads.cpp:570][errno=13]
thread [51445][u923y9l1]: acquire_pid_file() [./src/app/srs_app_threads.cpp:594][errno=13](Permission denied)

上面是从 srs.log 文件里面提取出来的一段 desc

51445 是当前进程的ID,u923y9l1 是协程的ID,然后是发生错误的函数 的整个调用栈,以及对应的文件行数,这就是通过之前的 SrsCplxError* wrapped 嵌套类来实现的。

因为用 wrapped 形成了一个 链表,所以可以循环遍历出来 函数调用栈。


7,std::string _summary

根据 SrsCplxError 的各个字段的信息,生成一个简短的总结,如下:

TODO:后面再补充一个例子

上面已经介绍完了 SrsCplxError 类的字段,下面简单介绍一下他的一些函数。

SrsCplxError 类里面的方法都是 static 静态方法,所以你不用 new,可以直接调。

1-3

首先 creator() 负责 new 一个 SrsCplxError 对象出来,然后 wrap() 负责套上上一个错误,这样可以形成一个链表,方便遍历出来函数调用栈

这些函数其实相对比较简单,读者自行看代码 与 注释即可。


另外需要补充的是,SRS 创建了好几个宏函数给我们用,你不需要自己去传前面的 3 个参数,如下:

1-4


版权所属 xianwanzhiyin.net 罗上文 2023 all right reserved,powered by Gitbook该文件修订时间: 2024-01-15 15:05:53

results matching ""

    No results matching ""