gen系列init使用注意事项
原创文章,转载请注明: 转载自系统技术非业余研究
本文链接地址: gen系列init使用注意事项
gen*都需要callback模块提供一个init模块, 在这个模块里面做相应的初始化操作.
我们以gen_server为例子. 当我们调用gen_server:start_link的时候, 底层会委托proc_lib来启动新的进程同时调用我们的init函数进行初始化. 同时gen系列会同步等待新进程初始化完毕, 才接着往下执行.
我们看下文档:
gen_server:start_link(ServerName, Module, Args, Options) -> Result
The gen_server process calls Module:init/1 to initialize. To ensure a synchronized start-up procedure, start_link/3,4 does not return until Module:init/1 has returned.
我们会经常误解这个行为, 以为start是马上返回的, otp团队之前也修正httpc的一个这类问题的bug.
所以我们在init的时候, 尽可能的做些简单的工作. 如果需要做费时的操作, 那么可以先让一条消息, 放到消息队列去, 让init马上返回. 这时候兵分二路, 调用进程可以继续往下执行, 费时操作也在稍后被调用.
而且gen*系列一旦启动起来, 如果该进程不幸发生意外崩溃, proc_lib会负责记录当时的现场和原因, 非常有助于诊断.
我们演示下这个问题:
root@ubuntu:~# cat tg.erl
-module(tg).
-behaviour(gen_server).
%% API
-export([start/0]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
-record(state, {}).
-define(SERVER, ?MODULE).
start() ->
gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
init([]) ->
io:format("init pid ~p~n", [self()]),
%% sleep
receive
after 3000 ->
cont
end,
erlang:send_after(0, self(), crash_me),
{ok, #state{}}.
handle_call(_Request, _From, State) ->
Reply = ok,
{reply, Reply, State}.
handle_cast(_Msg, State) ->
{noreply, State}.
handle_info(crash_me, State) ->
% do some hard work
% crash me
exit(crash_me),
{noreply, State};
handle_info(_Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
root@ubuntu:~# erl
Erlang R13B04 (erts-5.7.5) [source] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]
Eshell V5.7.5 (abort with ^G)
1> self().
<0.36.0>
2> timer:tc(tg, start, []).
init pid <0.34.0>
{3003583,{ok,<0.34.0>}}
2>
=ERROR REPORT==== 8-Apr-2010::16:20:09 ===
** Generic server tg terminating
** Last message in was crash_me
** When Server state == {state}
** Reason for termination ==
** crash_me
** exception error: crash_me
2>
1. 我们个tg:start启动了3003毫秒, 证明这是同步调用.
2. init是在新进程里面执行的
3. 我们的费时间操作用erlang:send_after发起
4. 一旦发生crash我们有记录在案.
收工!
Post Footer automatically generated by wp-posturl plugin for wordpress.
Recent Comments