From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 28406 invoked by alias); 10 Dec 2008 15:28:17 -0000 Mailing-List: contact archer-commits-help@sourceware.org; run by ezmlm Sender: Precedence: bulk List-Post: List-Help: List-Subscribe: Received: (qmail 28382 invoked by uid 306); 10 Dec 2008 15:28:16 -0000 Date: Wed, 10 Dec 2008 15:28:00 -0000 Message-ID: <20081210152816.28367.qmail@sourceware.org> From: tromey@sourceware.org To: archer-commits@sourceware.org Subject: [SCM] archer-tromey-python: gdb X-Git-Refname: refs/heads/archer-tromey-python X-Git-Reftype: branch X-Git-Oldrev: 170f3087305a4fbf35d06d344639534c06672965 X-Git-Newrev: ab8c44cb00aed42589972ef0e0cea4cb9d644fba X-SW-Source: 2008-q4/txt/msg00196.txt.bz2 List-Id: The branch, archer-tromey-python has been updated via ab8c44cb00aed42589972ef0e0cea4cb9d644fba (commit) from 170f3087305a4fbf35d06d344639534c06672965 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email. - Log ----------------------------------------------------------------- commit ab8c44cb00aed42589972ef0e0cea4cb9d644fba Author: Tom Tromey Date: Wed Dec 10 08:27:54 2008 -0700 gdb * python/python.c: Include event-loop.h. (struct gdbpy_event): New type. (gdbpy_event_list, gdbpy_event_list_end): New globals. (gdbpy_event_fd): Likewise. (gdbpy_run_events): New function. (gdbpy_post_event): Likewise. (gdbpy_initialize_events): Likewise. (_initialize_python): Call it. (GdbMethods) : New method. gdb/doc * gdb.texinfo (Basic Python): Document post_event. ----------------------------------------------------------------------- Summary of changes: gdb/ChangeLog | 12 +++++ gdb/doc/ChangeLog | 4 ++ gdb/doc/gdb.texinfo | 15 +++++++ gdb/python/python.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 144 insertions(+), 0 deletions(-) First 500 lines of diff: diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 86cc9ed..ef0bf91 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,15 @@ +2008-12-10 Tom Tromey + + * python/python.c: Include event-loop.h. + (struct gdbpy_event): New type. + (gdbpy_event_list, gdbpy_event_list_end): New globals. + (gdbpy_event_fd): Likewise. + (gdbpy_run_events): New function. + (gdbpy_post_event): Likewise. + (gdbpy_initialize_events): Likewise. + (_initialize_python): Call it. + (GdbMethods) : New method. + 2008-12-09 Thiago Jung Bauermann * python/python.c (gdbpy_get_threads): Rename to ... diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index b57f111..d35643c 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,7 @@ +2008-12-10 Tom Tromey + + * gdb.texinfo (Basic Python): Document post_event. + 2008-12-05 Thiago Jung Bauermann * gdb.texinfo: Fix references to renamed gdb module functions. diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 8057812..ea6698c 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -18119,6 +18119,21 @@ evaluate it, and return the result as a @code{gdb.Value}. @var{expression} must be a string. @end defun +@findex gdb.post_event +@defun post_event event +Put @var{event}, a callable object taking no arguments, into +@value{GDBN}'s internal event queue. This callable will be invoked at +some later point, during @value{GDBN}'s event processing. Events +posted using @code{post_event} will be run in the order in which they +were posted; however, there is no way to know when they will be +processed relative to other events inside @value{GDBN}. + +@value{GDBN} is not thread-safe. If your Python program uses multiple +threads, you must be careful to only call @value{GDBN}-specific +functions in the main @value{GDBN} thread. @code{post_event} ensures +this. +@end defun + @findex gdb.write @defun write string Print a string to @value{GDBN}'s paginated standard output stream. diff --git a/gdb/python/python.c b/gdb/python/python.c index 3bf3d54..1432e5e 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -27,6 +27,7 @@ #include "gdb_regex.h" #include "language.h" #include "valprint.h" +#include "event-loop.h" #include @@ -416,6 +417,113 @@ gdbpy_parse_and_eval (PyObject *self, PyObject *args) +/* 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) +{ + PyGILState_STATE state; + char buffer[100]; + int r; + + state = PyGILState_Ensure (); + + /* 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. */ + PyObject_CallObject (item->event, NULL); + + Py_DECREF (item->event); + xfree (item); + } + + PyGILState_Release (state); +} + +/* 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. */ + write (gdbpy_event_fds[1], &c, 1); + } + + 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); + } +} + + + /* Threads. */ /* Callback function for use with iterate_over_threads. This function @@ -1285,6 +1393,8 @@ Enables or disables auto-loading of Python code when an object is opened."), gdbpy_initialize_parameters (); gdbpy_initialize_objfile (); + gdbpy_initialize_events (); + PyRun_SimpleString ("import gdb"); PyRun_SimpleString ("gdb.pretty_printers = {}"); @@ -1397,6 +1507,9 @@ Note: may later change to return an object." }, { "parse_and_eval", gdbpy_parse_and_eval, METH_VARARGS, "Parse a string as an expression, evaluate it, and return the result." }, + { "post_event", gdbpy_post_event, METH_VARARGS, + "Post an event into gdb's event loop." }, + { "write", gdbpy_write, METH_VARARGS, "Write a string using gdb's filtered stream." }, { "flush", gdbpy_flush, METH_NOARGS, hooks/post-receive -- Repository for Project Archer.