Link and Monitor differences

Introduction

link/1 and monitor/2 are 2 different ways of notifying (or know) that a process died. Thing is, these are really very different in nature and these differences are not widely understood by beginners. So let's shed some light on this subject!

Linking to a process

Links are what makes it possible to have supervisor trees. As stated in the Error Handling section of the processes reference manual:

Erlang has a built-in feature for error handling between processes. Terminating processes will emit exit signals to all linked processes, which may terminate as well or handle the exit in some way.

The signal in question is the exit signal, and the links make this signal propagate through processes (i.e: up in the supervisor hierarchy). By default, this signal makes your processes terminate as well. Assume the following code:

  1. -module(mymodule).
  2. start_link() ->
  3. gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
  4. ...
  5. crash() ->
  6. gen_server:cast(?MODULE, crash).
  7. ...
  8. handle_cast(crash,State) ->
  9. {stop, error, State};
  10. ...

Let's spawn of those, and try to link our shell to it:

  1. 1> self().
  2. <0.31.0>
  3. 2> mymodule:start_link().
  4. {ok,<0.34.0>}
  5. 3> mymodule:crash().
  6. =ERROR REPORT==== 30-Dec-2012::15:36:47 ===
  7. ** Generic server a terminating
  8. ** Last message in was {'$gen_cast',crash}
  9. ** When Server state == []
  10. ** Reason for termination ==
  11. ** error
  12. ** exception exit: error
  13. 4> self().
  14. <0.36.0>

As you can see, using gen_server:start_link/4 automatically creates a link between our shell and the newly started process. So when this new process terminates, our shell gets an exit signal, also crashes, but it gets automatically restarted (note how the self() code returned 2 different pids).

The Receiving Exit Signals section of the processes reference manual gives some more information:

The default behaviour when a process receives an exit signal with an exit reason other than normal, is to terminate and in turn emit exit signals with the same exit reason to its linked processes. An exit signal with reason normal is ignored.

A process can be set to trap exit signals by calling:

process_flag(trap_exit, true)

When a process is trapping exits, it will not terminate when an exit signal is received. Instead, the signal is transformed into a message {'EXIT',FromPid,Reason} which is put into the mailbox of the process just like a regular message.

Let's now try the same thing, but capturing the exit signal with process_flag/2

:

  1. 1> process_flag(trap_exit, true).
  2. false
  3. 2> self().
  4. <0.31.0>
  5. 3> mymodule:start_link().
  6. {ok,<0.35.0>}
  7. 4> mymodule:crash().
  8. ok
  9. 5>
  10. =ERROR REPORT==== 30-Dec-2012::15:51:20 ===
  11. ** Generic server mymodule terminating
  12. ** Last message in was {'$gen_cast',crash}
  13. ** When Server state == []
  14. ** Reason for termination ==
  15. ** error
  16. 5> self().
  17. <0.31.0>
  18. 6> receive X->X end.
  19. {'EXIT',<0.35.0>,error}

As you can see, the shell didn't died, but got a message instead. Cool!

To sum up, and to quote the Processes entry in the OTP reference manual:

    • Two processes can be linked to each other. A link between two processes Pid1 and Pid2 is created by Pid1 calling the BIF link(Pid2) (or vice versa).
    • Links are bidirectional and there can only be one link between two processes. Repeated calls to link(Pid) have no effect.
    • The default behaviour when a process receives an exit signal with an exit reason other than normal, is to terminate and in turn emit exit signals with the same exit reason to its linked processes.
    • An exit signal with reason normal is ignored.

As a final note to links, there are a couple of interesting functions to know about:

Monitoring a process

Monitors are not links, they are a more relaxed way of knowing what happened to a process.

They use messages instead of signals, and these messages are not propagated like signals, so nothing happens to your process when a monitored process exits (except that you get a new message in your mailbox). Also, they are unidirectional and allow you to establish as many "monitors" as you want (remember how links limited the number of links between 2 processes to just 1). Quoting the manual:

