[erlang-questions] Shutting down a gen_server in a supervision tree

Jeroen Koops <>
Fri Jun 5 09:47:57 CEST 2009


Hi Torben,

> 1. Why is it important for your to keep the network connection happy when
you are shutting down?

For some protocols, it is important that the connection is shut down in an
orderly manner, instead of just closing the TCP connection. As an example,
closing an SMPP connection involves first waiting for responses to
oustanding requests, sending a logout PDU and waiting for a logout response
PDU.
Failing to wait for responses to outstanding requests means you don't know
if certain requests have been accepted by the server. Failing to send the
logout PDU may lead to the server not realizing that you have logged out and
rejecting new login attempts for some time.

> 2. When you are being told to die you should only clean up your resources.
Pending messages should not be a concern. If the requests are so important
you should consider spawning a separate process for them.

That's a possibility, but not what I want - I want
application:stop(my_application) to finish only after everything has been
shut down cleanly. Leaving a new process hanging around handling closing the
connection is not really an option.

> 3. Your problem sounds more like a gen_fsm problem where you should
introduce a shutting_down state that collects responeses or times out.

May gen_fsm is more fitting here than a gen_server, but I don't think it
will make a huge difference. If I create an extra shutting_down state (which
can be done just as easy with a gen_server by setting some flag in the
gen_server's state, by the way), someone will still have to trigger this
state.

> 4. My code style is normally to let the supervisors help out with starting
of processes and try to restart according to the policies. Shutting down is
normally something for another worker process to instruct us to do.

So you don't use application:stop/1 for this?

Regards,

Jeroen



On Thu, Jun 4, 2009 at 10:00 PM, Torben Hoffmann <
> wrote:

> Some questions/observations to get the right context:
>
>    1. Why is it important for your to keep the network connection happy
>    when you are shutting down?
>    2. When you are being told to die you should only clean up your
>    resources. Pending messages should not be a concern. If the requests are so
>    important you should consider spawning a separate process for them.
>    3. Your problem sounds more like a gen_fsm problem where you should
>    introduce a shutting_down state that collects responeses or times out.
>    4. My code style is normally to let the supervisors help out with
>    starting of processes and try to restart according to the policies. Shutting
>    down is normally something for another worker process to instruct us to do.
>
> Sorry if I did not get my interpretation of your problem right .
>
> Cheers,
> Torben
>
>
> On Thu, Jun 4, 2009 at 2:11 PM, Jeroen Koops <> wrote:
>
>> Hi all,
>>
>> I'm puzzled by the following: I have a gen_server that is part of an
>> application. The gen_server maintains a network connection using some
>> request/response protocol. When shutting down, it is important that the
>> gen_server wait for responses to all outstanding requests (or timeouts)
>> before terminating. To realize this, I would like the gen_server to keep
>> operating normally - that is, being able to handle_call/3, handle_cast/2
>> and
>> handle_info/2 - between the time the supervisor sends the { 'EXIT',
>> shutdown
>> } message, and the moment the gen_server really terminates.
>>
>> I thought this was simply a matter of:
>> - Specifying some integer value > 0 as the Shutdown value in the
>> supervisor's child-specification
>> - Setting trap_exit to true in the gen_server's init function
>> - Handling the { 'EXIT', shutdown } message from the supervisor in the
>> handle_info/2 function. The only thing this would do is setting some flag
>> in
>> the gen_server's internal state, indicating that we are now in the process
>> of shutting down.
>> - When the time has come to really shut down (so after all outstanding
>> requests have been responded to, or timed out), respond with { stop,
>> shutdown, SomeReply, SomeState } from a handle_call/3 or with { stop,
>> shutdown, SomeState } from a handle_cast/2 or handle_info/2, which would
>> send an exit-message back to the supervisor indicating that we have
>> terminated.
>>
>> Unfortunately, this doesn't seem to work. What seems to happen instead is
>> for the { 'EXIT', shutdown } message to immediately trigger a call to the
>> gen_server's terminate function- handle_info/2 is never called.
>> In theory, I could of course set up a receive-loop in the terminate
>> function
>> and deal with incoming messages in that way, but that would mean I would
>> process incoming messages (data from a TCP connection, for example) in two
>> different ways: by implementing handle_info before the shutdown, and by
>> explicitly receiving message after shutdown.
>>
>> How is this normally handled?
>>
>> Thanks,
>>
>> Jeroen
>>
>
>


More information about the erlang-questions mailing list