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.
This commit is contained in:
russell@unturf.com 2026-02-18 13:04:46 -05:00
parent 0ad82d5314
commit 2908511a8c

View file

@ -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)