`os.register_at_fork` `after_in_child` not called

643 views Asked by At

I'm trying to add a postfork function to patch my program after my Django application is forked by Gunicorn/uWSGI to spawn workers.

Now the problem is I know I can do this by adding @postfork decorator, but I thought it could be also achieved by using the Python 3.7 os.register_at_fork, it turns out the function is never called even registered before the fork happens? (or am I registering the function too late at a point where the fork already happened? I'm eager to learn how exactly register_at_fork works)

My wsgi.py is like below, and I tested it with everything I got but seems like the hook function was never called in forked server workers. I appreciate any help on this issue.

Btw, using the @postfork decorator, as commented out, works fine.

# from uwsgidecorators import postfork
# @postfork
def hook():
    # do something here
    print('hello')
    ...

if hasattr(os, 'register_at_fork'):
    print('registered')
    os.register_at_fork(after_in_child=hook)
else:
    print('not registered')

# os.fork()

from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'pollme.settings')

application = get_wsgi_application()

my start command is

uwsgi --die-on-term \
    --http 0.0.0.0:8000 \
    --http-manage-expect \
    --master \
    --workers 3 \
    --enable-threads \
    --threads 3 \
    --manage-script-name \
    --wsgi-file myapplication/wsgi.py

I guess it might relate to this documented behaviour but I cannot be sure, I hope someone could help me to understand if gunicorn/uwsgi forks are considered "subprocess launch".

These calls are only made if control is expected to return to the Python interpreter. A typical subprocess launch will not trigger them as the child is not going to re-enter the interpreter.

Functions registered for execution before forking are called in reverse registration order. Functions registered for execution after forking (either in the parent or in the child) are called in registration order.

1

There are 1 answers

0
eagr On BEST ANSWER

Looks like uwsgi is forking from C code and python states such cases may not work doc. uwsgi is manually calling the hooks that were registered with the decorator @postfork and that's why they work uwsgi source. I think there is something in the uwsgi that also calls the hooks registered with os.register_at_fork only in some conditions (not sure exactly when though).