Erlang在线运行

版本:

所属目录
点击了解高性能代码运行API
运行结果
教程手册
代码仓库
极速运行
终端运行
图形+终端

                        
以下是用户最新保存的代码
[更多]
显示目录

错误处理



学习嵌入式的绝佳套件,esp8266开源小电视成品,比自己去买开发板+屏幕还要便宜,省去了焊接不当搞坏的风险。 蜂鸣版+触控升级仅36元,更强的硬件、价格全网最低。

点击购买 固件广场

Erlang错误处理

在讨论监督与错误处理细节之前,让我们先一起来看一下 Erlang 进程的终止过程,或者说 Erlang 的术语 exit。

进程执行 exit(normal) 结束或者运行完所有的代码而结束都被认为是进程的正常(normal)终止。

进程因为触发运行时错误(例如,除零、错误匹配、调用不存在了函数等)而终止被称之为异常终止。进程执行 exit(Reason) (注意此处的 Reason 是除 normal 以外的值)终止也被称之为异常终止。

一个 Erlang 进程可以与其它 Erlang 进程建立连接。如果一个进程调用 link(Other_Pid),那么它就在其自己与 Othre_Pid 进程之间创建了一个双向连接。当一个进程结束时,它会发送信号至所有与之有连接的进程。

这个信号携带着进程的进程标识符以及进程结束的原因信息。

进程收到进程正常退出的信号时默认情况下是直接忽略它。

但是,如果进程收到的是异常终止的信号,则默认动作为:

  • 接收到异常终止信号的进程忽略消息队列中的所有消息

  • 杀死自己

  • 将相同的错误消息传递给连接到它的所有进程。

所以,你可以使用连接的方式把同一事务的所有进程连接起来。如果其中一个进程异常终止,事务中所有进程都会被杀死。正是因为在实际生产过程中,常常有创建进程同时与之建立连接的需求,所以存在这样一个内置函数 spawn_link,与 spawn 不同之处在于,它创建一个新进程同时在新进程与创建者之间建立连接。

下面给出了 ping pong 示例子另外一种实现方法,它通过连接终止 "pong" 进程:

-module(tut20).

-export([start/1,  ping/2, pong/0]).

ping(N, Pong_Pid) ->
    link(Pong_Pid),
    ping1(N, Pong_Pid).

ping1(0, _) ->
    exit(ping);

ping1(N, Pong_Pid) ->
    Pong_Pid ! {ping, self()},
    receive
        pong ->
            io:format("Ping received pong~n", [])
    end,
    ping1(N - 1, Pong_Pid).

pong() ->
    receive
        {ping, Ping_PID} ->
            io:format("Pong received ping~n", []),
            Ping_PID ! pong,
            pong()
    end.

start(Ping_Node) ->
    PongPID = spawn(tut20, pong, []),
    spawn(Ping_Node, tut20, ping, [3, PongPID]).
(s1@bill)3> tut20:start(s2@kosken).
Pong received ping
<3820.41.0>
Ping received pong
Pong received ping
Ping received pong
Pong received ping
Ping received pong

与前面的代码一样,ping pong 程序的两个进程仍然都是在 start/1 函数中创建的,“ping”进程在单独的结点上建立的。但是这里做了一些小的改动,用到了内置函数 link。“Ping” 结束时调用 exit(ping) ,使得一个终止信号传递给 “pong” 进程,从而导致 “pong” 进程终止。

也可以修改进程收到异常终止信号时的默认行为,避免进程被杀死。即,把所有的信号都转变为一般的消息添加到信号接收进程的消息队列中,消息的格式为 {'EXIT',FromPID,Reason}。我们可以通过如下的代码来设置:

process_flag(trap_exit, true)

还有其它可以用的进程标志,可参阅 erlang (3)。标准用户程序一般不需要改变进程对于信号的默认处理行为,但是对于 OTP 中的管理程序这个接口还是很有必要的。下面修改了 ping pong 程序来打印输出进程退出时的信息:

-module(tut21).

-export([start/1,  ping/2, pong/0]).

ping(N, Pong_Pid) ->
    link(Pong_Pid), 
    ping1(N, Pong_Pid).

ping1(0, _) ->
    exit(ping);

ping1(N, Pong_Pid) ->
    Pong_Pid ! {ping, self()},
    receive
        pong ->
            io:format("Ping received pong~n", [])
    end,
    ping1(N - 1, Pong_Pid).

pong() ->
    process_flag(trap_exit, true), 
    pong1().

pong1() ->
    receive
        {ping, Ping_PID} ->
            io:format("Pong received ping~n", []),
            Ping_PID ! pong,
            pong1();
        {'EXIT', From, Reason} ->
            io:format("pong exiting, got ~p~n", [{'EXIT', From, Reason}])
    end.

start(Ping_Node) ->
    PongPID = spawn(tut21, pong, []),
    spawn(Ping_Node, tut21, ping, [3, PongPID]).
(s1@bill)1> tut21:start(s2@gollum).
<3820.39.0>
Pong received ping
Ping received pong
Pong received ping
Ping received pong
Pong received ping
Ping received pong
pong exiting, got {'EXIT',<3820.39.0>,ping}
由JSRUN为你提供的Erlang在线运行、在线编译工具
        JSRUN提供的Erlang 在线运行,Erlang 在线运行工具,基于linux操作系统环境提供线上编译和线上运行,具有运行快速,运行结果与常用开发、生产环境保持一致的特点。
yout