An alternative to links are monitors. A process Pid1 can create a monitor for Pid2 by calling the BIF erlang:monitor(process, Pid2). The function returns a reference Ref.

If Pid2 terminates with exit reason Reason, a 'DOWN' message is sent to Pid1:

{'DOWN', Ref, process, Pid2, Reason}

Monitors are unidirectional. Repeated calls to erlang:monitor(process, Pid) will create several, independent monitors and each one will send a 'DOWN' message when Pid terminates.

Now, to the very same source code we tried above, let's modify it to add a start/0 function:

  1. -module(mymodule).
  2. start() ->
  3. gen_server:start({local, ?MODULE}, ?MODULE, [], []).
  4. ...
  5. start_link() ->
  6. gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
  7. ...
  8. crash() ->
  9. gen_server:cast(?MODULE, crash).
  10. ...
  11. handle_cast(crash,State) ->
  12. {stop, error, State};
  13. ...

Note the new start/0 call that uses gen_server:start/4 instead of gen_server:start_link/4, so we can avoid having our shell linked to the new process when trying it.

Let's try it in the shell:

  1. 1> self().
  2. <0.31.0>
  3. 2> mymodule:start().
  4. {ok,<0.34.0>}
  5. 3> process_flag(trap_exit, true).
  6. false
  7. 4> erlang:monitor(process, mymodule).
  8. #Ref<0.0.0.43>
  9. 5> mymodule:crash().
  10. ok
  11. =ERROR REPORT==== 30-Dec-2012::16:21:29 ===
  12. ** Generic server mymodule terminating
  13. ** Last message in was {'$gen_cast',crash}
  14. ** When Server state == []
  15. ** Reason for termination ==
  16. ** error
  17. 6> receive X->X end.
  18. {'DOWN',#Ref<0.0.0.43>,process,{mymodule,nonode@nohost},error}

So our shell, while still was informed about the exit of the other process, didn't die (because it didn't got an exit signal).

A couple of interesting functions related to monitoring:

To link or to monitor: That is the question

So this brings up the question: should I link to or monitor my processes? Of course the answer is 42.. I mean, it depends. Use link if you:

      • Have a dependency on a process (i.e: you can't run if a specific process dies). This fits great into supervisor trees.
      • Have a bidirectional dependency, where a parent can't run if the child dies, and you also want to kill the child if the parent dies in turn.
      • Only need 1 link between processes (remember that if A and B are linked, all subsequent calls to link/2 will be ignored).
      • You are a supervisor, or you want some kind of physical relationship between your processes in your architecture (i.e: you actually need to die or restart or try something out to fix the situation that led to the death of your child.

Use monitor if you:

      • Just want to know if a specific process is running, but it's ok for you to continue execution without it (i.e: you can just send an alarm and keep going).
      • Don't need a bidirectional relation (i.e: you want A to know about B dying but you don't need B to know about A).
      • You are an external process, just interested in the faith of a particular process

【转载】Erlang 中 link 和 monitor 的区别的更多相关文章

  1. [转载]C++中声明与定义的区别

    C++学了这么多年你知道为什么定义类时,类的定义放在.h文件中,而类的实现放在cpp文件中.它们为什么能够关联到一起呢?你知道什么东西可以放在.h文件中,什么不能.什么东西又可以放在cpp文件中.如果 ...

  2. CSS中link与import的区别

    一.import的用法 1,在html文件中 <style type="text/css"> @import url(http://www.dreamdu.com/st ...

  3. AngularJS自定义Directive中link和controller的区别

    在AngularJS中,自定义Directive过程中,有时用link和controller都能实现相同的功能.那么,两者有什么区别呢? 使用link函数的Directive 页面大致是: <b ...

  4. AngularJs 指令 directive中link,controller 的区别

    其实严格来讲,link和controller是完全不同的概念,这里讲区别有点牵强. angular指令中,带有link和controller两个函数,很多人在写指令的时候不知道是写在link里 还是c ...

  5. HTML网页设计中 link 和 @import 的区别

    页面中使用CSS的方式主要有3种:行内添加定义style属性值,页面头部内嵌调用和外面链接调用,其中外面引用有两种:link和@import.外部引用CSS两种方式link和@import的方式分别是 ...

  6. 转载http中302与301的区别

    http://blog.csdn.net/qmhball/article/details/7838989 一.官方说法301,302 都是HTTP状态的编码,都代表着某个URL发生了转移,不同之处在于 ...

  7. 【对比分析三】CSS中 link 和@import 的区别

    1).  link 是 XHTML 标签,无兼容问题: @import 是在 CSS2.1 提出的,只有IE5以上才能识别. 2).  语法结构不同. link (链接式)只能放入HTML源码中,语法 ...

  8. 外部引用CSS中 link与@import的区别

    差别1:link属于XHTML标签,而@import完全是CSS提供的一种方式. link标签除了可以加载CSS外,还可以做很多其它的事情,比如定义RSS,定义rel连接属性等,@import就只能加 ...

  9. [转载]jquery中attr和prop的区别

    在高版本的jquery引入prop方法后,什么时候该用prop?什么时候用attr?它们两个之间有什么区别?这些问题就出现了. 关于它们两个的区别,网上的答案很多.这里谈谈我的心得,我的心得很简单: ...

