Celery调用Django模型触发SIGSEGV错误,求助排查方案
解决Celery任务SIGSEGV段错误问题
错误日志
2024-01-29 07:23:52,962: ERROR/MainProcess] Process 'ForkPoolWorker-16' pid:2871 exited with 'signal 11 (SIGSEGV)'[2024-01-29 07:23:54,730: ERROR/MainProcess] Task handler raised error: WorkerLostError('Worker exited prematurely: signal 11 (SIGSEGV) Job: 0.') Traceback (most recent call last): File "/Users/asim/Django/Practice-tool-ai-backend/ptenv/lib/python3.12/site-packages/billiard/pool.py", line 1264, in mark_as_worker_lost raise WorkerLostError( billiard.einfo.ExceptionWithTraceback: """ Traceback (most recent call last): File "/Users/asim/Django/Practice-tool-ai-backend/ptenv/lib/python3.12/site-packages/billiard/pool.py", line 1264, in mark_as_worker_lost raise WorkerLostError( billiard.exceptions.WorkerLostError: Worker exited prematurely: signal 11 (SIGSEGV) Job: 0. """
问题分析
SIGSEGV(段错误)属于内存访问异常,结合你的场景——仅当Celery任务执行Django模型查询+OpenAI API调用时触发,去掉模型查询就正常,大概率和Django ORM在Celery fork进程中的初始化问题、数据库连接复用冲突有关。
解决步骤
1. 确保Celery任务正确初始化Django环境
在tasks.py开头添加Django初始化代码,避免fork进程中Django环境未就绪:
import os import django os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'PracticeToolAI.settings') django.setup()
2. 避免复用父进程的数据库连接
Django的数据库连接在fork后无法安全复用,会导致内存异常。在任务中手动关闭旧连接后再查询模型:
from django.db import connection from celery import app from .models import ListeningTask import openai @app.task def generate_listening_task_questions(task_id): # 关闭fork继承的旧连接,强制重新建立 connection.close() # 通过ID查询对象,确保获取最新数据 task = ListeningTask.objects.get(id=task_id) # 调用OpenAI API生成问题 response = openai.ChatCompletion.create( model="gpt-3.5-turbo", messages=[{"role": "user", "content": f"根据这段文本生成听力题:{task.transcript}"}] ) # 保存生成的问题到数据库 task.questions = response.choices[0].message.content task.save()
3. 传递对象ID而非实例到Celery任务
在Admin的save_model中,不要直接传递ListeningTask对象实例,而是传递它的ID,避免序列化/反序列化时的内存问题:
from django.contrib import admin from .models import ListeningTask from .tasks import generate_listening_task_questions class ListeningTaskAdmin(admin.ModelAdmin): def save_model(self, request, obj, form, change): super().save_model(request, obj, form, change) # 传递对象ID而非实例 generate_listening_task_questions.delay(obj.id) admin.site.register(ListeningTask, ListeningTaskAdmin)
4. 检查OpenAI SDK与Python/Celery兼容性
Python 3.12属于较新版本,部分旧版OpenAI SDK可能存在兼容性问题。尝试升级或降级SDK:
# 升级到最新稳定版 pip install --upgrade openai # 或降级到兼容Python 3.12的版本 pip install openai==1.13.3
5. 排查模型的信号/钩子逻辑
如果ListeningTask模型有post_save信号、自定义管理器或其他钩子方法,检查其中是否存在非线程安全的操作(比如全局变量、未正确释放的资源),这些操作在fork进程中可能触发内存异常。
内容的提问来源于stack exchange,提问作者Asim Solehria
相关产品推荐
相关产品推荐

