0
点赞
收藏
分享

微信扫一扫

一次linux中定位c++程序运行异常的经历


今天下午我遇到了一些棘手的问题,因为在​​mips64​​上编译程序,经常出现程序编译不出来,或者运行不正常,花了很长的时间定位,最后和同事一些解决了,下面分享出来我提炼出来的一些核心定位问题的步骤。

子线程创建不出来

猜测:​​go​​​的程序都能创建出子线程,但是​​c++​​的创建不出来,但是在 x86 可以,是不是什么 linux 系统限制?

一次linux中定位c++程序运行异常的经历_编程语言

一次linux中定位c++程序运行异常的经历_堆栈_02

解决方法:加错误日志进行调试(最 lower 办法)

找到报错点:

一次linux中定位c++程序运行异常的经历_编程语言_03

查询 ​​man​​ 手册,看看是不是能找到有帮助的东西

man pthread_attr_setstacksize

打印出解释

ERRORS
pthread_attr_setstacksize() can fail with the following error:

EINVAL The stack size is less than PTHREAD_STACK_MIN (16384) bytes.

On some systems, pthread_attr_setstacksize() can fail with the error EINVAL if stacksize is not a multiple of the system page size.

翻译上面的话,可能会产生这个错误

  • ​EINVAL​​​ 堆栈大小小于 ​​PTHREAD_STACK_MIN(16384)​​ 字节。
  • 在某些系统上,如果 ​​stacksize​​ 不是系统页面大小的倍数, ​​pthread_attr_setstacksize()​​ 可能会失败,并显示错误 ​​EINVAL​

查询​​ linux​​​含义, 得知错误码 ​​22​​​ 果然和 ​​man​​ 手册中说的一致,是参数有问题。

一次linux中定位c++程序运行异常的经历_堆栈_04

第一次尝试:扩大线程栈到上面说的 ​​16384​​ ,但还是报错

一次linux中定位c++程序运行异常的经历_编程语言_05

根据经验,查看最小页大小,发现是 ​​16k​​​ , 而 ​​x86​​​ 架构是 ​​4K​​​ ,原来用的 ​​20K​​ 是不对齐的,怪不得创建不出来线程。

一次linux中定位c++程序运行异常的经历_堆栈_06

依次尝试, 最终发现 ​​10*16K​​ 子线程成功创建。

但是不准确,按其说法,应该是设置 ​​PAGESIZE​​​ 的整数倍都行,怀疑其对最小值有要求。 ​​c++​​​ 的头文件在 ​​/usr/include​​​ 目录下面, ​​PTHREAD_STACK_MIN​​ 是一个常量,估计里面会有定义,尝试查找

$ grep -rl PTHREAD_STACK_MIN *
bits/local_lim.h
pthread.h

还真让我找到了, 根据英文注释,至少要两个 ​​64K​​ 作为线程栈,才能跑起一个线程。

一次linux中定位c++程序运行异常的经历_编程语言_07

至此问题解决。

部分线程卡住

我发现程序虽然正常运行,但是部分功能不正常,经过查看日志发现,有一个线程只执行了一半就卡住了。

经过查看日志可以定位出是哪个线程卡住,如果从日志看不出来也没关系。可以使用 ​​pstack 进程号​​ 看一些进程堆栈。

查看进程 ​​pid​

ps -ef |grep 进程名

使用 ​​gdb​​ 查看是否出现问题,两个重要命令

gdb attach {pid} #查看正在运行程序的栈
info thread #进入以后使用,查看线程信息

找到错误位置,出现了 ​​fgets()​​​ 和 ​​read()​​ 函数,怀疑是此处出现问题。

一次linux中定位c++程序运行异常的经历_linux_08

一次linux中定位c++程序运行异常的经历_编程语言_09

怀疑 1: ​​_LINE_LENGTH 1024​​ 长度太短,接受命令返回值后超过了数组本身的长度,覆盖了位置的内存。

这种情况我以前遇到过,表现应该是程序直接就崩溃了。

怀疑 2:执行命令的时候卡了,导致后面的程序没有执行。

根据 ​​gdb​​​ 打印出来的参数,执行 ​​linux​​ 命令进行测试,果然是卡在这了!

再次使用 ​​pstree -p {pid}​​​ 查看,确实主线程,调用了 ​​linux​​ 命令卡住。

一次linux中定位c++程序运行异常的经历_c++_10

接下来解决卡命令的问题

解决 1:加 ​​timeout​​ 处理空返回。下面是示例命令,并不是我使用的命令。

timeout 5 ls -al

代表超过 5 秒返回。

解决 2:定位为什么这个 ​​linux​​ 命令会卡住。

strace ls -al

直到解决为止。这就是今晚我加班到 10 点 30 解决的问题,我又用了一个小时总结下整个过程备忘,希望对你也有帮助。


举报

相关推荐

0 条评论