本文目录导读:

原子操作、状态清理和避免死锁,以下是一些常见语言和场景的实现策略:
通用原则
# 理想退出流程 1. 设置"退出标志"(原子操作) 2. 主循环检查标志,正常退出 3. 清理资源(文件、网络连接、锁) 4. 退出前发送信号给子进程 5. 恢复终端设置(如果是交互程序)
Python 实现(最优雅的方式)
使用 threading.Event(推荐)
import signal
import threading
import time
# 全局退出事件
exit_event = threading.Event()
def signal_handler(signum, frame):
print(f"收到信号 {signum},准备退出...")
exit_event.set() # 原子操作,不阻塞
def main_loop():
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
while not exit_event.is_set():
# 你的业务逻辑,可以设置超时
# time.sleep(1) # 避免忙等待
# 或者使用 select/poll 等
# 示例:带超时的等待
if exit_event.wait(timeout=1):
break
do_work() # 你的实际工作
cleanup()
def cleanup():
print("清理资源...")
# 关闭文件、数据库连接等
time.sleep(0.5)
print("安全退出完成")
if __name__ == "__main__":
main_loop()
异步版本(asyncio)
import asyncio
import signal
class GracefulHandler:
def __init__(self):
self.shutdown = False
def signal_handler(self, signum):
print(f"收到信号 {signum},准备优雅退出")
self.shutdown = True
async def main(self):
loop = asyncio.get_event_loop()
for sig in (signal.SIGINT, signal.SIGTERM):
loop.add_signal_handler(
sig,
lambda s=sig: self.signal_handler(s)
)
while not self.shutdown:
await asyncio.sleep(1)
print("工作中...")
await self.cleanup()
async def cleanup(self):
print("清理中...")
await asyncio.sleep(1)
print("退出完成")
if __name__ == "__main__":
app = GracefulHandler()
try:
asyncio.run(app.main())
except KeyboardInterrupt:
pass
Shell 脚本中的优雅退出
#!/bin/bash
# 全局退出标志
EXIT_FLAG=false
# 信号处理函数
cleanup() {
echo "收到退出信号,清理资源..."
EXIT_FLAG=true
# 杀死子进程
if [ -n "$CHILD_PID" ]; then
kill -TERM "$CHILD_PID" 2>/dev/null || true
wait "$CHILD_PID" 2>/dev/null || true
fi
# 清理临时文件
rm -f /tmp/myapp_*.tmp
echo "安全退出"
exit 0
}
# 注册信号处理
trap cleanup SIGINT SIGTERM
# 主循环
while [ "$EXIT_FLAG" = false ]; do
# 你的业务逻辑
sleep_handler &
CHILD_PID=$!
wait $CHILD_PID 2>/dev/null
# 检查是否需要退出
if [ "$EXIT_FLAG" = true ]; then
break
fi
done
C/C++ 实现(信号安全考量)
#include <stdio.h>
#include <signal.h>
#include <stdatomic.h>
#include <unistd.h>
// 使用原子变量确保信号安全
static atomic_bool exit_flag = false;
void signal_handler(int signum) {
// 只设置标志,不做其他操作
exit_flag = true;
}
int main() {
struct sigaction sa = {0};
sa.sa_handler = signal_handler;
sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
while (!exit_flag) {
// 你的业务逻辑
sleep(1);
do_work();
}
// 清理资源
cleanup_logs();
close_database();
return 0;
}
关键注意事项
信号处理函数必须安全
- 只做最小的操作:设置标志位、写入管道
- 避免:内存分配、锁操作、printf(非信号安全)
- 使用
sig_atomic_t或atomic_bool
主循环检查退出条件
# 反模式:纯忙等待
while True:
if should_exit:
break
do_work() # 如果阻塞,可能永远退不出
# 好模式:使用超时
while not should_exit:
result = do_work_with_timeout(timeout=1.0)
if result is None: # 超时
continue
资源释放顺序
# 正确的释放顺序(与创建相反) connections.close() # 先关连接 files.close() # 再关文件 locks.release() # 最后释放锁
子进程处理
import subprocess
import signal
class ProcessManager:
def __init__(self):
self.children = []
def handle_exit(self, signum, frame):
for p in self.children:
p.terminate() # 先发 SIGTERM
for p in self.children:
try:
p.wait(timeout=5) # 等待最多5秒
except subprocess.TimeoutExpired:
p.kill() # 强制杀死
完整示例:网络服务器
import socket
import select
import signal
import threading
class GracefulServer:
def __init__(self, host='localhost', port=8080):
self.running = True
self.server = socket.socket()
self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.server.bind((host, port))
self.server.listen(5)
def signal_handler(self, signum, frame):
print(f"收到信号 {signum}")
self.running = False
def cleanup(self):
self.server.close()
print("服务器已关闭")
def run(self):
signal.signal(signal.SIGINT, self.signal_handler)
signal.signal(signal.SIGTERM, self.signal_handler)
while self.running:
# 使用 select 实现超时
readable, _, _ = select.select(
[self.server], [], [], 1.0
)
if not readable:
continue # 超时,重新检查退出标志
conn, addr = self.server.accept()
# 处理连接(可以放入线程池)
self.cleanup()
if __name__ == "__main__":
server = GracefulServer()
try:
server.run()
except KeyboardInterrupt:
server.cleanup()
优雅退出的核心要素
| 要素 | 说明 | 反例 |
|---|---|---|
| 原子标志 | 使用 atomic 或 threading.Event |
普通 bool 变量 |
| 非阻塞处理 | 信号处理中只设标志 | 在信号处理中做 I/O |
| 超时循环 | 主循环有超时检查 | 无限阻塞的 accept() |
| 资源逆序释放 | 后创建的先释放 | 随意释放资源 |
| 子进程管理 | 先 TERM 后 KILL | 直接 KILL |
优雅退出的目标是让程序在收到信号后,能在合理的时间内安全地结束,不丢失数据、不损坏文件、不留下孤儿进程。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播