[erlang-questions] gen_event:add_sup_handler... correct usage?

Scott Lystig Fritchie fritchie@REDACTED
Tue Jul 28 20:14:35 CEST 2009


Steve Davis <steven.charles.davis@REDACTED> wrote:

sd> I have boot-time logging for a server that needs to start before
sd> anything really happens, i.e. **before the main supervisor is kicked
sd> off by application:start(my_server)**.

Looking at your code snippet, I think I agree that's what'll happen.
Mostly.

sd> Despite this requirement, I still need the error_logger process to
sd> supervise my gen_event handler.

Perhaps it'll be helpful to use the Erlang flavor of the journalist's
rule, "Follow the money."  Instead, it's "follow the process structure".
In such pursuits, the "appmon" GUI app is an invaluable visualization
tool.  The WebAppMon tool within the "webtool" app is a close second.(*)

Adding io:format() calls to my_server_app:start/2 and :stop/1 and all
those other callback also helps figure out what's running where, e.g.

    start(Type, Args) ->
        io:format("~s: start() in pid ~p\n", [?MODULE, self()]),
        ...

The error_logger process(**) doesn't appear (in R13B01) to be part of
the kernel's supervisor hierarchy.  Instead it claims to be spawned
directly by the <0.1.0> process, very very early in the VM's startup
phase.  Try process_info(whereis(error_logger)).  Any callback you
register using gen_event:add_sup_handler(error_logger, ...) will be
executed by the error_logger process.

If one of your gen_event callbacks throws an exception of some sort, the
gen_event framework will silently remove your callback module from its
list ... so your use of gen_event:add_sup_handler/3 is a good idea.  If
your module has a bug, you'll be informed about it...

... except that the link that's created between
gen_event:add_sup_handler/3's caller and the gen_event server will be
the process that's executing my_server_sup:start().  You may not want
that.  Add an intentional bug to my_logger_h, trigger the bug, and see
what other process(es) dies as a result.(***)

sd> ..while all of this "works", I have concerns about the OTP-ness of
sd> doing this, and also a nagging feeling that the fact that
sd> application process is essentially the "supervisor" that's passed to
sd> error_logger, not the supervisor process itself.

You probably don't want to use the gen_event:which_handlers() method of
deciding whether or not to call supervisor:start_link().  If I'm not
mistaken, this sequence of commands:

    application:start(my_server_app).
    application:stop(my_server_app).
    application:start(my_server_app).

... won't start your app's supervisor the second time around.  Stopping
your app won't automagically remove the my_logger_h callback module from
the error_logger server.  (Unless you have removal code explicitly in
my_server_app:stop/1.)

As for "... 'supervisor' that's passed to error_logger...", hopefully
it's clear that your nagging feeling doesn't make sense.  Or, at least
it doesn't to me, sorry.  :-)

-Scott

(*) In OTP's HTML documentation, see the "Tool Applications" section,
"webtool" app, "User's Guide" doc.

(**) In OTP's HTML documentation, see "Basic Applications" section,
"kernel" app, "error_logger" doc.

(***) If you don't have the OTP SASL app running, you probably should.
Otherwise, many errors inside the VM are invisible.  Use
application:start(sasl) or start the sasl app in your .boot scheme.

  HA HA HA!  I followed my own advice and tried it: added a exit(bogus)
  call to my error handler's handle_event/2 callback.

  The supervisor silently consumes the {'EXIT', ...} message.  Oops.
  Now *I* need to do some refactoring work!

  HA HA part 2.  My custom error logger is critical.  If there's a
  callback bug, I need to know about it ASAP.  gen_event will silently
  drop errors, so I should use gen_event:add_sup_handler/3 to let
  someone in the world know about the error.  Now I discover that the
  process death that I was expecting in such a doomsday situation
  ... doesn't happen.  Cool!


More information about the erlang-questions mailing list