You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django请求处理线程中收到SIGTERM信号时执行自定义代码

问题原因分析

你的猜测完全正确,Python的信号处理逻辑是所有信号只会被主线程接收和处理,你在信号处理器里调用sys.exit()只会在主线程抛出SystemExit异常,根本不会传递到处理请求的子线程,子线程的异常捕获逻辑自然触发不了。而且Django开发服务器默认采用多线程模型处理请求,主线程退出后子线程如果是非守护模式还会继续运行,守护模式会被直接强制终止,都走不到你写的异常捕获分支。

可行解决方案

方案1:全局终止标志轮询(最稳定,推荐)

这个方案适配你现有循环逻辑的场景,不需要改动太多代码,稳定性最高。

代码修改步骤:

  1. 新增全局终止标志,信号处理器收到SIGTERM后只修改标志,不直接退出
import signal
import sys
from django.apps import AppConfig
import logging

logger = logging.getLogger(__name__)

# 全局终止标志
g_terminate = False

def signal_handler(signal_num, frame):
    global g_terminate
    g_terminate = True
    # 不需要直接调用sys.exit(),等待请求处理完后进程自然退出即可
    # 如果有超时要求,可以在这里启动定时器,超时后再强制调用sys.exit()

class TesterConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'tester'

    def ready(self):
        logger.info('starting ready')
        signal.signal(signal.SIGTERM, signal_handler)
  1. 请求处理逻辑中每次循环轮询标志位,检测到终止信号后直接执行状态保存逻辑
import logging
import time
from django.http import HttpResponse
from tester.apps import g_terminate # 导入全局终止标志

logger = logging.getLogger(__name__)

def handler(request):
    try:
        logger.info('start')
        while True:
            # 每次循环都检查终止标志
            if g_terminate:
                logger.info('收到终止信号,开始保存当前请求状态')
                # 此处编写你的状态保存逻辑
                break
            time.sleep(1)
    except Exception as e:
        logger.info(f'exception: {e}')
    return HttpResponse('hallo')

方案2:主动向子线程注入异常(适用于无法轮询的场景)

如果你的长耗时逻辑不是可轮询的循环结构,可以用Python C API主动给所有活跃的请求子线程抛出异常,子线程捕获后处理状态保存。
注意:如果子线程正在执行C语言实现的扩展代码,异常不会立即触发,存在一定延迟。
示例代码参考:

# 线程ID存储,请求开始时存入,请求结束时删除
active_thread_ids = set()

# 信号处理器中给所有活跃子线程抛异常
def signal_handler(signal_num, frame):
    import ctypes
    for tid in active_thread_ids:
        ctypes.pythonapi.PyThreadState_SetAsyncExc(
            ctypes.c_long(tid),
            ctypes.py_object(SystemExit)
        )
    # 等待一段时间后再退出
    time.sleep(2)
    sys.exit()
生产环境注意事项
  • 不要用Django自带的runserver做生产部署,建议用Gunicorn/uWSGI这类生产级WSGI服务器
  • 部署时需要调整服务器的超时配置,确保你的状态保存逻辑能在SIGKILL触发前执行完成,比如Gunicorn可以设置--graceful-timeout参数调整优雅退出的等待时长

内容的提问来源于stack exchange,提问作者FlorianK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.18 09:06:04