1

So, I have some code like this:

class ProgressProc(multiprocessing.Process):
    def __init__(self):
        multiprocessing.Process.__init__(self)

    def run(self):
        while True:
            markProgress()
            time.sleep(10)

progressProc = ProgressProc()
progressProc.start()
doSomething()
progressProc.terminate()

The problem is, if I do pdb.set_trace() inside the doSomething() function, the ProgressProc process keeps going. It keeps printing stuff to the console while the pdb prompt is active. What I would like is to have some way for ProgressProc to check if the main thread (really, any other thread) is suspended in pdb and then I can skip markProgress().

There's sys.gettrace(), but that only works for the thread that did the pdb.set_trace() and I can't figure out how to call it on a different thread than the one I'm in. What else can I do? Are there any signals I can catch? I could have my main method replace pdb.set_trace to call some multiprocessing.Event first. Is there any cleaner way?

ETA: This is also for a python gdb command.

Jason Raff
  • 11
  • 3

1 Answers1

1

Debugging with multiple threads or processes is currently not possible with Pdb. However, I hope the following can help you.

This solution suspends the main thread with Pdb and then sends a signal to the other process where Rpdb is started.

Open a socket in run. Make sure to set the timeout to 0. When the process receives a signal, start Rpdb with rpdb.set_trace().

signal = 'break'
address = ('localhost', 6000)

def run(self):
    listener = Listener(address=address)
    listener._listener._socket.settimeout(0)
    recvd = False
    while True:
        markProgress()
        if not recvd:
            try:
                conn = listener.accept()
                msg = conn.recv()
                if msg == signal:
                    recvd = True
                    rpdb.set_trace()
            except:
                pass
        time.sleep(2)

Do set_trace() inside doSomething() like before, then connect to the socket and send the signal.

def doSomething():
    pdb.set_trace()
    conn = Client(address)
    conn.send(signal)
    conn.close()
    for x in range(100):
        time.sleep(1)
        sys.__stdout__.write("doSomething: " + str(x) + "\n")

Now you can start your program. After the signal is sent, you should get the output pdb is running on 127.0.0.1:4444. Now open a second terminal and connect to Rpdb with nc localhost 4444.

  • This only works with two processes/threads. If you want to work with more, you could try starting Rpdb with a different port for each process, like this: rpdb.Rpdb(port=12345)
  • You may have to change all your prints to sys.__stdout__.write, because Rpdb changes stdout.
Nbfour
  • 145
  • 3
  • 10