今天写代码的发现,关闭app的时候,监控树下的某个进程terminate函数没执行,所以有以下备忘记录

1 erlang:process_flag(trap_exit,true).

When trap_exit is set to true, exit signals arriving to a process are converted to {'EXIT', From, Reason} messages, which can be received as ordinary messages. If trap_exit is set to false, the process exits if it receives an exit signal other than normal and the exit signal is propagated to its linked processes. Application processes are normally not to trap exits.

可以理解为捕获退出信号:如果trap_exit设置为true,该进程接收到的退出信号被转为{'EXIT', From, Reason}格式的消息;trap_exit为false,如果接收到除normal之外的退出信号,则该进程退出并将退出信号传递给跟它连接的进程。

2 erlang:exit(Pid, Reason)

Sends an exit signal with exit reason Reason to the process or port identified by Pid.

The following behavior applies if Reason is any term, except normal or kill:

  • If Pid is not trapping exits, Pid itself exits with exit reason Reason.

  • If Pid is trapping exits, the exit signal is transformed into a message{'EXIT', From, Reason} and delivered to the message queue of Pid.

  • From is the process identifier of the process that sent the exit signal. See also process_flag/2.

If Reason is the atom normal, Pid does not exit. If it is trapping exits, the exit signal is transformed into a message {'EXIT', From, normal} and delivered to its message queue.

If Reason is the atom kill, that is, if exit(Pid, kill) is called, an untrappable exit signal is sent to Pid, which unconditionally exits with exit reason killed.

大概理解为:

A 如果退出Reason是除了normal和kill之外的任意term:

1:如果trap_exit=false Pid进程退出

2:如果trap_exit=true Pid进程捕获退出信号,退出信号转化格式为{'EXIT', From, Reason}的一条普通消息

B

1:如果Reason=normal, pid进程不会退出。 如果trap_exit=true Pid进程捕获退出信号,退出信号转化格式为{'EXIT', From, Reason}的一条普通消息

2:如果Reason=kill,pid进程无条件退出,无论是否设置trap_exit=true;也就是说,trap_exit无法捕获kill的退出信号。

3 terminate:进程退出前的数据保存操作可以在这里进行。

一般情况下,自己写的进程停止操作都是如下:

stop(Pid) when is_pid(Pid) ->
    gen_server:call(Pid, stop).

handle_call(stop, State) ->
    {reply, stop, normal, State};

但是,监控树下的进程停止操作是执行erlang:exit(Pid,Reason)的,具体代码可以看一下:supervisor.erl的源码

