在不需要的系统调用上引发异常

gue*_*tli 4 python debugging system-calls

有人告诉我修复旧应用程序中的错误。

我可以重现一个错误,但是我不知道该错误会在哪个python源代码行执行。

我可以看到有关的故障strace:文件被打开,该文件不应该被打开。

我想使相关的open()linux-syscall在python解释器中引发异常。我的目标:我希望看到stacktrace能够修复该错误。

这样,我可以避免在调试器中花很多时间来遍历许多行。

换句话说:如果执行了syscall,这会导致open("/somefile", O_RDONLY) = 4python解释器的strace输出应以traceback退出。

有没有人解决?

如果您不明白我在寻找什么,请发表评论。

zsr*_*myn 5

我们可以open在导入模块之前做一个补丁,这是一个例子:

test.py

def func():
    with open('test', 'w') as f:
        pass
Run Code Online (Sandbox Code Playgroud)

test2.py

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()
Run Code Online (Sandbox Code Playgroud)

并在func()中调用时test2.py,将显示调用堆栈:

$ 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()
Run Code Online (Sandbox Code Playgroud)


Leo*_*eon 4

您可以在 gdb 下运行 python,在open()系统调用(或者更确切地说,libc 中调用它的存根函数)上设置一个(条件)断点,并且当断点被击中时,SIGINT向 python 进程发送一个信号并让它继续,然后 python 脚本的执行应该被所需的堆栈跟踪中断。

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

用法:

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


stack_trace_on_open

#!/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
Run Code Online (Sandbox Code Playgroud)

示范:

$ 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)
Run Code Online (Sandbox Code Playgroud)