信号处理

更新日期: 2026-03-29

概述

Butterfly 使用统一的信号处理机制,所有信号处理集中在 main.py 中管理,确保进程能够优雅退出。

信号对照表

信号
发送方式
功能
状态

SIGINT

2

Ctrl+C

优雅退出

SIGTERM

15

kill

优雅退出

SIGUSR1

10

kill -USR1

输出堆栈信息

SIGUSR2

12

kill -USR2

输出内存信息

实现细节

main.py - 统一信号处理

from xlib.util import stackdump, mem_top

def signal_handler_shutdown(signum, frame):
    """优雅退出 (SIGINT=2, SIGTERM=15)"""
    global _server
    logger.info("Received signal %s (%s), shutting down gracefully...", sig_name, signum)

    # Step 1: 发送停止信号给所有组件
    signals.signal_server_stop.send("main")

    # Step 2: 停止 HTTP Server
    if _server:
        _server.stop()

    logger.info("Server stopped successfully")
    sys.exit(0)


def signal_handler_stackdump(signum, frame):
    """输出堆栈信息 (SIGUSR1=10)"""
    logger.info("Stack dump requested (SIGUSR1)")
    stackdump.stackdump()


def signal_handler_mem(signum, frame):
    """输出内存信息 (SIGUSR2=12)"""
    logger.info("Memory info requested (SIGUSR2)")
    mem_info = mem_top.mem_top(limit=20, width=200)
    logger.info("Memory info:\n%s", mem_info)


if __name__ == '__main__':
    # 注册信号处理
    signal.signal(signal.SIGINT, signal_handler_shutdown)
    signal.signal(signal.SIGTERM, signal_handler_shutdown)
    signal.signal(signal.SIGUSR1, signal_handler_stackdump)
    signal.signal(signal.SIGUSR2, signal_handler_mem)

    _server = CherryPyWSGIServer(
        config.SERVER_LISTEN_ADDR,
        wsgiapp.application,
        config.SERVER_THREAD_NUM,
        perfork=1,
        after_perfork=lambda worker_id: wsgiapp_workers.initialize_workers()
    )

    _server.start()

优雅退出流程

使用示例

优雅退出

查看堆栈

查看内存

设计原则

  1. 统一管理: 所有信号处理在 main.py 中统一管理,避免冲突

  2. 优雅退出: 通过信号机制通知所有组件优雅停止

  3. 职责分离:

    • main.py: 进程生命周期管理

    • wsgiapp.py: WSGI 应用逻辑

    • wsgiapp_workers.py: Worker 初始化(通过 after_perfork 回调)

Last updated