Skip to content

Commit f931938

Browse files
authored
Merge pull request #2726 from taegyunkim/lazy-atexit
fix: install atexit handlers after apps are initialized When --lazy or --lazy-apps is set, uwsgi's atexit() handlers, for Python it is uwsgi_python_atexit(), are installed in master process before calling fork(), and when worker loads the application, destructors for static global variables used in Python native extension modules are installed via atexit(). Those static global variables are destructed first and uwsgi atexit() handlers are run. An application can install Python atexit handler via following two ways uwsgi Python module's atexit attribute, which will be called by uwsgi_python_atexit() here. using Python atexit module, which will be called by CPython Py_Finalize(), and uwsgi calls Py_Finalize() also from uwsgi_python_atexit() from here For both cases, setting --lazy or --lazy-apps changes the order atexit() handlers are installed. So, if the Python atexit function installed with either of the method calls into native extension module using global states, it results in an undefined behavior leading to segmentation faults.
2 parents 1eb8615 + 58aa180 commit f931938

File tree

1 file changed

+9
-5
lines changed

1 file changed

+9
-5
lines changed

core/uwsgi.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3202,13 +3202,12 @@ int uwsgi_start(void *v_argv) {
32023202
//init apps hook (if not lazy)
32033203
if (!uwsgi.lazy && !uwsgi.lazy_apps) {
32043204
uwsgi_init_all_apps();
3205+
// Register uwsgi atexit plugin callbacks after all applications have
3206+
// been loaded. This ensures plugin atexit callbacks are called prior
3207+
// to application registered atexit callbacks.
3208+
atexit(uwsgi_plugins_atexit);
32053209
}
32063210

3207-
// Register uwsgi atexit plugin callbacks after all applications have
3208-
// been loaded. This ensures plugin atexit callbacks are called prior
3209-
// to application registered atexit callbacks.
3210-
atexit(uwsgi_plugins_atexit);
3211-
32123211
if (!uwsgi.master_as_root) {
32133212
uwsgi_log("dropping root privileges after application loading\n");
32143213
uwsgi_as_root();
@@ -3553,6 +3552,11 @@ void uwsgi_worker_run() {
35533552

35543553
if (uwsgi.lazy || uwsgi.lazy_apps) {
35553554
uwsgi_init_all_apps();
3555+
3556+
// Register uwsgi atexit plugin callbacks after all applications have
3557+
// been loaded. This ensures plugin atexit callbacks are called prior
3558+
// to application registered atexit callbacks.
3559+
atexit(uwsgi_plugins_atexit);
35563560
}
35573561

35583562
// some apps could be mounted only on specific workers

0 commit comments

Comments
 (0)