[erlang-questions] gen_server cleanup handling

Bernard Duggan bernie@REDACTED
Thu May 13 02:29:01 CEST 2010


Hi Essien,

On 13/05/10 09:29, Essien Essien wrote:
> - You want a gen_server to spawn a worker, and both should be
> restarted if any of the other goes down... What to do is this (forgive
> the ascii art!):
>
>            [root_sup] % root_sup should use a one_for_all restart strategy
>                   |
> [gen_server, worker_sup]  % worker_sup should be simple_one_for_one,
> MaxR = 0, MaxT=10
>                          |
>                     [worker(s)] % this should be a permanent child.
>
> To complete the above, establish a monitor (erlang:monitor/2) b/w
> gen_server and worker pid after the supervisor:start_child(worker_sup,
> []) call.
>
> The above tree will work as you want, though it introduces root_sup
> and worker_sup.
>
> - If gen_server crashes, worker_sup will also crash and restart, thus
> taking down and restart worker(s)?
>
> - Since the gen_server is monitoring the worker, it will recieve the
> 'DOWN' message when the worker goes down and you can then {stop,
> Reason} from the gen_server. Also, the worker restart frequency is
> zero times in 10 seconds, so it will not be restarted by its
> supervisor, untill the gen_server has died also, taken them all down
> and they're all restarted by the root_sup.
>    
Yeah, that arrangement was one I considered, I'm just not sure that it's 
better than just doing a straight spawn_link, and catching and 
propagating the non-normal 'EXIT' message from the worker.  If you have 
to catch and propagate the 'DOWN', the only difference in terms of code 
size is the extra supervisor and the explicit monitoring call which both 
count against that plan.  (Not, of course, that code size should be the 
sole determining factor, but trying to avoid unnecessary code was what 
got me onto this train of thought in the first place).  I do make use of 
monitoring elsewhere, though, and I think you're quite right that it's 
underused at the expense of linking.
> I have tried it out, and it works nicely too.
>
> The question i have for you though, is:
>
> Does every gen_server just spawn a single worker process or can it
> spawn multiple workers? If multiple, what happens to the rest if one
> dies? (I'm assuming the answer to this is one gen_server, one worker)
>    
You assume correctly.  I have a gen_server that needs to be quite 
responsive.  Occasionally it also kicks off a single longer-running 
operation which can be done in parallel, but is only transient.

You know, it's just occurred to me that the "easy" and (probably) 
"right" solution for this particular case is to have the worker as "just 
another gen_server" under a one_for_all supervisor with the original 
gen_server.  It can then sit idle quite happily until required - I don't 
know why I had it fixed in my head that it had to be spawned only when 
it was needed and terminated when it was done.  Duh.

Thanks for your thoughtful response :)

Cheers,

Bernard



More information about the erlang-questions mailing list