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