【发布时间】:2012-12-21 20:35:02
【问题描述】:
正如问题所述,总是在所有错误函数和信号处理程序中收集基于软件的回溯(如使用 libc 回溯 http://www.gnu.org/software/libc/manual/html_node/Backtraces.html)是否有用?
它对调试各种各样的错误(如内存、并发错误等)不是很有帮助吗?我猜它不会损害正常性能,并且只会在错误路径中触发。
【问题讨论】:
正如问题所述,总是在所有错误函数和信号处理程序中收集基于软件的回溯(如使用 libc 回溯 http://www.gnu.org/software/libc/manual/html_node/Backtraces.html)是否有用?
它对调试各种各样的错误(如内存、并发错误等)不是很有帮助吗?我猜它不会损害正常性能,并且只会在错误路径中触发。
【问题讨论】:
正如问题所述,始终收集基于软件的回溯是否有用
是的,在以下情况下拥有崩溃堆栈跟踪通常非常有用:
喜欢使用 libc 回溯
glibc backtrace 在特定条件下调用calloc,在崩溃处理程序中是不安全的。它可能导致挂起和上述进一步的损坏。编写一个能够以异步信号安全的方式可靠地打印堆栈跟踪的崩溃处理程序并非易事。
为什么“标准”应用程序中的错误函数不调用回溯?
考虑cat /no/such/file。目前它产生:
cat: /no/such/file: No such file or directory
这是您真正需要知道的全部。让这个印刷品做其他任何事情都是没有用的。如果你有很多这样的文件,并且 cat 为每个文件打印一个完整的堆栈跟踪,你会得到很多页的错误输出,这只会让找到真正的问题变得更加困难。
对于致命的信号处理程序(例如SIGSEGV),答案是大多数“标准”应用程序实际上并不处理此类信号,而只是使用默认操作,这会产生核心转储。
但如果他们确实捕捉到了信号,从信号处理程序中调用backtrace、backtrace_symbols 或backtrace_symbols_fd 将同样不安全,并且可能死锁,这比简单地转储核心要糟糕得多。考虑一下如果您有一个包含 1000 个命令的长时间运行的脚本会发生什么。您启动它,一周后发现它没有任何进展,因为第二个命令在尝试打印崩溃堆栈跟踪时崩溃并死锁。
【讨论】:
backtrace_symbols_fd不比 backtrace 更安全。是什么让你不这么认为?