This is the mail archive of the
archer@sourceware.org
mailing list for the Archer project.
plan for python inferiors, threads, and events
- From: Tom Tromey <tromey at redhat dot com>
- To: Project Archer <archer at sourceware dot org>
- Date: Fri, 12 Dec 2008 12:11:25 -0700
- Subject: plan for python inferiors, threads, and events
- Reply-to: Tom Tromey <tromey at redhat dot com>
I've been looking at writing a Python API to the inferior and threads.
It got complicated enough that I thought I would post a note
describing my plan before going off and implementing it. I'd
appreciate your thoughts on the subject.
There are a few goals driving the design of this API:
* The result ought to be "pythonic" (something I think we strive for
in general), and it ought to be reasonably understandable to non-gdb
experts. That is, we don't necessarily want a direct reflection of
the underlying gdb API.
* It ought to keep working once gdb moves to multi-process. E.g., the
current "gdb.threads" stuff is not super in this regard (IMO).
* It should provide a way to be notified on inferior status changes --
at least notification of when the inferior stops, and why.
Given this, I came up with the below. This is just the minimum; I
picture us adding more attributes and methods over time.
class gdb.Inferior
Represents a single inferior.
Some attributes:
* pid. The inferior pid. It isn't clear how useful this is to
expose, given remote debugging and whatnot.
* threads. A tuple holding all the currently existing threads of
this inferior. A "live" inferior always has at least one thread.
When the threads change internally, the implementation will update
this tuple.
Note that gdb internally keeps a global list of all threads. So,
segregating threads according to the inferior is an abstraction we
would supply under the hood.
See below for thread details.
Maybe we need some events here? "thread_started"? Events to notify
changes in the overall inferior state?
Some methods:
* run. Start the inferior.
A few things I am not as sure about:
* Add method to fetch the command-line arguments? There are other
per-inferior attributes like this, too: working directory,
environment. Maybe some gdb-side settings, like target-charset.
* Should we move gdb.objfiles here? Abstractly, I would say yes.
The intent of the multiprocess branch here is not clear to me,
though.
* I'd like to have a constructor so that user code can easily set up
a new Inferior, with some arguments, and start it. Perhaps for
the time being we could do this by restricting gdb to a single
Inferior instance... ?
class gdb.InferiorThread
This represents a single inferior thread.
I didn't name this "Thread" since there is already a commonly-used
Python class of that name... or maybe we should use Thread and just
let packages work their magic?
Some attributes:
* Maybe ptid? The thread id.
* state. The state of the thread -- running, stopped, etc. This
means taking the various is_* functions from gdb and turning them
into a set of state values.
* stop_event. An event which is fired when a thread stops. The
stop reason (struct bpstats) would be passed as an argument. See
below for info about events.
It isn't totally clear that this is the correct abstraction. In
some modes (non-stop), I think it is. In all-stop, it seems less
clear.
* continue_event. Fired with no arguments when the thread starts
running again.
* exited_event. Fired when the thread exits.
Right now, no methods. It seems like we'd want a way to let user
code request a stop ("interrupt the inferior now")... should this be
on Thread or on Inferior?
class gdb.Event
An event is just a container. User code puts functions into the
container. Firing an event just means walking through all the
functions, and calling them with whatever arguments the event has.
Methods:
* connect (function). Add function.
* disconnect (function). Remove function.
* emit (args). Fire the event.
The names here are inspired by GObject. However, I dislike using
strings for event names; why not just use Python attributes instead?
So rather than the Gtk-ish:
thread.connect("stop", callback)
We will have:
thread.stop_event.connect(callback)
I think we can reuse this class in other places, eventually.
Tom