在初始化 Erlang 主管进程时添加gen_event处理程序



我正在学习 Erlang,并且设法相对有效地找到答案并制定大多数问题的解决方案,但花了不可接受的时间解决这个问题:

将处理程序添加到由主管进程启动的gen_event模块的正确方法是什么?在我迄今为止的探索中,我已经能够设置流程、gen_servers、主管(gen_servers开始)和gen_event模块,但我试图实际向gen_event添加处理程序的所有内容都使我的主管进程崩溃——有时甚至是我的 shell!!

监控器模块:

-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行为的理解很差,但我对运行包含这些代码片段的代码的结果并不感到惊讶:

  • 它启动而不会崩溃
  • 它启动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 数量相比,我敢肯定,这算不了什么。

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

这意味着,如果要添加处理程序,鉴于您无法在主管中运行任意代码来执行此操作,最简单的方法是在gen_event进程准备就绪让主管生成一个同级进程。

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

最新更新