%%-----------------------------------------------------------------
%% Func: terminate_children/2
%% Args: Children = [child_rec()] in termination order
%%       SupName = {local, atom()} | {global, atom()} | {pid(),Mod}
%% Returns: NChildren = [child_rec()] in
%%          startup order (reversed termination order)
%%-----------------------------------------------------------------
terminate_children(Children, SupName) ->terminate_children(Children, SupName, []).%% Temporary children should not be restarted and thus should
%% be skipped when building the list of terminated children, although
%% we do want them to be shut down as many functions from this module
%% use this function to just clear everything.
terminate_children([Child = #child{restart_type=temporary} | Children], SupName, Res) ->_ = do_terminate(Child, SupName), % 顺序停止子进程terminate_children(Children, SupName, Res);
terminate_children([Child | Children], SupName, Res) ->NChild = do_terminate(Child, SupName),terminate_children(Children, SupName, [NChild | Res]);
terminate_children([], _SupName, Res) ->Res.do_terminate(Child, SupName) when is_pid(Child#child.pid) ->case shutdown(Child#child.pid, Child#child.shutdown) ofok ->ok;{error, normal} when Child#child.restart_type =/= permanent ->ok;{error, OtherReason} ->report_error(shutdown_error, OtherReason, Child, SupName)end,Child#child{pid = undefined};
do_terminate(Child, _SupName) ->Child#child{pid = undefined}.%%-----------------------------------------------------------------
%% Shutdowns a child. We must check the EXIT value
%% of the child, because it might have died with another reason than
%% the wanted. In that case we want to report the error. We put a
%% monitor on the child an check for the 'DOWN' message instead of
%% checking for the 'EXIT' message, because if we check the 'EXIT'
%% message a "naughty" child, who does unlink(Sup), could hang the
%% supervisor.
%% Returns: ok | {error, OtherReason}  (this should be reported)
%%-----------------------------------------------------------------
shutdown(Pid, brutal_kill) -> %如果子进程的重启策略是brutal_kill case monitor_child(Pid) ofok ->exit(Pid, kill), % 则子进程无法执行terminate函数,因为kill退出信号无法捕获为{'EXIT', From, Reason}receive{'DOWN', _MRef, process, Pid, killed} ->ok;{'DOWN', _MRef, process, Pid, OtherReason} ->{error, OtherReason}end;{error, Reason} ->      {error, Reason}end;
shutdown(Pid, Time) ->case monitor_child(Pid) ofok ->exit(Pid, shutdown), %% Try to shutdown gracefully % 其他重启策略的子进程退出信号receive {'DOWN', _MRef, process, Pid, shutdown} ->ok;{'DOWN', _MRef, process, Pid, OtherReason} ->{error, OtherReason}after Time ->exit(Pid, kill),  %% Force termination.receive{'DOWN', _MRef, process, Pid, OtherReason} ->{error, OtherReason}endend;{error, Reason} ->      {error, Reason}end.%% Help function to shutdown/2 switches from link to monitor approach
monitor_child(Pid) ->%% Do the monitor operation first so that if the child dies %% before the monitoring is done causing a 'DOWN'-message with%% reason noproc, we will get the real reason in the 'EXIT'-message%% unless a naughty child has already done unlink...erlang:monitor(process, Pid),unlink(Pid),receive%% If the child dies before the unlik we must empty%% the mail-box of the 'EXIT'-message and the 'DOWN'-message.{'EXIT', Pid, Reason} -> receive {'DOWN', _, process, Pid, _} ->{error, Reason}endafter 0 -> %% If a naughty child did unlink and the child dies before%% monitor the result will be that shutdown/2 receives a %% 'DOWN'-message with reason noproc.%% If the child should die after the unlink there%% will be a 'DOWN'-message with a correct reason%% that will be handled in shutdown/2. ok   end.

为什么trap_exit=true,进程退出之前会跑到terminate函数呢?看一下gen_server.erl的源码:

decode_msg(Msg, Parent, Name, State, Mod, Time, HibernateAfterTimeout, Debug, Hib) ->case Msg of{system, From, Req} ->sys:handle_system_msg(Req, From, Parent, ?MODULE, Debug,[Name, State, Mod, Time, HibernateAfterTimeout], Hib);{'EXIT', Parent, Reason} ->terminate(Reason, ?STACKTRACE(), Name, undefined, Msg, Mod, State, Debug);_Msg when Debug =:= [] ->handle_msg(Msg, Parent, Name, State, Mod, HibernateAfterTimeout);_Msg ->Debug1 = sys:handle_debug(Debug, fun print_event/3,Name, {in, Msg}),handle_msg(Msg, Parent, Name, State, Mod, HibernateAfterTimeout, Debug1)end.

trap_exit与terminate相关推荐

  1. erlang mysql:start_link_Erlang OTP之terminate 深入分析

    gen_server进程设置了trap_exit为true(process_flag(trap_exit, true)),则在该进程结束时会自动调用terminate.利用这个功能,我们可以在进程退出 ...

  2. iOS开发socket程序被SIGPIPE信号Terminate的问题

    以前在iphone上写socket的程序的时候,如果尝试send到一个disconnected socket上,就会让底层抛出一个SIGPIPE信号. client端通过 pipe 发送信息到serv ...

  3. subprocess 的 kill()/terminate() 问题

    虽然 python2.6中的subprocess模块增加了  kill()  terminate()  来控制子进程退出 但是在实际的使用过程中会发现 如果子进程并不是自己退出,而是调用 kill() ...

  4. python 结束进程 terminate_python – 如果已存在浏览器窗口,则process.terminate()不适用于chrome / firefox子进程...

    这不是python问题,并且您的代码不包含错误.这是浏览器的问题.使用–new-window启动firefox或chrome的可执行文件时,将在浏览器的现有实例中打开一个新窗口. 换句话说,您刚刚开始 ...

  5. 图像识别工程师 VS The application has requested the Runtime to terminate it in an unusual way.

    图像处理开发需求.图像处理接私活挣零花钱,请加微信/QQ 2487872782 图像处理开发资料.图像处理技术交流请加QQ群,群号 271891601 The application has requ ...

  6. pycharm点击右上角退出程序时terminate和disconnect区别?(别用disconnect)

    如图,pycharm点右上角×退出时会提示,选择terminate还是disconnect,两个有啥区别呢? 经过亲测 点击terminate时,python会终止python程序,然后再退出pych ...

  7. python 多进程 multiprocessing 进程池pool报错 in join assert self._state in (CLOSE, TERMINATE) AssertionError

    原因:pool.close()关闭进程池,不再接受新的任务.join之前必须加上close(),否则会报错 在进程池操作join()时.在前面加上pool.close()即可 参考文章1:Python ...

  8. This application has requested the Runtime to terminate it in an unusual way. Please contact the app

    在做机器学习实战第九章的实验,使用Tkinter和matplotlib绘制回归树和模型树时,代码没有问题但是抛出了如下错误 ValueError: Masked arrays must be 1-D ...

  9. XGB模型训练报错 terminate called after throwing an instance of ‘std::bad_alloc‘ what()

    背景:需要做XGB模型增量训练,但是因为一些原因没有得到原来的XGB模型,只有dump文件. XGB模型的dump文件是它的树结构存储为一个相对人类好理解的模型文件,但并不能被重新加载进XGB进行增量 ...

最新文章

  1. 真的有人在偷听我们讲话么?
  2. 记录避免一些逻辑问题的过程
  3. STM32的晶振脚(OSCIN和OSCOUT)当成普通IO来使用
  4. python3用什么系统好_学python用什么系统【怎么学好python】
  5. 8. Leetcode 26. 删除有序数组中的重复项 (数组-同向双指针-快慢指针)
  6. 无源的nfc加传感_基于ON Semiconductor SPS无源温度标签,应用于冷链运输的 UHF 标签读取器方案...
  7. JS 三级联动 下拉列表
  8. java 线程 单例_多线程单例模式
  9. JavaEE实战班第十五天
  10. Zabbix对接AD域
  11. OC语言--OC语言基础、类
  12. 关于华为AR/HUAWEI AR Engine
  13. python中matplotlib画图导入到word中如何保证分辨率
  14. Timus 1104. Don’t Ask Woman about Her Age
  15. 机械臂速成小指南(六):步进电机驱动器
  16. oracle安装使用
  17. js控制元素显示与否JS控制HTML元素的显示和隐藏
  18. java基于springboot二手物品交易网站
  19. 推特推 Periscope 垂死挣扎还是扭转乾坤
  20. 886_AUTOSAR_TPS_GenericStructureTemplate33_变体处理例子

热门文章

  1. pwrite,pread
  2. css给长方形画对角线
  3. 移动端H5 富文本编辑器
  4. qchart 怎么点击一下 出一条线_新手修眉教程:初学者怎么自己修眉毛?简单三步图解让你快速学会...
  5. 蓝桥云课linux入门3:用户及文件权限管理
  6. 目前工业机器人可以替代哪些工种或者哪些从业人员的工作?
  7. 线程和进程 并发和并行
  8. matlab最小费用最大流函数,最小费用最大流算法通用Matlab程序
  9. 几种常见加密算法初窥及如何选用加密算法
  10. Java基础复习-常用类