Table Of Contents

Next topic

mmf.async.server

This Page

mmf.async.remote_debug

listen([password, verbose]) Start debug listener for the current process.

Module to allow a user on a unix system to interrupt a running process, connect to it, inspect variables, and then restart.

Based on a recipe by Brian McErlean:

http://code.activestate.com/recipes/576515/

Usage

Start a process and run listen(). This will register a signal handler and print out a message about what signal to send:

>>> import mmf.async.remote_debug
>>> mmf.async.remote_debug.example()    
Debug listener started for process 12578.
Start winpdb and send signal 30 to process 12578.
With a shell you can do this as:

winpdb& kill -%i %i

Original Documentation

This provides code to allow any python program which uses it to be interrupted at the current point, and communicated with via a normal python interactive console. This allows the locals, globals and associated program state to be investigated, as well as calling arbitrary functions and classes.

To use, a process should import the module, and call listen() at any point during startup. To interrupt this process, the script can be run directly, giving the process Id of the process to debug as the parameter.

Discussion

This was written to deal with a problem I had with a long-running background process that would occassionally get stuck after a long time. This was difficult to reproduce when testing, so I wrote the above code so that when it did happen, I’d be able to break in and see what was going on.

Its implemented by first sending the process to debug a signal, and then opening a pair of pipes with the name /tmp/debug-pid.in and /tmp/debug-pid.out. The remote process, on receiving the signal, opens the other end of this pipe and these are used to pass code to be executed from the debugging process, and read responses from the debugee.

There are a few warnings to make:

  • There is absolutely no security here - pretty much anyone who can write to the pipe can gain full control of any process using this. Use only for developer environments, not live systems!
  • Sending a signal can interrupt whatever I/O or activity the process is currently doing, so you won’t always just be able to detach again and let it run unchanged.
  • It uses signals to wake the process, so currently only works on unix-like systems that support this.
  • Untested with threads

Updated Documentation

Details of Operation

The way this works is that the original process calls listen() which registers a signal handler – either _remote_pdb_handler() or _pdb_handler() – to be called when it receives _REMOTE_SIGNAL.

The handler then creates an instance of pdb.Pdb attached to two named handles name’.in’ and name’.out’ where name is returned by _pipename() and contains the process id: Thus there is a unique pair of named pipes for each process that runs listen().

Another process can then be used to remotely debug the process by: 1) sending signal _REMOTE_SIGNAL to the process. 2) reading output from the named pipe name.out 3) sending pdb commands to the named pipe name.in

This could all be done using the shell as follows:

:math:` kill -_REMOTE_SIGNAL pid
` cat < name.out& cat > name.in

There are some issues with the persistence of the pipes etc. Originally we created these in the handler, but then the execution halts in the handler and as soon as the handler exits, the pipes are closed. We now rely on Pdb to close the pipes when it exits, and rely on an atexit hook to delete the pipes (which means that they may still remain if the original process is killed suddenly).

Examples

Known Bugs

Todo

Make the handlers check to see if the process is already being debugged. If so, don’t start a new debugger (otherwise one will start debugging the debugger internals!) Print a message for the user.

Todo

Make a pythonic version of the client that will ensure the streams are properly closed. Right now, Ctrl-c on the terminal will hang the process.

mmf.async.remote_debug.listen(password='password', verbose=True)[source]

Start debug listener for the current process.

This registers a signal handler so that debug_process() can be used to inspect the current process.

Parameters :

password : str, optional

This is the password required to connect with winpdb. If it is not provided, then the user will be prompted for one right now on the running process.

verbose: bool, optional :

If True (default), then a message with the current process id will be displayed.