日记239. STL 里面 coredump 了,如何定位?

作者: | 更新日期:

帮别人解决一个问题,分析过程分析一下。

本文首发于公众号:天空的代码世界,微信号:tiankonguse

一、问题背景

有天中午,团队里的核心主力 A 向我求助,说服务偶现 coredump,core 在 STL 里面,定位好几天了,怀疑 STL 有 BUG。

我说,一般情况下不要怀疑 STL 这种基础库,有问题一般都是我们自己代码的问题。

二、初步分析

一看 核心主力 A 屏幕上的 coredump 的堆栈,core 在 STL 的 map 里面了。
堆栈往上是 Github 上的开源库 antrl 的调用链,在使用 STL 的 map。
堆栈再继续往上是 业务代码,调用的开源库 antrl 。

开源库 antrl 是基于LL算法实现的语法解析器生成器,一般用于读取、处理、执行或翻译结构化文本或二进制文件。 程序语言编译器一般都会有这样一个语法解析模块,这个库也是做这个事情的。

看了一眼堆栈后,我说:既然 core 在 map 里了,肯定是并发操作 map 导致的。
怀疑 antrl 有并发问题或者业务并发调用了同一个 antrl。

核心主力 A 反馈自己读 antrl 代码了,antrl 好像没有并发问题。 而对于自己的业务代码,确认使用 antrl 都是局部变量。

我于是要到容器名,去看堆栈,要到代码,准备看下。

三、阅读源码

近两年,项目内的核心主力A 和核心主力B研究了这个库,并在自己的模块里使用了这个库。

他们对这个库算是相当熟悉了。 之前我一直想了解这个库,但又一直没找到机会,于是,我便想趁这个机会,来了解下这个库。

抱着了解这个库的心态来定位这个问题,打开堆栈后,我是从最外层一层层向里面看的。

这样的好处是可以快速了解到,这个服务是怎么使用这个库的,从而了解这个库的部分功能。

大概看了业务逻辑调用 antrl 的入口,发现一个很奇怪的方式,大家这种方式一般怎么写的呢?

看了业务的代码,发现确实都是局部变量,不同请求之间没有复用的资源。

然后一层层去看 antrl 的代码,结果看到 core 的那一行代码时,一眼就发现了问题。

如图,getPrecedenceStartState 函数读没有加锁,setPrecedenceStartState 函数写的时候加锁了。

看到这里,当然会猜测外面加的有锁。

但是不管外面有没有加锁,这里设计显然存在一致性问题:写在哪里加锁,读也应该在哪里加锁。

看外面的代码,发现读真的没有加锁。

那问题就确定了,读没加锁,写加锁,并发时就 coredump 了。

于是我给 核心主力 A 两个建议:要么设计保持一致,锁传进来。要么外面加锁。

四、最后

后来,我想起去 github antrl 看看官方的代码,发现最新的 master 也有这个问题。

当然,github antrl 现在已经修复这个BUG,所以我可以公开这个 BUG 以及经过了。

你使用过 antrl 或者 语法解析器生成器吗?

《完》

-EOF-

本文公众号:天空的代码世界
个人微信号:tiankonguse

本文首发于公众号:天空的代码世界,微信号:tiankonguse
如果你想留言,可以在微信里面关注公众号进行留言。

点击查看评论

关注公众号,接收最新消息

tiankonguse +
穿越