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.
This commit is contained in:
parent
7346b668d7
commit
ca5c20b6d3
@ -1,3 +1,11 @@
|
||||
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 Ken Werner <ken.werner@de.ibm.com>
|
||||
|
||||
* gdb/valarith.c (vector_binop): New function.
|
||||
|
@ -1,3 +1,8 @@
|
||||
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.texinfo (Basic Python): Describe solib_address and
|
||||
|
@ -20525,6 +20525,45 @@ compute values, for example, it is the only way to get the value of a
|
||||
convenience variable (@pxref{Convenience Vars}) as a @code{gdb.Value}.
|
||||
@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. For example:
|
||||
|
||||
@smallexample
|
||||
(@value{GDBP}) python
|
||||
>import threading
|
||||
>
|
||||
>class Writer():
|
||||
> def __init__(self, message):
|
||||
> self.message = message;
|
||||
> def __call__(self):
|
||||
> gdb.write(self.message)
|
||||
>
|
||||
>class MyThread1 (threading.Thread):
|
||||
> def run (self):
|
||||
> gdb.post_event(Writer("Hello "))
|
||||
>
|
||||
>class MyThread2 (threading.Thread):
|
||||
> def run (self):
|
||||
> gdb.post_event(Writer("World\n"))
|
||||
>
|
||||
>MyThread1().start()
|
||||
>MyThread2().start()
|
||||
>end
|
||||
(@value{GDBP}) Hello World
|
||||
@end smallexample
|
||||
@end defun
|
||||
|
||||
@findex gdb.write
|
||||
@defun write string
|
||||
Print a string to @value{GDBN}'s paginated standard output stream.
|
||||
|
@ -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." },
|
||||
|
@ -1,3 +1,8 @@
|
||||
2010-08-11 Phil Muldoon <pmuldoon@redhat.com>
|
||||
|
||||
* gdb.python/python.exp (gdb_py_test_multiple): Add gdb.post_event
|
||||
tests.
|
||||
|
||||
2010-08-11 Ken Werner <ken.werner@de.ibm.com>
|
||||
|
||||
* gdb.base/Makefile.in (EXECUTABLES): Add gnu_vector.
|
||||
|
@ -120,6 +120,20 @@ gdb_test_no_output \
|
||||
"python x = gdb.execute('printf \"%d\", 23', to_string = True)"
|
||||
gdb_test "python print x" "23"
|
||||
|
||||
# Test post_event.
|
||||
gdb_py_test_multiple "post event insertion" \
|
||||
"python" "" \
|
||||
"someVal = 0" "" \
|
||||
"class Foo():" "" \
|
||||
" def __call__(self):" "" \
|
||||
" global someVal" "" \
|
||||
" someVal += 1" "" \
|
||||
"gdb.post_event(Foo())" "" \
|
||||
"end" ""
|
||||
|
||||
gdb_test "python print someVal" "1" "test post event execution"
|
||||
gdb_test "python gdb.post_event(str(1))" "RuntimeError: Posted event is not callable.*" "Test non callable class"
|
||||
|
||||
# Test (no) pagination of the executed command.
|
||||
gdb_test "show height" {Number of lines gdb thinks are in a page is unlimited\.}
|
||||
set lines 10
|
||||
|
Loading…
Reference in New Issue
Block a user