【问题标题】:Adding gen_event handlers while initializing an Erlang supervisor process在初始化 Erlang 主管进程时添加 gen_event 处理程序
【发布时间】:2019-09-09 09:22:47
【问题描述】:

我正在学习 Erlang,并且正在设法找到答案并相对有效地解决大多数问题,但花费了大量时间来解决这个问题:

将处理程序添加到主管进程正在启动的 gen_event 模块的正确方法是什么?到目前为止,在我的探索中,我已经能够设置进程、gen_servers、主管(启动 gen_servers)和 gen_event 模块,但是我尝试向 gen_event 实际添加处理程序的所有操作都使我的主管进程崩溃——有时甚至我的壳!!

主管模块:

-module(sup).
-behaviour(supervisor).

%% API
-export([start_link/0, init/1]).
-export([stop/0]).

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

init(_) ->
  EventServerSpec = #{
    id => osc_event_server,
    start => {gen_event, start_link, [{local, osc_server}]},
    modules => dynamic
  },
  ChildSpecList = [EventServerSpec, child(frequency), child(bkpt_server)],
  SupFlags = #{strategy => rest_for_one,
    intensity => 2, period => 3600},
  {ok, {SupFlags, ChildSpecList}}.

child(Module) ->
  #{id => Module,
    start => {Module, start_link, []},
    restart => permanent,
    shutdown => 2000,
    type => worker,
    modules => [Module]}.

...以及来自 gen_event 模块 osc_event_server 的一些点点滴滴(希望是相关的!)

...
init([]) ->
  {ok, Socket} = gen_udp:open(8980, [binary, {active, false}]),
  {ok, #{socket => Socket, target_port => get_target_port()}}.

...
handle_event({send_osc, Path, Data}, State) ->
  TargetPort = maps:get(target_port, State),
  Socket = maps:get(socket, State),
  sendMessage(Socket, TargetPort, Path, Data),
  {ok, State};
...

尽管我对 gen_event 的行为了解甚少,但我对运行包含这些 sn-ps 的代码的结果并不感到惊讶:

  • 它启动时不会崩溃
  • 它启动 gen_event 并为其生成一个可引用的 Pid,但从未命中“osc_event_server”的init
  • gen_event 没有附加实际的事件处理程序。 “which_handlers”和发送消息的尝试都证实了这一点。

我想合并的两件事:

  1. 将特定的事件处理程序(例如,“send_osc”)附加到我的 gen_event 进程中……希望是在主管代码中
  2. 将初始化参数传递给 osc_event_server 模块;我希望至少能够为 UDP 服务器指定端口(而不是硬连线“8980”),并提供我希望我的进程与之通信的远程 UDP 服务器的 IP+端口。

非常感谢。随意批评你看到的任何东西……例如,我的整个方法 :) 就我在这一点上理解的 Erlang 而言,我敢肯定,与我误解的 Erlang 的数量相比,它什么都不是.

【问题讨论】:

    标签: erlang erlang-supervisor gen-event


    【解决方案1】:

    您应该将gen_event 进程视为存在于您的节点上的一种服务。通常你会给它一个名字,然后用这个名字和它说话。在您这样做之前,它只是一段独立的代码。

    这意味着如果您想添加处理程序,鉴于您不能在主管中运行任意代码来执行此操作,最简单的方法是让您的主管在之后生成一个兄弟进程 em>gen_event 进程已准备就绪。

    将新的同级标记为transienttemporary,让它有点gen_serversupervisor_bridge worker,并给它gen_event 的名称和处理程序。小工人应该添加处理程序。然后它可以以normal 的原因关闭,或者如果需要,监督处理程序以防它们崩溃以重新添加它们。

    【讨论】:

    • @IGTA:我赞成并怀疑这是一个很好的解决方案,但不幸的是还没有时间尝试它。我将能够在接下来的几天内进行测试,不用担心,当(我怀疑)我可以用我自己的结果来支持它时,我会标记为已接受的解决方案。
    猜你喜欢
    • 2011-04-15
    • 2021-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-29
    • 2011-07-11
    • 1970-01-01
    相关资源
    最近更新 更多