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. SQL小技巧小知识

    1.[ ]的使用 当我们所要查的表是系统关键字或者表名中含有空格时,需要用[]括起来,例如新建了两个表,分别为user,user info,那么select * from user和select * ...

  2. svn 切换默认用户名

    2015年1月19日 15:37:30\ 原文: http://www.2cto.com/os/201307/229325.html linux svn切换用户   1. 临时切换   在所有命令下强 ...

  3. Hadoop 2.6.0 集群部署

    Hadoop的集群部署和单节点部署类似,配置文件不同,另外需要修改网络方面的配置 首先,准备3台虚拟机,系统为CentOS 6.6,其中一台为namenode 剩余两台为 datanode: 修改主机 ...

  4. Python多线程(3)——Queue模块

    Queue模块支持先进先出(FIFO)队列,支持多线程的访问,包括一个主要的类型(Queue)和两个异常类(exception classes). Python 2 中的Queue模块在Python ...

  5. poj 3080 Blue Jeans 解题报告

    题目链接:http://poj.org/problem?id=3080 该题属于字符串处理中的串模式匹配问题.题目要求我们:给出一个DNA碱基序列,输出最长的相同的碱基子序列.(保证在所有的序列中都有 ...

  6. 【读书笔记】读《高性能JavaScript》

    这本<高性能JavaScript>讲述了有关JavaScript性能优化的方方面面,主要围绕以下几个方面: 1> 加载顺序 2> 数据访问(如怎样的数据类型访问最快,怎样的作用 ...

  7. 何时使用hadoop fs、hadoop dfs与hdfs dfs命令(转)

    hadoop fs:使用面最广,可以操作任何文件系统. hadoop dfs与hdfs dfs:只能操作HDFS文件系统相关(包括与Local FS间的操作),前者已经Deprecated,一般使用后 ...

  8. 态势感知 > 技术运维问题

    http://blog.csdn.net/sanmaoljh/article/details/52670226 http://u.sanwen.net/subject/250516.html http ...

  9. Redis笔记(二)Redis的部署和启动

    Linux下Redis的部署和启动 下载安装介质 Redis官网地址:http://www.redis.io/目前最新版本是redis-3.0.3. 可以访问 http://download.redi ...

  10. hdu 2044:一只小蜜蜂...(水题,斐波那契数列)

    一只小蜜蜂... Time Limit: / MS (Java/Others) Memory Limit: / K (Java/Others) Total Submission(s): Accepte ...