Python3.6升3.8后Django项目SIGABRT崩溃及核心转储问题求助
问题描述
将Django项目从Python 3.6升级至3.8后,开始生成最大达500MB的核心转储文件,导致Kubernetes Pod重启,且无任何日志或异常信息输出。
通过gdb调试核心转储文件,得到以下输出:
#Reading symbols from /usr/local/bin/uwsgi... #[New LWP 8] #[Thread debugging using libthread_db enabled] #Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". #Core was generated by `uwsgi myapp.ini'. #Program terminated with signal SIGABRT, Aborted. #0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50 #50 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
执行backtrace命令的输出:
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50 #1 0x00007f5998445859 in __GI_abort () at abort.c:79 #2 0x00007f59984b026e in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7f59985da298 "%s\n") at ../sysdeps/posix/libc_fatal.c:155 #3 0x00007f59984b82fc in malloc_printerr (str=str@entry=0x7f59985d844d "corrupted size vs. prev_size") at malloc.c:5347 #4 0x00007f59984b896b in unlink_chunk (p=p@entry=0x55dc42df1900, av=0x7f599860fb80 <main_arena>) at malloc.c:1454 #5 0x00007f59984b9e8b in _int_free (av=0x7f599860fb80 <main_arena>, p=0x55dc42dedf40, have_lock=<optimized out>) at malloc.c:4342 #6 0x00007f5998857bde in ?? () from /lib/x86_64-linux-gnu/libpython3.8.so.1.0 #7 0x00007f5998697070 in ?? () from /lib/x86_64-linux-gnu/libpython3.8.so.1.0 #8 0x00007f599877b89d in _PyGC_CollectNoFail () from /lib/x86_64-linux-gnu/libpython3.8.so.1.0 #9 0x00007f59987bcefd in PyImport_Cleanup () from /lib/x86_64-linux-gnu/libpython3.8.so.1.0 #10 0x00007f59987a8610 in Py_FinalizeEx () from /lib/x86_64-linux-gnu/libpython3.8.so.1.0 #11 0x000055dc3f2943e1 in uwsgi_plugins_atexit () #12 0x00007f59984698a7 in __run_exit_handlers (status=30, listp=0x7f599860f718 <__exit_funcs>, run_list_atexit=run_list_atexit@entry=true, run_dtors=run_dtors@entry=true) at exit.c:108 #13 0x00007f5998469a60 in __GI_exit (status=<optimized out>) at exit.c:139 #14 0x000055dc3f249415 in uwsgi_exit () #15 0x000055dc3f292f2b in end_me () #16 0x000055dc3f2965f7 in uwsgi_ignition () #17 0x000055dc3f29ae16 in uwsgi_worker_run () #18 0x000055dc3f29b394 in uwsgi_run () #19 0x000055dc3f245d44 in main ()
环境信息:
- Python 3.8
- Django 2.1.5
- Ubuntu 20.04
排查思路与解决方案
1. 定位内存损坏根源
从backtrace可见,崩溃发生在Python GC回收阶段的内存释放流程,错误提示corrupted size vs. prev_size,属于堆内存被非法篡改。这类问题大概率来自两个方向:
- 旧C扩展模块与Python3.8内存管理机制不兼容,存在内存操作bug
- uWSGI进程退出时的清理流程与Python3.8的Finalize逻辑冲突
2. 优先排查并升级C扩展依赖
项目中带C扩展的第三方包(如psycopg2、numpy、cryptography等)是重灾区,Python3.8对内存管理做了调整,旧版本的C扩展可能存在兼容性问题:
- 列出所有带C扩展的包:
pip list --format=freeze | grep -E "(psycopg2|numpy|cryptography|lxml|Pillow)" - 将这些包升级到官方明确支持Python3.8的版本,优先使用官方发布的wheel包,避免使用过时的二进制编译包。
3. 调整uWSGI配置规避退出时崩溃
崩溃发生在进程退出阶段的Py_FinalizeEx清理流程,可通过uWSGI配置跳过部分清理步骤:
- 在
myapp.ini中添加以下配置:py-ignore-exception=1 disable-exception-cleanup=1 - 同时调整进程重启策略,比如降低
max-requests参数值,避免进程长时间运行积累内存问题;或者禁用reload-on-rss这类可能频繁触发进程退出的配置。
4. 启用Python内存调试工具
通过工具提前捕获内存损坏的发生点,而非等到进程退出时崩溃:
- 开启Python调试malloc环境变量,强制使用内存检测:
该配置会在内存非法操作时立即抛出错误,而非延迟到释放阶段。export PYTHONMALLOC=debug - 启用
faulthandler模块捕获Python调用栈:
在项目入口文件(如wsgi.py)顶部添加:
崩溃时会打印更详细的Python层级调用栈,帮助定位问题代码。import faulthandler faulthandler.enable()
5. 升级Django到兼容版本
Django 2.1.x仅对Python3.8提供实验性支持,Django 2.2 LTS才正式适配Python3.8。升级到Django2.2.x版本可以修复大量版本兼容性问题,这是优先级很高的操作。
内容的提问来源于stack exchange,提问作者Manjunath
相关产品推荐
相关产品推荐

