【问题标题】:GDB empty backtrace when using gunicorn core dump使用 gunicorn 核心转储时的 GDB 空回溯
【发布时间】:2025-11-25 13:30:01
【问题描述】:

我正在尝试在一个 docker 容器中制作 gunicorn 的核心转储,并在另一个容器中对其进行调试。 Gunicorn 使用 python3.5 运行。 当我在转储的容器中打开核心文件时,一切看起来都很好:

Reading symbols from /opt/pyenv/versions/3.5.0/bin/python3.5...done.
[New LWP 786]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `/opt/pyenv/versions/3.5.0/bin/python3.5'.
#0  0x00007f7caec93af3 in __epoll_wait_nocancel () at ../sysdeps/unix/syscall-template.S:81
81      ../sysdeps/unix/syscall-template.S: No such file or directory.
(gdb) bt
#0  0x00007f7caec93af3 in __epoll_wait_nocancel () at ../sysdeps/unix/syscall-template.S:81
#1  0x00007f7cacdaf213 in pyepoll_poll (self=0x7f7ca5aa9a80, args=<optimized out>, kwds=<optimized out>) at /tmp/python-build.20160412233915.330/Python-3.5.0/Modules/selectmodule.c:1549
#2  0x00000000005a7579 in PyCFunction_Call (func=func@entry=0x7f7c98706090, args=args@entry=0x7f7c9feb5550, kwds=kwds@entry=0x0) at Objects/methodobject.c:98
...

但是当我试图在我为调试目的而构建的另一个容器中打开这个文件时,我得到了这个:

Reading symbols from /opt/pyenv/versions/3.5.0/bin/python3.5...done.

warning: exec file is newer than core file.
[New LWP 356]

warning: Unexpected size of section `.reg-xstate/356' in core file.
Core was generated by `/opt/pyenv/versions/3.5.0/bin/python3.5'.

warning: Unexpected size of section `.reg-xstate/356' in core file.
#0  0x00007fb1e8695af3 in ?? ()
(gdb) bt
#0  0x00007fb1e8695af3 in ?? ()
#1  0x00007fb1e67b1213 in ?? ()
#2  0x000000000225b588 in ?? ()
#3  0x0034e2b269edb810 in ?? ()
#4  0x00000000000003ff in ?? ()
#5  0x0000000400000001 in ?? ()

我不明白为什么我得到空的回溯。也许有人可以帮我解决这个问题? 谢谢!

【问题讨论】:

  • "警告:执行文件比核心文件新。"应该已经让你怀疑了。
  • 不,这是因为核心转储的构建早于 python。
  • 没错。想想这意味着什么。

标签: python c docker gdb gunicorn


【解决方案1】:

在我为调试目的而构建的另一个容器中,我得到了这个:

不清楚“我为调试而构建”是什么意思。

一般而言,您用于分析核心转储的二进制文件必须与生成此核心转储的二进制文件完全匹配

这意味着你不能这样做:

gcc -O2 -o foo t.c
./foo  # crashes, produces core dump

gcc -g -o foo-g t.c  # note lack of -O2
gdb ./foo-g core     # will not work!

相反,你应该这样做:

gcc -g -O2 -o foo-g t.c  # optimize with debug info
cp foo-g foo
strip -g foo   # make a production binary by removing debug info

./foo             # crashes, produces a core dump
gdb ./foo-g core  # this works!

要测试两个二进制文件是否足够“相同”,您可以比较它们的符号,例如

diff <(readelf -Ws foo-g) <(readelf -Ws foo)

调试二进制可以包含剥离二进制中不存在的符号(例如LOCAL函数),但两个二进制中存在的符号必须具有相同的值。

我猜您的“为调试而构建”python3.5 与您的“生产”python3.5 不同。

【讨论】:

  • 尽管我在不同的容器中构建 python 的方式相同,但它们确实不同。非常感谢您的帮助!
  • 我终于找到了python二进制文件不同的原因。原来的容器是在ubuntu上的,但是我的debug容器是在debian上的,所以python是在不同的环境下编译的。