【问题标题】:Why did I get a Segmentation Fault in Python when /tmp is mounted with noexec?为什么在使用 noexec 挂载 /tmp 时在 Python 中出现分段错误?
【发布时间】:2015-04-05 23:16:10
【问题描述】:

我正在 Linux 的 CherryPy 上运行自定义 Python 2.7.3 应用程序。当我使用 /etc/init.d/ 中的服务脚本来启动或停止服务时,我遇到了分段错误 (SIGSEGV)。奇怪的是,如果我使用“python /path/to/file.py --stop”从 shell 手动运行启动或停止命令,我没有收到 SIGSEGV。服务脚本执行相同的命令。

经过一些调试后,我偶然发现我的 /tmp 挂载了一个“noexec”选项。我删除了“noexec”选项,应用程序能够通过服务脚本启动和停止,没有任何分段错误。

当我第一次遇到这个问题时,我运行了 strace 并生成了一个核心转储。这两种工具都没有给我任何迹象表明 /tmp 是罪魁祸首。我的问题是:我如何使用 strace 或 gdb 来帮助我确定 /tmp 上的“noexec”导致了分段错误?

这是分析核心转储时 gdb 的一些输出:

(gdb) bt 已满 #0 PyObject_Malloc (nbytes=4) at Objects/obmalloc.c:788 bp = 0x7f6b0fd1c6e800 \地址0x7f6b0fd1c6e800越界\ 池 = 0x7f6b0fd1c000 下一个 = \优化出来的值\ 大小 = 0 #1 0x00007f6b0f7fd8e6 in _PyUnicode_New (length=1) at Objects/unicodeobject.c:345 新尺寸 = 4 unicode = 0x3873480 #2 PyUnicodeUCS2_FromUnicode 中的 0x00007f6b0f7fdd4e (u=0x38367cc, size=) 在对象/unicodeobject.c:461 unicode = \value 优化出来\

(还有很多输出,这只是前几行)

以下是 strace 关于失败的一些输出:

3046 打开(“/usr/local/python2.7/lib/python2.7/site-packages/oauthlib/common.py”,O_RDONLY)= 9 3046 fstat(9, {st_mode=S_IFREG|0644, st_size=13310, ...}) = 0 3046 打开(“/usr/local/python2.7/lib/python2.7/site-packages/oauthlib/common.pyc”,O_RDONLY)= 10 3046 fstat(10, {st_mode=S_IFREG|0644, st_size=16043, ...}) = 0 3046 mmap(NULL,4096,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0)= 0x7fbc9ff9d000 3046 读取(10, "\3\363\r\n}\321\322Tc\0\0\0\0\0\0\0\0\5\0\0\0@@\2\0sd\ 2\0\0d\0"..., 4096) = 4096 3046 fstat(10, {st_mode=S_IFREG|0644, st_size=16043, ...}) = 0 3046 读取(10,“\0\0\0C@\2\0s\330\0\0\0t\0\0|\0\0t\1\0\203\2\0s\36\0t\0 \0|\0"..., 8192) = 8192 3046 读取(10,“thon2.7/site-packages/oauthlib/c”...,4096)= 3755 3046 读取(10,“”,4096)= 0 3046 关闭(10)= 0 3046 munmap(0x7fbc9ff9d000,4096)= 0 3046 --- SIGSEGV(分段错误)@ 0 (0) ---

解决问题后,这是一个来自 strace 的 sn-p,来自它尝试加载 oauthlib/common.pyc 的同一点 - 请注意,唯一的区别似乎是 munmap() 之前的 brk():

3416 打开(“/usr/local/python2.7/lib/python2.7/site-packages/oauthlib/common.pyc”,O_RDONLY)= 10 3416 fstat(10,{st_mode=S_IFREG|0644,st_size=16043,...})= 0 3416 mmap(NULL,4096,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0)= 0x7f5791f2c000 3416 读(10, "\3\363\r\n}\321\322Tc\0\0\0\0\0\0\0\0\5\0\0\0@@\2\0sd\ 2\0\0d\0"..., 4096) = 4096 3416 fstat(10,{st_mode=S_IFREG|0644,st_size=16043,...})= 0 3416 读(10,“\0\0\0C@\2\0s\330\0\0\0t\0\0|\0\0t\1\0\203\2\0s\36\0t\0 \0|\0"..., 8192) = 8192 3416 读取(10,“thon2.7/site-packages/oauthlib/c”...,4096)= 3755 3416 读取(10,“”,4096)= 0 3416 brk(0x372f000) = 0x372f000 3416 关闭(10)= 0 3416 munmap(0x7f5791f2c000, 4096) = 0 3416 关闭(9)= 0

哪些信息可以帮助我将责任归咎于 /tmp 的挂载选项?

【问题讨论】:

  • strace diff 可能没用;相反,获取python的调试版本(在ubuntu上很容易,但必须是系统范围的而不是virtualenv),并尝试找出为无效的指针分配的空间。附言cmd 行和 init.d/cron.d 之间的区别在于环境变量——在您的启动脚本中记录env,您应该能够模拟从 cmd 行执行。例如$TMP $PATH $LD_LIBRARY_PATH 可能不同。
  • 还有bugzilla.redhat.com/show_bug.cgi?id=674369请追踪它并向python上游打开错误
  • 你的应用程序是纯python还是调用C语言编写的代码?
  • @MarkPlotnick - 它是纯 Python。我相信 Python 解释器有时会调用 C 代码

标签: python debugging gdb segmentation-fault strace


【解决方案1】:

对于那些与我有同样问题并找到此页面的人: 我的 CherryPy server.py 在 python3.8 上的 Win10 系统上运行良好,但在具有 python3.6.1 的 Linux 系统上因分段错误而失败。 在 Linux 上切换到 python3.8 解决了我的问题。

【讨论】:

    猜你喜欢
    • 2013-07-16
    • 2021-03-04
    • 2015-01-27
    • 1970-01-01
    • 2011-10-11
    • 2011-12-23
    • 1970-01-01
    • 1970-01-01
    • 2012-02-28
    相关资源
    最近更新 更多