unbit / uwsgi

uWSGI application server container
http://projects.unbit.it/uwsgi
Other
3.46k stars 691 forks source link

uwsgi.atexit() not firing for all worker processes. #2063

Open klichukb opened 5 years ago

klichukb commented 5 years ago

uwsgi 2.0.18

A python app (example.py):

import json

def application(env, start_response):
    start_response('200 OK', [])
    a = 5 ** 100000
    return json.dumps({'a': len(str(a))})

def atexit(*args):
    import uwsgi
    print 'At exit called', uwsgi.worker_id()

try:
    import uwsgi
    uwsgi.atexit = atexit
except ImportError:
    pass

uWsgi handler does somewhat CPU intensive work. Setup:

uwsgi --master --processes 4 --http :9090 --die-on-term --wsgi-file example.py

If I try to kill uwsgi master with SIGTERM I properly get 4 messages from workers:

SIGINT/SIGQUIT received...killing workers...
At exit called 4
At exit called 2
At exit called 1
At exit called 3

Now I try to load the server, say, with "ab":

ab -c 2 -n 100000 "http://127.0.0.1:9090/"

which should keep around 2 workers constantly busy and at high CPU usage, SIGTERM to master does not call atexit on these busy workers:

SIGINT/SIGQUIT received...killing workers...
At exit called 2
At exit called 3

Does master still prioritize dispatching messages onto workers instead of running atexit? How is this behavior formally explained? Looks like under heavy load I can get 0 atexits called at all.

Same happens if using atexit module directly.

klichukb commented 5 years ago

Friend of mine pointed out code that exactly doesn't call atexit if worker is busy. Is this correct? It means there are no guarantees that atexit is called since you cant know what load you're gonna get.

arthuriantech commented 5 years ago

All time this hook worked unreliably. Moreover, it just not work in async mode. You can use as-user-atexit etc, but code will be executed in other address space.

methane commented 8 months ago

// if busy do not run atexit hooks is introduced in this commit. https://github.com/unbit/uwsgi/commit/80be7385ed66d29eaf0cfa7a8f4399be6ad12b5c?diff=unified&w=1

I don't know why this line is necessary.