How to control gdb using Python subprocess.Popen?
Question: So I'm writing (or at least trying to) a program to compare the outputs of two
gdb runs in python. This is what I have so far:

    
    
    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
    

Now the problem is that this doesn't seem to be working. Any ideas on where I
might be going wrong?

More detail: The point of the program is to take in an executable, break at
the main function, and then run through each until the output varies between
the two. This is intended as a debugging tool (that I would use, even if no
one else would!). Then when you find a difference it gives you the choice of
whether to end the program, or to continue. In theory, this should work, but
I'm just not sure what's messing up.


Answer: `.communicate` waits for a `Popen` object to finish execution. Since you are
trying to talk to gdb while it's running, this will just hang forever. gdb
isn't going to exit without any input. Additionally you need to write the
newlines yourself to emulate the user hitting _enter_.

what you want to do is write into and read from gdb while it is executing. For
this, use `p1.stdin.write('break main\n')` (note the `'\n'`) when sending
input, and `p1.stdout.readline()` when reading output. This applies to the
break in the beginning, the args you are sending, and the continues.

On sending the arguments and beggining executing, you should also be sure to
`start` gdb.

    
    
    p1.stdin.write('start ' + args1 + '\n')
    p2.stdin.write('start ' + args2 + '\n')
    

You also want to handle the case where one process terminates before another.
You can use `Popen.poll` to check if a process has completed yet, it will
return `None` if it has not. Although this may not be exactly how you want to
handle it, you can change the top of your loop to something like this:

    
    
    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()
    

Reading a single line will likely not be correct, and you will have to
calibrate the number of lines you read in order to get the correct output.

You should either add reads to `stderr`, or send it to `/dev/null` if you
don't care about it. If you don't do either of these, the PIPE buffer can fill
and cause it to hang.

