进程无故消失的破案历程
概述
前段时间公司有个系统的进程老是无故退出,在客户那边好好的,在家里服务器上老是出现,而且出现的时间也没啥规律,当然最终查出来还是有规律的,不过这个规律比较特别。大家看了后面的内容之后就明白了,真的很特殊!
初步分析 进程Crash?
当同事找到我的时候,我第一反应是是不是进程Crash了,如果是crash,那通常情况下会有crash的日志,检查了一遍,什么日志都没有留下,当然有时候Crash了,JVM也确实也不会留下Crash日志,不过这个特别罕见了,绝大部分是人为操作了。
被OS Kill?
既然不是Crash,那是不是系统存在内存泄露,被OS Kill了,不过很快通过dmesg也排除了,因为没有看到任何kill的迹象。
System.exit?
排除掉以上两个因素之后,接着马上就怀疑是否有什么代码执行过System.exit,于是重新编译了一把JDK,在System的exit方法处打印了些日志,于是坐等奇迹的发生。
令人兴奋的是,进程真的消失了,可是令人遗憾的是,我们埋点的日志并没有出现。这让我再次陷入沉思。
回归源码
从日志看确实是调用了ShutdownHook
于是找到addShutdownHook源码的位置
再次翻了一下JDK的源码,除了正常退出,System.exit等之外还有哪些情况会调用这个Shutdown的Hook,于是将埋点埋到了Shutdown.runHooks方法里。
继续等待事情再次发生,果然没多久,当天下午又发生了,打印了如下日志
也就是说当时是收到了一个SIGHUP的信号,这个信号最终会让进程退出,JVM对这个信号确实是没有特殊处理的,因此没有我们看到的Crash日志。
那接下来就是要找到为什么会收到这个信号了,这个信号又是谁发出的。
找出信号源
SIGHUP这个信号,最主要发生的场景是Shell终端关闭一个Session的时候会对该Session关联的进程发送一个SIGHUP信号,这个信号默认是会退出进程的。为此我还特地下载了ITerm2(我和同事都是mac,用的iTerm2的终端)的源码,还真找到了几个发送SIGHUP信号的代码
看名字PTYTask就能猜到了,这应该是一个seesion任务,于是进到代码里看到主要是有两个方法有发送SIGHUP信号给子进程,分别是dealloc和stop,其中stop会通过sendSignal函数给子进程发送SIGHUP信号。 对于我这种比较喜欢自虐的人,一般会想怎么就确定这个就是我要找的代码,之前从没有写过Object-C的代码,想着是否有个类似java的jmap的工具可以让我看内存里的对象的情况,然而临时没找到,不过偶然发现mac自带的Activity工具就能看到一些迹象,于是在Activity里找到了iTerm2进程,然后对其内存数据进行了采样,看能否抓到类似PTYTask. dealloc或者stop的调用栈,可是比较难模拟,因为存在时间差,点击采样的时候,很快就结束了,我还没来得及关闭session。在看采样报告的时候偶然看到了/usr/bin/sample的命令,原来Activity是采用这个命令进行采样的,于是摸索了一把,真能搞起来,采样的时间可以自定义,间隔是1ms一次,这样可以让我有充足的时间来操作了,于是在采样开启之后,不断地开一个session,起一个进程,然后close,重复做了好几次,结束采样之后看采样的输出,还真的就抓到了PTYTask.stop的调用栈
这也就验证了我close session的时候确实会给对应的子进程发送SIGHUP的信号。
那到此为止我们可以确认的是
- 进程退出是因为收到了信号SIGHUP
- 而SIGHUP的发生是因为终端Session Close 那到底是不是这种情况呢?
重新复盘问题现场
这个貌似不太可能,因为我们的shell脚本里执行java的时候都会带上&,这样进程就会后台运行,不会出现这种session的问题。看了下脚本,确实是带上了&的,自己也模拟了几遍,在一个shell里调用带有&的java命令,关闭终端java进程并不会退出。难道是因为同事的终端配置和我的不一样?后来要同事发了它的iTerm2里的seesion的配置给我看了下,和我的完全一样,这就挺奇怪了。
于是再回过来看看之前的几次进程消失时候的日志(我要同事有保留),看到那几个进程退出的时间点,分别是
- 2019-01-14 20:42:52* 2019-01-15 18:34:00* 2019-01-18 00:57:58* 2019-01-18 17:34:30
这几个时间点完全没有规律看起来,不过我突然想起2019-01-18那天是周五,同事是在上海出差,而17:34:30那会应该是快下班了,或者那会正好从上海赶车回杭州,于是问了下那个点同事是不是准备回杭州了,同事说那会确实合上电脑准备赶车回杭州,于是我接着问其他几个时间是不是差不多也是合上电脑的时间,结果还真是那么巧,既然这样,那说明我们的判断方向是正确的了。
水落石出
后面突然发现同事修改过这个启动脚本,在脚本的最后加了行命令
java xxxx &cd $DIR_LOG && tail -f common-*.log
难道是这个命令搞的鬼?
突然想起一个问题来,父子进程的问题,假如说当我们在shell里加了&跑的话,当父进程跑完之后,会直接将其挂到init进程下面,也就是你通过ps -ef去看它的父进程会是1号进程,但是如果原来的父进程没有跑完,那其父进程仍然会是原来的进程,所以当我们执行这个脚本的时候,一直被执行tail等待日志输出,这样一来,如果我们将当前窗口关闭了,那就意味着父进程会退出,然后给子进程发送SIGHUP的信号,于是导致java进程退出,但是如果我们在tail日志过程中ctrl c了,那java进程会过继给init进程,因此此时当我们再关闭窗口的时候也不会给其发送SIGHUP的信号了。
经过验证果然如此,至此这个消失的进程终于得到了解释,嗯,好在不是我们代码的问题,值得欣慰,毕竟我们的代码是要在客户那边运行的,必须要保证好稳定性。
欢迎关注 PerfMa 社区,推荐阅读:
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
循环神经网络
最近的股市震荡的有点厉害,跌的有点惨,面对如此情景,我波澜不惊,原因很简单,前几年我小试牛刀的时候我意识到了这不是我这种散户能玩得懂的,如今的我早已空仓。万物皆可 AI,如何用深度学习的方法去理解呢?当然,本篇不是一个指导买股票的文章,也不会用股票的数据信息去训练模型,我付不起这样的责任,也同样因为股票的市场行情远非一点股票价钱数据就可以解释的。下面我们来聊一聊正事,循环神经网络(RNN)。 为什么要引入循环神经网络?思考一个问题,如果问你明天股票的市场行情是看涨还是看跌,大概率你会搜索一下近一段时间的行情趋势,然后给我一个猜测的回答,我们认为明天的行情与近一段时间的股票价格是有关系的,我们人脑会对此进行一定的推测,我们知道神经网络在某一种程度上来说,也是一种模拟人脑的行为,那我们的神经网络可以做预测吗?我们之前用于训练神经网络的是一个独立的数据信息,我们把它们打乱顺序,还是可以得到正确的结果,很显然,股票的价钱信息是不能打乱顺序的,这两种数据有什么区别? 一种数据是顺序无关的,一种数据是顺序有关的。 我们之前的网络不好用了,我们需要新的网络去解决这个问题——循环神经网络。循环神经网...
- 下一篇
分布式图数据库 Nebula Graph 的 Index 实践
导读 索引是数据库系统中不可或缺的一个功能,数据库索引好比是书的目录,能加快数据库的查询速度,其实质是数据库管理系统中一个排序的数据结构。不同的数据库系统有不同的排序结构,目前常见的索引实现类型如 B-Tree index、B+-Tree index、B*-Tree index、Hash index、Bitmap index、Inverted index 等等,各种索引类型都有各自的排序算法。 虽然索引可以带来更高的查询性能,但是也存在一些缺点,例如: 创建索引和维护索引要耗费额外的时间,往往是随着数据量的增加而维护成本增大 索引需要占用物理空间 在对数据进行增删改的操作时需要耗费更多的时间,因为索引也要进行同步的维护 Nebula Graph 作为一个高性能的分布式图数据库,对于属性值的高性能查询,同样也实现了索引功能。本文将对 Nebula Graph的索引功能做一个详细介绍。 图数据库 Nebula Graph 术语 开始之前,这里罗列一些可能会使用到的图数据库和 Nebula Graph 专有术语: Tag:点的属性结构,一个 Vertex 可以附加多种 tag,以 TagID...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7安装Docker,走上虚拟化容器引擎之路
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS8编译安装MySQL8.0.19
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- CentOS关闭SELinux安全模块
- CentOS7,CentOS8安装Elasticsearch6.8.6