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

Graham Dumpleton graham.dumpleton at gmail.com
Tue Feb 21 02:39:22 CET 2012


On 21 February 2012 12:03, Simon Sapin <simon.sapin at exyr.org> wrote:
> Le 21/02/2012 01:18, Chris McDonough a écrit :
>
>> On Mon, 2012-02-20 at 17:39 -0500, PJ Eby wrote:
>>>
>>> >  The standard way to do this would be to define an "optional server
>>> >  extension" API supplied in the environ; for example, a
>>> >  'x-wsgiorg.register_shutdown' function.
>>
>> Unlikely, AFACIT, as shutdown may happen when no request is active.
>> Even if this somehow happened to not be the case, asking the application
>> to put it in the environ is not useful, as the environ can't really be
>> relied on to retain values "up" the call stack.
>
>
> Hi,
>
> I like environ['x-wsgiorg.register_shutdown']. It would work without changes
> to WSGI itself.
>
> I think that the idea is not to put your shutdown function in the
> environment and hope it stays there "up" the stack, but to register it by
> calling register_shutdown:
>
> @environ.get('x-wsgiorg.register_shutdown', lambda f: f)
> def do_cleanup():
>    pass
>
> Also, a shutdown function would be used to clean up something that was set
> up in a request. So if the server shuts down without having ever served a
> request, there probably is nothing to clean up.

Using environ is not going to work it is supplied on a per request basis.

You would typically want an application scope cleanup handler to only
be registered once.

In this scheme you are relying on it being registered from within a
request scope.

To ensure that it is only registered once, the caller would need to
use a flag protected by a thread mutex to know whether should call a
second time, which is cumbersome.

If you don't do that you could end up registering a separate callback
for every single request that occurs and memory usage alone would blow
out just from recording them all.

Alternatively, you would have to require the underlying WSGI
server/adapter to weed out duplicates, but even if you do that, you
still waste the time of the per request scope registering it all the
time.

Even if you have a registration mechanism, especially with a WSGI
adapter riding on top of something else, how is the WSGI adapter going
to get notified to call them.

All you have therefore done is shift the problem of how it is
triggered somewhere else.

Overall the best chance of being able to do anything is relying on atexit.

You are though at the mercy of the WSGI hosting mechanism shutting
down the process and so the interpreter, in an orderly manner such
that atexit callbacks get called.

In Apache/mod_wsgi you get this guarantee, even in sub interpreters
where atexit callbacks wouldn't normally be called when they are
destroyed.

For uWSGI, atexit callbacks will not be called at the moment, by
Robert is making changes to it so you get a guarantee there as well.
It is possible he is only doing this though for case where main
interpreter is being used, as doing it for sub interpreters is a bit
fiddly.

Any pure Python WSGI servers shouldn't have issues so long as they
aren't force exiting the whole process and bypassing normal
interpreter destruction.

Graham


More information about the Web-SIG mailing list