首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在不需要的syscall上引发异常

在不需要的syscall上引发异常
EN

Stack Overflow用户
提问于 2017-02-26 19:05:50
回答 2查看 390关注 0票数 4

有人告诉我修复遗留应用程序中的一个bug。

我可以复制一个bug,但我不知道在哪个python源代码行中执行了错误。

我可以看到与strace相关的失败:文件被打开,而不应该被打开。

我想在python解释器中将相关的linux-syscall打开。我的目标是:我希望看到堆栈跟踪,以便能够修复这个bug。

这样,我就可以避免使用调试器跨过很多行的时间。

换句话说:如果执行syscall,导致open("/somefile", O_RDONLY) = 4的strace输出,那么python解释器应该退出并进行跟踪。

有谁有解决办法吗?

如果你不明白我在找什么,请留下评论。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-03-08 11:17:06

您可以在gdb下运行python,在open() syscall上设置一个(条件)断点(或者更确切地说,它是通过libc中的存根函数来调用它),并且在命中断点时,向process发送一个SIGINT信号,并让它继续运行,从而应该用所需的堆栈跟踪中断python脚本的执行。

下面的shell脚本自动执行该过程。

用法:

stack_trace_on_open filename -- python script.py [script args]

stack_trace_on_open

代码语言:javascript
复制
#!/usr/bin/env bash

myname="$(basename "$0")"

if [[ $# -lt 4 || "$2" != '--' ]]
then
    echo >&2 "Usage: $myname <filename> -- python <script.py> [script args ...]"
    exit 1
fi

fname=$1
python_exe="$3"
shift 3

gdb -q "$python_exe" <<END
set breakpoint pending on
break open
condition 1 strcmp(\$rdi,"$fname") == 0
run "$@"
signal 2
cont
quit
END

示范:

代码语言:javascript
复制
$ cat test.py 
import ctypes

clib = ctypes.CDLL(None)
fd = clib.open("/dev/urandom", 0)
clib.close(fd)

$ ./stack_trace_on_open /dev/urandom -- python test.py 
Reading symbols from python...(no debugging symbols found)...done.
(gdb) (gdb) Function "open" not defined.
Breakpoint 1 (open) pending.
(gdb) (gdb) Starting program: /usr/bin/python "test.py"
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, open64 () at ../sysdeps/unix/syscall-template.S:84
84  ../sysdeps/unix/syscall-template.S: No such file or directory.
(gdb) Continuing with signal SIGINT.

Breakpoint 1, open64 () at ../sysdeps/unix/syscall-template.S:84
84  in ../sysdeps/unix/syscall-template.S
(gdb) Continuing.
Traceback (most recent call last):                #     <--------
  File "test.py", line 4, in <module>             #     <--------
    fd = clib.open("/dev/urandom", 0)             #     <--------
KeyboardInterrupt
[Inferior 1 (process 14248) exited with code 01]
(gdb)
票数 4
EN

Stack Overflow用户

发布于 2017-02-26 19:39:40

在导入模块之前,我们可以在open上做一个补丁,下面是一个示例:

test.py

代码语言:javascript
复制
def func():
    with open('test', 'w') as f:
        pass

test2.py

代码语言:javascript
复制
try:
    import __builtin__ # for python2
except ImportError:
    import builtins as __builtin__ #for python3

import copy
import traceback

orig_open = copy.copy(__builtin__.open)

def myopen(*args):
    traceback.print_stack()
    return orig_open(*args)

__builtin__.open = myopen

from test import func # Note that we import the module after patching on open()

func()

func()test2.py中被调用时,调用堆栈将被打印出来:

代码语言:javascript
复制
$ python test2.py 
  File "test2.py", line 19, in <module>
    func()
  File "/tmp/test.py", line 4, in func
    with open('test', 'w') as f:
  File "test2.py", line 12, in myopen
    traceback.print_stack()
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42472864

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档