随机推荐

  1. linux下创建库函数

    来源: 在Linux下如何使用自己的库函数-riverok-ChinaUnix博客 http://blog.chinaunix.net/uid-21393885-id-88128.html 构建Lin ...

  2. DP:Bridging Signals(POJ 1631)

    不能交叉的引脚 (这一题的难度在于读题)题目大意:有一堆引脚(signals),左边一排,右边一排,左边从上到下,对应着连接右边的引脚(所有的引脚都被接上),现在引脚之间的连线有交叉,我们要桥接这些交 ...

  3. codeforces 474D.Flowers 解题报告

    题目链接:http://codeforces.com/problemset/problem/474/D 题目意思:Marmot 吃两种类型的花(实在难以置信呀--):red 或者 white,如果要吃 ...

  4. 【python-mysql】在ubuntu下安装python-mysql环境

    1.先安装mysql sudo apt-get install mysql-server apt-get isntall mysql-client sudo apt-get install libmy ...

  5. NEFU 1151 特殊的质数

    特殊的质数 Problem:1151 Time Limit:1000ms Memory Limit:65535K Description 如果一个数是质数,而且他在质数表中的编号也是质数,称为特殊的质 ...

  6. 使用apktool工具遇到could not decode arsc file的解决办法

    问题详情: 当前环境为 win7 64位  jdk1.7  apktool.jar(版本1.5.2)   apktool(版本windows-r05-ibot) 使用的反编译工具和apk文件为 反编译 ...

  7. 学习BigDecimal用法

    一.简介 Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算.双精度浮点型变量double可以处理16位有效数.在实际应用中,需要对更大或者更 ...

  8. ubuntu下eclipse无法启动问题

    添加-vm和对应参数 -vm/jdk安装目录/bin/java-startupplugins/org.eclipse.equinox.launcher_1.3.100.v20150511-1540.j ...

  9. 使用jQuery简单实现产品展示的图片左右滚动功能

    今天要做一个产品展示功能,由于产品比较多,一屏展示不完,所以想要做一个通过点击进行翻页的效果,在网上找了几个都不大好用,最后只能自己动手写了. 效果如下所示: 原理比较简单:将要滚动显示的区域的CSS ...

  10. express再学习

    对比spring,django,再学习express就有很多共通的地方啦... 看的书是一本小书,<express in action>,排版比较好. 昨天开始看,看了快四分之一啦... ...