I'm learning Erlang, and am managing to find answers and work out solutions to most issues relatively efficiently, but have spent an unacceptable amount of time working out this one:
What is the correct way to add handlers to a gen_event module that is being being started by a supervisor process? In my exploration so far, I have been able to set up processes, gen_servers, supervisors (that start gen_servers), and gen_event modules, but everything I've attempted to actually add a handler to gen_event is crashing my supervisor process — and sometimes even my shell!!
The supervisor module:
-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]}.
… and some bits and pieces from the gen_event module, osc_event_server (hopefully the relevant ones!)
...
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};
...
As poorly as I understand the gen_event behaviour, I'm not much surprised by the result of running the code that includes these snippets:
- it launches without crashing
- it launches gen_event and produces a referenceable Pid for it, but never hits the
init
block of 'osc_event_server' - there are no actual event handlers attached to gen_event. Both "which_handlers" and attempts to send messages confirm that.
The two things that I'd like to incorporate:
- attach the specific event handlers (e.g., "send_osc") to my gen_event process… hopefully from within the supervisor code
- pass initialization arguments to the osc_event_server module; I want to be able at least to specify the port for the UDP server (rather than hard-wiring "8980") and provide the IP+port of a remote UDP server with which I want my process to communicate.
Thanks very much. Feel free to be critical of anything you see… e.g., my whole approach :) As much Erlang as I've come to understand at this point, it's nothing, I'm sure, compared to the amount of Erlang I misunderstand.