diff options
author | Phil Muldoon <pmuldoon@redhat.com> | 2010-08-11 20:54:12 +0000 |
---|---|---|
committer | Phil Muldoon <pmuldoon@redhat.com> | 2010-08-11 20:54:12 +0000 |
commit | ca5c20b6d32018c05a1c20a099a71137b4b27a4d (patch) | |
tree | 482c9088571e90381ebc0739179e47c8e3c0f1f8 /gdb/python/python.c | |
parent | 7346b668d73fe13b9b07b805379ff0e03d3aef5e (diff) | |
download | gdb-ca5c20b6d32018c05a1c20a099a71137b4b27a4d.zip gdb-ca5c20b6d32018c05a1c20a099a71137b4b27a4d.tar.gz gdb-ca5c20b6d32018c05a1c20a099a71137b4b27a4d.tar.bz2 |
2010-08-11 Tom Tromey <tromey@redhat.com>
Phil Muldoon <pmuldoon@redhat.com>
* python/python.c (gdbpy_run_events): New function.
(gdbpy_post_event): Likewise.
(gdbpy_initialize_events): Likewise.
(_initialize_python): Call gdbpy_initialize_events.
2010-08-11 Tom Tromey <tromey@redhat.com>
Phil Muldoon <pmuldoon@redhat.com>
* gdb.texinfo (Basic Python): Describe post_event API.
2010-08-11 Phil Muldoon <pmuldoon@redhat.com>
* gdb.python/python.exp (gdb_py_test_multiple): Add gdb.post_event
tests.
Diffstat (limited to 'gdb/python/python.c')
-rw-r--r-- | gdb/python/python.c | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/gdb/python/python.c b/gdb/python/python.c index 16c3cba..030b142 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -28,6 +28,7 @@ #include "value.h" #include "language.h" #include "exceptions.h" +#include "event-loop.h" #include <ctype.h> @@ -548,6 +549,114 @@ source_python_script (FILE *stream, const char *file) +/* Posting and handling events. */ + +/* A single event. */ +struct gdbpy_event +{ + /* The Python event. This is just a callable object. */ + PyObject *event; + /* The next event. */ + struct gdbpy_event *next; +}; + +/* All pending events. */ +static struct gdbpy_event *gdbpy_event_list; +/* The final link of the event list. */ +static struct gdbpy_event **gdbpy_event_list_end; + +/* We use a file handler, and not an async handler, so that we can + wake up the main thread even when it is blocked in poll(). */ +static int gdbpy_event_fds[2]; + +/* The file handler callback. This reads from the internal pipe, and + then processes the Python event queue. This will always be run in + the main gdb thread. */ +static void +gdbpy_run_events (int err, gdb_client_data ignore) +{ + struct cleanup *cleanup; + char buffer[100]; + int r; + + cleanup = ensure_python_env (get_current_arch (), current_language); + + /* Just read whatever is available on the fd. It is relatively + harmless if there are any bytes left over. */ + r = read (gdbpy_event_fds[0], buffer, sizeof (buffer)); + + while (gdbpy_event_list) + { + /* Dispatching the event might push a new element onto the event + loop, so we update here "atomically enough". */ + struct gdbpy_event *item = gdbpy_event_list; + gdbpy_event_list = gdbpy_event_list->next; + if (gdbpy_event_list == NULL) + gdbpy_event_list_end = &gdbpy_event_list; + + /* Ignore errors. */ + if (PyObject_CallObject (item->event, NULL) == NULL) + PyErr_Clear (); + + Py_DECREF (item->event); + xfree (item); + } + + do_cleanups (cleanup); +} + +/* Submit an event to the gdb thread. */ +static PyObject * +gdbpy_post_event (PyObject *self, PyObject *args) +{ + struct gdbpy_event *event; + PyObject *func; + int wakeup; + + if (!PyArg_ParseTuple (args, "O", &func)) + return NULL; + + if (!PyCallable_Check (func)) + { + PyErr_SetString (PyExc_RuntimeError, + _("Posted event is not callable")); + return NULL; + } + + Py_INCREF (func); + + /* From here until the end of the function, we have the GIL, so we + can operate on our global data structures without worrying. */ + wakeup = gdbpy_event_list == NULL; + + event = XNEW (struct gdbpy_event); + event->event = func; + event->next = NULL; + *gdbpy_event_list_end = event; + gdbpy_event_list_end = &event->next; + + /* Wake up gdb when needed. */ + if (wakeup) + { + char c = 'q'; /* Anything. */ + if (write (gdbpy_event_fds[1], &c, 1) != 1) + return PyErr_SetFromErrno (PyExc_IOError); + } + + Py_RETURN_NONE; +} + +/* Initialize the Python event handler. */ +static void +gdbpy_initialize_events (void) +{ + if (!pipe (gdbpy_event_fds)) + { + gdbpy_event_list_end = &gdbpy_event_list; + add_file_handler (gdbpy_event_fds[0], gdbpy_run_events, NULL); + } +} + /* Printing. */ /* A python function to write a single string using gdb's filtered @@ -854,6 +963,7 @@ Enables or disables printing of Python stack traces."), gdbpy_initialize_lazy_string (); gdbpy_initialize_thread (); gdbpy_initialize_inferior (); + gdbpy_initialize_events (); PyRun_SimpleString ("import gdb"); PyRun_SimpleString ("gdb.pretty_printers = []"); @@ -974,6 +1084,9 @@ gdb.Symtab_and_line objects (or None)."}, Parse String as an expression, evaluate it, and return the result as a Value." }, + { "post_event", gdbpy_post_event, METH_VARARGS, + "Post an event into gdb's event loop." }, + { "target_charset", gdbpy_target_charset, METH_NOARGS, "target_charset () -> string.\n\ Return the name of the current target charset." }, |