uwsgi
uwsgi copied to clipboard
uwsgi.atexit() not firing for all worker processes.
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.
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.
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.
// 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.