From 2908511a8cd872635639bf16824183eb8046fc11 Mon Sep 17 00:00:00 2001 From: "russell@unturf.com" Date: Wed, 18 Feb 2026 13:04:46 -0500 Subject: [PATCH] double-fork backfill to fully detach from uWSGI worker Single fork left the child in the uWSGI process group with inherited HTTP sockets, causing 502s. Double-fork with setsid() and fd cleanup so the grandchild is fully orphaned to init. --- make_post_sell/lib/karaoke.py | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/make_post_sell/lib/karaoke.py b/make_post_sell/lib/karaoke.py index 9097389..a85233e 100644 --- a/make_post_sell/lib/karaoke.py +++ b/make_post_sell/lib/karaoke.py @@ -175,9 +175,28 @@ def backfill_karaoke_async(shop_id, session_factory, app_settings): pid = os.fork() if pid > 0: - return # parent returns immediately + # Parent: reap the intermediate child immediately so it doesn't zombie + os.waitpid(pid, 0) + return + + # Intermediate child: detach fully from uWSGI, then fork again + os.setsid() + pid2 = os.fork() + if pid2 > 0: + os._exit(0) # intermediate child exits — grandchild is orphaned to init + + # --- Grandchild process: fully detached from uWSGI --- + # Close inherited file descriptors (uWSGI sockets, HTTP connections) + import resource + maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1] + if maxfd == resource.RLIM_INFINITY: + maxfd = 1024 + for fd in range(3, maxfd): + try: + os.close(fd) + except OSError: + pass - # --- Child process: independent of uWSGI worker --- lock_fd = None try: # Acquire file lock (guards one-per-shop)