uWSGI+Flask环境下无法启停Python守护进程的问题求助
Alright, let's dig into why your daemon process isn't receiving SIGTERM when uWSGI is running with threads=2—this is almost certainly tied to how uWSGI manages signal masking in multi-threaded mode, and how your daemon inherits those settings.
Root Cause
When uWSGI runs with multiple threads per worker, it automatically blocks certain signals (including SIGTERM) in worker threads to avoid race conditions and ensure thread safety. When you launch your daemon via os.system(), it inherits the signal mask from the parent uWSGI worker process. This means SIGTERM is blocked for your daemon, so even if you send kill -15 <pid>, the signal never reaches your custom handler.
In single-thread mode, uWSGI doesn't apply this strict signal masking, so your daemon inherits a clean signal mask and can receive SIGTERM as expected.
Fixes to Try
1. Unblock SIGTERM in Your Daemon
The simplest fix is to explicitly unblock SIGTERM in your webservice.py right after startup, before registering your signal handler:
import signal import sys # Unblock SIGTERM to ensure it can reach our handler signal.pthread_sigmask(signal.SIG_UNBLOCK, [signal.SIGTERM]) # Register your existing SIGTERM handler signal.signal(signal.SIGTERM, lambda signo, handler: sys.exit(0))
This overrides the inherited signal mask and ensures your daemon can receive the terminate signal.
2. Launch the Daemon in a New Session
A more robust approach is to detach your daemon completely from the uWSGI process environment using subprocess.Popen with start_new_session=True. This creates a new process group and session for your daemon, so it doesn't inherit any of uWSGI's signal or thread-related settings:
Replace your Flask request code from:
os.system("python /SWS/webservice.py %s" % cmd)
With:
import subprocess subprocess.Popen( ["python", "/SWS/webservice.py", cmd], start_new_session=True, stdout=subprocess.DEVNULL, # Optional: redirect output to avoid uWSGI logs clutter stderr=subprocess.DEVNULL )
This method is better for long-running daemons as it fully isolates them from the parent uWSGI process.
3. Verify the Signal Mask (Debug Step)
To confirm the signal mask is the issue, add this debug code to webservice.py and check the output when launching with threads=1 vs threads=2:
import signal import os print(f"Daemon PID: {os.getpid()}") blocked_signals = signal.pthread_sigmask(signal.SIG_BLOCK, None) print(f"Blocked signals: {blocked_signals}") if signal.SIGTERM in blocked_signals: print("⚠️ SIGTERM is blocked! This is the problem.") else: print("✅ SIGTERM is not blocked.")
When running with threads=2, you should see SIGTERM listed as blocked—this confirms our root cause.
Bonus: Check uWSGI Signal Configuration
While not recommended unless necessary, you can tell uWSGI to ignore SIGTERM in worker processes (though this may affect uWSGI's own graceful shutdown behavior). Add this to your uWSGI config:
[uwsgi] # Your existing config... ignore-signals = SIGTERM
Only use this if the first two fixes don't work, as it can interfere with uWSGI's ability to shut down cleanly.
内容的提问来源于stack exchange,提问作者Houpp

