如何使用Python subprocess.Popen控制gdb?

问题描述 投票:0回答:1

所以我正在编写(或者至少尝试)一个程序来比较 python 中两个 gdb 运行的输出。这是我到目前为止所拥有的:

from subprocess import *
import subprocess

file = raw_input('enter program name (with a ./ if in local directory): ')

p1 = Popen(['gdb', file], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p2 = Popen(['gdb', file], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

p1.communicate(input='break main')
p2.communicate(input='break main')

args1 = raw_input('args for running program (from file) (ie r < input.txt): ')
args2 = raw_input('args for running program (from file) (for program 2...): ')

p1.communicate(input=args1)
p2.communicate(input=args2)

while True:
    p1out = p1.communicate(input='continue')[0]
    p2out = p2.communicate(input='continue')[0]

    if p1out != p2out:
        print 'difference: '
        print 'p1: ' + p1out
        print 'p2: ' + p2out
        cont = raw_input('continue (y/n): ')
        if cont != 'y':
            break

现在的问题是这似乎不起作用。关于我可能出错的地方有什么想法吗?

更详细:该程序的要点是接收一个可执行文件,在主函数处中断,然后运行每个函数,直到两者之间的输出有所不同。这是一种调试工具(我会使用它,即使其他人不会!)。然后,当您发现差异时,它会让您选择是否结束程序或继续。从理论上讲,这应该可行,但我只是不确定出了什么问题。

python debugging gdb syntax-error
1个回答
4
投票

.communicate
等待
Popen
对象完成执行。由于您试图在 gdb 运行时与其通信,因此这将永远挂起。如果没有任何输入,gdb 不会退出。此外,您需要自己编写换行符来模拟用户点击 enter

您想要做的是在 gdb 执行时写入和读取。为此,在发送输入时使用

p1.stdin.write('break main\n')
(注意
'\n'
),在读取输出时使用
p1.stdout.readline()
。这适用于开头的中断、您发送的参数以及继续。

在发送参数并开始执行时,您还应该确保

start
gdb。

p1.stdin.write(f'start {args1}\n')
p2.stdin.write(f'start {args2}\n')

您还想处理一个进程先于另一个进程终止的情况。您可以使用

Popen.poll
检查进程是否已完成,如果尚未完成,它将返回
None
。尽管这可能不完全是您想要的处理方式,但您可以将循环的顶部更改为如下所示:

while True:
    if p1.poll() is not None and p2.poll() is not None:
        print 'p1 and p2 have both finished'
        break
    elif p1.poll() is not None:
        print 'p1 finished before p2'
        break
    elif p2.poll() is not None:
        print 'p2 finished before p1'
        break

    p1.stdin.write('continue\n')
    p2.stdin.write('continue\n')
    p1out = p1.stdout.readline()
    p2out = p2.stdout.readline()

读取单行可能不正确,您必须校准读取的行数才能获得正确的输出。

您应该将读数添加到

stderr
,或者如果您不关心它,请将其发送到
/dev/null
。如果您不执行其中任何一项操作,PIPE 缓冲区可能会填满并导致其挂起。

© www.soinside.com 2019 - 2024. All rights reserved.