天天看点

OTP supervisor的monitor_child是否有漏洞

otp的supervisor中为了防止淘气的child从link的另一端断掉link,supervisor会在shutdown child之前unlink(child)并切换为monitor状态,这样supervisor对child的监控将无法被chlid终止。这段代码是由monitor_child/1实现的,其具体实现代码如下:

但是这里我们会发现一个问题,unlink后monitor_child/1有一段奇怪的代码:

注释的意思是,如果在unlink之前child已经死掉,则 ‘exit‘消息中的reason才是真实的reason ,而之后因monitor/2而产生的‘down‘消息会因为无法找到目标进程而变为noproc. 但是这里就存在一个问题:receive语句在扫描信箱后立刻就退出了,但是有可能unlink之前的‘exit‘消息此时 并未到达。

supervisor究竟是否存在这个问题呢?erlang otp的文档中对unlink/1是这样描述的:

从最后一句话中,我们可以看出——新版本的unlink/1的语义中不仅包含断开link,同时包含不再接收‘exit‘信号。所以unlink/1后如果信箱中还有‘exit‘信号,那一定是 unlink/1真正生效之前到达 的。也就是说,不可能存在unlink/1之后到达的‘exit‘消息,也就不会出现之前分析的‘exit‘信号堆积问题。

一开始还在怀疑erlang的实现怎么如此不严谨,原来erlang的代码看似简单,但是底层的代码事实上是仔细考虑了许多问题的。

继续阅读