2013-10-14 66 views
6

應用程序時,我已經創建使用poolboy幾乎空工人簡單的應用程序,但是當我停止應用程序,我看到啤酒印刷以下錯誤:奇怪的錯誤消息,停止使用啤酒和poolboy

10:50:26.363 [error] Supervisor {<0.236.0>,poolboy_sup} had child test_worker started with test_worker:start_link([]) at undefined exit with reason shutdown in context shutdown_error 

是什麼原因導致這個錯誤,我該如何解決這個問題?

主管:

-module(test_sup). 
-behaviour(supervisor). 
-export([start_link/0, init/1]). 


start_link() -> 
    supervisor:start_link({local, ?MODULE}, ?MODULE, []). 

init([]) -> 
    ChildSpecs = [pool_spec()], 
    {ok, {{one_for_one, 1000, 3600}, ChildSpecs}}. 

pool_spec() -> 
    Name = test_pool, 
    PoolArgs = [{name, {local, Name}}, 
       {worker_module, test_worker}, 
       {size, 10}, 
       {max_overflow, 20}], 
    poolboy:child_spec(Name, PoolArgs, []). 

工人:

-module(test_worker). 
-behaviour(gen_server). 
-behaviour(poolboy_worker). 

-export([start_link/1]). 
-export([init/1, handle_call/3, handle_cast/2, 
    handle_info/2, terminate/2, code_change/3]). 

-record(state, {}). 

start_link([]) -> 
    gen_server:start_link(?MODULE, [], []). 

init([]) -> 
    {ok, #state{}}. 

handle_call(_Request, _From, State) -> 
    {reply, _Reply = ok, State}. 

handle_cast(_Msg, State) -> 
    {noreply, State}. 

handle_info(_Info, State) -> 
    {noreply, State}. 

terminate(_Reason, _State) -> 
    ok. 

code_change(_OldVsn, State, _Extra) -> 
    {ok, State}. 

應用程序的其餘部分是相當標準。

二郎:R16B02

Poolboy:1.0.1

拉格:在寫的問題(822062478a223313dce30e5a45e30a50a4b7dc4e)

+0

我從來沒有聽說過poolboy,但從他們的網站上的例子來看,你似乎需要在worker中實現'poolboy_worker'行爲,不是嗎? – akonsu

+0

我用-behaviour(poolboy_worker)試過 - 沒有幫助。更新後的源代碼。 –

+0

我也遇到這個問題;看起來好像它已經在Poolboy中修復了,保羅的建議是刪除鏈接讓我有點煩惱... – Seb

回答

5

您所看到的錯誤實際上是不是一個錯誤,而是由lager產生錯誤報告。此報告似乎是由Poolboy中的一個錯誤引起的。

您可以:

  • 修復bug和提交補丁poolboy開發商。
  • 安全地忽略報告。
  • 退出時手動終止您的員工。

當您停止OTP應用程序時應該發生的情況是監督樹用於終止所有進程,最好是優雅的。默認的做法是發送監督進程一個shutdown信號,如果這個信號在一段時間後不起作用,就會殘忍地殺死它們。當一切順利時,你永遠不會得到任何報告。

有兩種二郎微妙之處理解錯誤:

  1. 進程可以是linked,這意味着,當一個進程異常終止時(即,具有比normal以外的原因),所有鏈接的過程被終止與同樣的道理。這個原始是OTP監督的基礎。
  2. 進程可以trap exit signals(或陷阱離開),這意味着其接收退出信號作爲常規消息而不是被終止(包括normal這不會終止它,但不包括kill這將無條件終止它)。

鏈接結合陷印出口通常用於監視進程的終止,並在監視進程終止時終止監視進程的額外好處。例如,如果主管終止,其子女將被終止。一個不對稱的monitor機制也存在。

在這裏,您的主管(執行test_sup行爲)終止,原因爲shutdown,因爲它應該是。主管行爲實際上會陷入退出狀態,當它收到shutdown信號時,它會根據其關機策略嘗試終止其子女。在這裏,您使用默認策略,即將孩子shutdown信號作爲第一次嘗試。因此,您的主管將shutdown信號發送給其唯一的孩子。

Poolboy在這裏介紹它的魔力,而你的主管的孩子實際上是一個gen_serverpoolboy回調模塊。它應該關閉游泳池並優雅地終止。

此模塊鏈接到pool supervisor,但也鏈接到the workers。這個令人驚訝的實現選擇可能是因爲游泳池崩潰(poolboy gen_server)將終止工人。但是,這是錯誤的來源,而非對稱顯示器可能更有意義。由於主管已經聯繫到poolboy gen_server,因此終止poolboy進程最終將導致工人終止。

鏈接到工作人員的結果是,他們也得到shutdown退出信號,該信號最初指向poolboy進程。他們被終止。由於工作人員的主管沒有發送信號,因此該終止被認爲是不正常的(執行poolboy_sup回調)。因此,主管報告關閉,這是由lager在這裏記錄的。

poolboytraps exits不能阻止shutdown信號傳播的事實。該進程在收到信號時不會立即終止,而是將其作爲消息接收。 gen_server截取此消息,調用terminate/2回調函數,然後terminates with shutdown,最終將信號傳播到所有鏈接的進程。

如果避免到link to workers不是一個選項,解決此錯誤的一種方法是取消鏈接terminate handler中的所有工作人員。

0

你如何阻止應用程序的時間從主最新版本?也許主管應該有停止/ 1功能?例如,看到

http://www.erlang.org/doc/apps/kernel/application.html#stop-1

+0

我只是在做應用程序:stop(test_app)。 –

+0

如果test_app_sup.erl和test_app.erl沒有停止/ 1功能,那可能是問題所在。 –