[Web-SIG] A 'shutdown' function in WSGI

Benoit Chesneau bchesneau at gmail.com
Tue Feb 21 10:21:55 CET 2012


On Mon, Feb 20, 2012 at 5:03 PM, Tarek Ziadé <ziade.tarek at gmail.com> wrote:
> Hello
>
> I need to be able to call a function when the web application shuts down
> (SIGTERM/SIGINT) -- the use case is to stop a background thread.
>
> I am currently using signals because it seems to be the most clean way to do
> this. atexit is much trickier since you don't know when it's going to get
> called and you might try to call objects that were garbage collected unless
> you hack something to keep references alive.
>
> But signals are also tricky beasts since you may compete with other code
> that are listening to them. For instance mod_wsgi don't like apps that have
> signal handlers.
>
> Anyways, the bottom line is that the cleanest way to do this -- as per Chris
> McDonough idea, would be to introduce in the WSGI protocol a "shutdown"
> function the servers would be obligated to call before exiting.
>
> I am not sure yet about its arguments, maybe a signum + frame or simply an
> exit code...
>
> But how do you like the idea ?  That would solve for me the problem of
> having to deal differently here depending on if I am called with mod_wsgi or
> gunicorn or xxx
>
Hi Tarek,

In gunicorn we have the concept of hook which exactly does what you want
(on_exit hook). You can do this via the configuration file. And you can
do this for the other steps (reload, pre/post fork, pre/post request
...).

Anyway, I think there are 2 issues to solve with this shutdown thing
(and more) in a generic way:

1. how to make your application aware of the server capabilities (can it
or not handle shutdown)
2. how to pass such functions to the server.

There are also some others details like determining what is the context
needed by the application at this step.

Today the server is acting as a gateway so it just pass a request to an
application and return the response from the application. The
application by itself only lives in this context. Maybe, like some said,
if we want to give more info about that, we could imagine the application
object or function as a bus reacting on different contexts:

    def application(environ, start_application):
        pass

where the environ can be different depending on the context an action, we
could have:

    http request    {"wsgi.context": "http", ...}
    shutdown        {"wsgi.context"; "server", "action": "shutdown", ...}

smth like it. But how to know when the server can't pass the action
shutdown? Also what would be the environ at shutdown?

One other method, like the one described by Sylvain Hellegouarch, would
be adding some properties/attributes to the application object. So the
server would eventually check if they exists and eventually call them.
But again how to know when the server can't pass the action shutdown?
Though, I don't like to handle more than the application callable today,
I can see some problems when you have to handle server reload and such
things.

It seems important for me that the application knows about the server
capabilities if it want to handle such things like the `shutdown`. And
this step is solved by gunicorn & others by specifically handling a
configuration. But maybe we could just considers that a server always
handle the "reload", "shutdown", also pre/post "request" evenst and have
optionnals message passed to the application? (how do we handled process
context changes - if we re in a thread for ex - ?).

We could also imagine a web application package that provides hooks
handling depending on the server target... I quite like this idea.

Not sure what is the right way. What do you think?

- benoît


More information about the Web-SIG mailing list