[PATCH 18/28] check gdb_python_initialized everywhere

Tom Tromey
2013-04-19T14:38:36Z

This patch changes the rest of gdb to use gdb_python_initialized. It
also changes ensure_python_env to throw an exception if Python is not
initialized. In some spots no other checks were needed -- there is no
way to reach some of the calls to ensure_python_env unless some
previous call into Python was made.

value_get_print_value had to be reindented, which is why that part of
the patch looks odd.

While sending out the series I realized I had meant to write a test case
for this patch but forgot to. I will hold on to this one until I write
it.

* mi/mi-main.c: Include python-internal.h.
(mi_cmd_list_features): Check gdb_python_initialized.
* python/py-inferior.c (python_on_normal_stop, python_on_resume)
(python_inferior_exit, python_new_objfile, add_thread_object)
(delete_thread_object, py_free_inferior): Check
gdb_python_initialized.
* python/py-prettyprint.c (apply_val_pretty_printer): Check
gdb_python_initialized.
* python/py-type.c (save_objfile_types): Check
gdb_python_initialized.
* python/python-internal.h (gdb_python_initialized): Declare.
* python/python.c (ensure_python_env): Throw exception if
Python not initialized.
(before_prompt_hook, source_python_script_for_objfile)
(start_type_printers, apply_type_printers,
free_type_printers): Check gdb_python_initialized.
* varobj.c (varobj_get_display_hint)
(dynamic_varobj_has_child_method, update_dynamic_varobj_children)
(install_new_value_visualizer, varobj_set_visualizer)
(value_get_print_value): Check gdb_python_initialized.
---
gdb/mi/mi-main.c | 6 +-
gdb/python/py-inferior.c | 21 +++++
gdb/python/py-prettyprint.c | 3 +
gdb/python/py-type.c | 3 +
gdb/python/python-internal.h | 2 +
gdb/python/python.c | 19 +++++
gdb/varobj.c | 182 ++++++++++++++++++++++++-------------------
7 files changed, 153 insertions(+), 83 deletions(-)

diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index 94fda8f..9428e8c 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -52,6 +52,9 @@
#include "ctf.h"
#include "ada-lang.h"
#include "linespec.h"
+#ifdef HAVE_PYTHON
+#include "python/python-internal.h"
+#endif

#include <ctype.h>
#include <sys/time.h>
@@ -1757,7 +1760,8 @@ mi_cmd_list_features (char *command, char **argv, int argc)
ui_out_field_string (uiout, NULL, "ada-task-info");

#if HAVE_PYTHON
- ui_out_field_string (uiout, NULL, "python");
+ if (gdb_python_initialized)
+ ui_out_field_string (uiout, NULL, "python");
#endif

do_cleanups (cleanup);
diff --git a/gdb/python/py-inferior.c b/gdb/python/py-inferior.c
index b11d786..1ab58e6 100644
--- a/gdb/python/py-inferior.c
+++ b/gdb/python/py-inferior.c
@@ -85,6 +85,9 @@ python_on_normal_stop (struct bpstats *bs, int print_frame)
struct cleanup *cleanup;
enum gdb_signal stop_signal;

+ if (!gdb_python_initialized)
+ return;
+
if (!find_thread_ptid (inferior_ptid))
return;

@@ -103,6 +106,9 @@ python_on_resume (ptid_t ptid)
{
struct cleanup *cleanup;

+ if (!gdb_python_initialized)
+ return;
+
cleanup = ensure_python_env (target_gdbarch (), current_language);

if (emit_continue_event (ptid) < 0)
@@ -117,6 +123,9 @@ python_inferior_exit (struct inferior *inf)
struct cleanup *cleanup;
const LONGEST *exit_code = NULL;

+ if (!gdb_python_initialized)
+ return;
+
cleanup = ensure_python_env (target_gdbarch (), current_language);

if (inf->has_exit_code)
@@ -139,6 +148,9 @@ python_new_objfile (struct objfile *objfile)
if (objfile == NULL)
return;

+ if (!gdb_python_initialized)
+ return;
+
cleanup = ensure_python_env (get_objfile_arch (objfile), current_language);

if (emit_new_objfile_event (objfile) < 0)
@@ -231,6 +243,9 @@ add_thread_object (struct thread_info *tp)
inferior_object *inf_obj;
struct threadlist_entry *entry;

+ if (!gdb_python_initialized)
+ return;
+
cleanup = ensure_python_env (python_gdbarch, python_language);

thread_obj = create_thread_object (tp);
@@ -260,6 +275,9 @@ delete_thread_object (struct thread_info *tp, int ignore)
inferior_object *inf_obj;
struct threadlist_entry **entry, *tmp;

+ if (!gdb_python_initialized)
+ return;
+
cleanup = ensure_python_env (python_gdbarch, python_language);

inf_obj = (inferior_object *) find_inferior_object (PIDGET(tp->ptid));
@@ -728,6 +746,9 @@ py_free_inferior (struct inferior *inf, void *datum)
inferior_object *inf_obj = datum;
struct threadlist_entry *th_entry, *th_tmp;

+ if (!gdb_python_initialized)
+ return;
+
cleanup = ensure_python_env (python_gdbarch, python_language);

inf_obj->inferior = NULL;
diff --git a/gdb/python/py-prettyprint.c b/gdb/python/py-prettyprint.c
index dbf6c22..c337334 100644
--- a/gdb/python/py-prettyprint.c
+++ b/gdb/python/py-prettyprint.c
@@ -708,6 +708,9 @@ apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr,
if (!value_bytes_available (val, embedded_offset, TYPE_LENGTH (type)))
return 0;

+ if (!gdb_python_initialized)
+ return 0;
+
cleanups = ensure_python_env (gdbarch, language);

/* Instantiate the printer. */
diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c
index 05e251b..dd3a751 100644
--- a/gdb/python/py-type.c
+++ b/gdb/python/py-type.c
@@ -1192,6 +1192,9 @@ save_objfile_types (struct objfile *objfile, void *datum)
htab_t copied_types;
struct cleanup *cleanup;

+ if (!gdb_python_initialized)
+ return;
+
/* This prevents another thread from freeing the objects we're
operating on. */
cleanup = ensure_python_env (get_objfile_arch (objfile), current_language);
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 63d020d..4a9405f 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -183,6 +183,8 @@ struct program_space;
struct bpstats;
struct inferior;

+extern int gdb_python_initialized;
+
extern PyObject *gdb_module;
extern PyObject *gdb_python_module;
extern PyTypeObject value_object_type
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 51f8cd5..a7b1b44 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -150,6 +150,10 @@ ensure_python_env (struct gdbarch *gdbarch,
{
struct python_env *env = xmalloc (sizeof *env);

+ /* We should not ever enter Python unless initialized. */
+ if (!gdb_python_initialized)
+ error (_("Python not initialized"));
+
env->state = PyGILState_Ensure ();
env->gdbarch = python_gdbarch;
env->language = python_language;
@@ -896,6 +900,9 @@ before_prompt_hook (const char *current_gdb_prompt)
struct cleanup *cleanup;
char *prompt = NULL;

+ if (!gdb_python_initialized)
+ return;
+
cleanup = ensure_python_env (get_current_arch (), current_language);

if (gdb_python_module
@@ -1159,6 +1166,9 @@ source_python_script_for_objfile (struct objfile *objfile, FILE *file,
{
struct cleanup *cleanups;

+ if (!gdb_python_initialized)
+ return;
+
cleanups = ensure_python_env (get_objfile_arch (objfile), current_language);
gdbpy_current_objfile = objfile;

@@ -1220,6 +1230,9 @@ start_type_printers (void)
struct cleanup *cleanups;
PyObject *type_module, *func, *result_obj = NULL;

+ if (!gdb_python_initialized)
+ return NULL;
+
cleanups = ensure_python_env (get_current_arch (), current_language);

type_module = PyImport_ImportModule ("gdb.types");
@@ -1266,6 +1279,9 @@ apply_type_printers (void *printers, struct type *type)
if (printers_obj == NULL)
return NULL;

+ if (!gdb_python_initialized)
+ return NULL;
+
cleanups = ensure_python_env (get_current_arch (), current_language);

type_obj = type_to_type_object (type);
@@ -1324,6 +1340,9 @@ free_type_printers (void *arg)
if (printers == NULL)
return;

+ if (!gdb_python_initialized)
+ return;
+
cleanups = ensure_python_env (get_current_arch (), current_language);
Py_DECREF (printers);
do_cleanups (cleanups);
diff --git a/gdb/varobj.c b/gdb/varobj.c
index 467e59a..70ed28f 100644
--- a/gdb/varobj.c
+++ b/gdb/varobj.c
@@ -935,7 +935,12 @@ varobj_get_display_hint (struct varobj *var)
char *result = NULL;

#if HAVE_PYTHON
- struct cleanup *back_to = varobj_ensure_python_env (var);
+ struct cleanup *back_to;
+
+ if (!gdb_python_initialized)
+ return NULL;
+
+ back_to = varobj_ensure_python_env (var);

if (var->pretty_printer)
result = gdbpy_get_display_hint (var->pretty_printer);
@@ -1067,6 +1072,9 @@ dynamic_varobj_has_child_method (struct varobj *var)
PyObject *printer = var->pretty_printer;
int result;

+ if (!gdb_python_initialized)
+ return 0;
+
back_to = varobj_ensure_python_env (var);
result = PyObject_HasAttr (printer, gdbpy_children_cst);
do_cleanups (back_to);
@@ -1092,6 +1100,9 @@ update_dynamic_varobj_children (struct varobj *var,
int i;
PyObject *printer = var->pretty_printer;

+ if (!gdb_python_initialized)
+ return 0;
+
back_to = varobj_ensure_python_env (var);

*cchanged = 0;
@@ -1623,6 +1634,9 @@ install_new_value_visualizer (struct varobj *var)
#if HAVE_PYTHON
/* If the constructor is None, then we want the raw value. If VAR
does not have a value, just skip this. */
+ if (!gdb_python_initialized)
+ return;
+
if (var->constructor != Py_None && var->value)
{
struct cleanup *cleanup;
@@ -1899,6 +1913,9 @@ varobj_set_visualizer (struct varobj *var, const char *visualizer)
PyObject *mainmod, *globals, *constructor;
struct cleanup *back_to;

+ if (!gdb_python_initialized)
+ return;
+
back_to = varobj_ensure_python_env (var);

mainmod = PyImport_AddModule ("__main__");
@@ -2862,92 +2879,93 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,

gdbarch = get_type_arch (value_type (value));
#if HAVE_PYTHON
- {
- PyObject *value_formatter = var->pretty_printer;
+ if (gdb_python_initialized)
+ {
+ PyObject *value_formatter = var->pretty_printer;

- varobj_ensure_python_env (var);
+ varobj_ensure_python_env (var);

- if (value_formatter)
- {
- /* First check to see if we have any children at all. If so,
- we simply return {...}. */
- if (dynamic_varobj_has_child_method (var))
- {
- do_cleanups (old_chain);
- return xstrdup ("{...}");
- }
+ if (value_formatter)
+ {
+ /* First check to see if we have any children at all. If so,
+ we simply return {...}. */
+ if (dynamic_varobj_has_child_method (var))
+ {
+ do_cleanups (old_chain);
+ return xstrdup ("{...}");
+ }

- if (PyObject_HasAttr (value_formatter, gdbpy_to_string_cst))
- {
- struct value *replacement;
- PyObject *output = NULL;
+ if (PyObject_HasAttr (value_formatter, gdbpy_to_string_cst))
+ {
+ struct value *replacement;
+ PyObject *output = NULL;

- output = apply_varobj_pretty_printer (value_formatter,
- &replacement,
- stb);
+ output = apply_varobj_pretty_printer (value_formatter,
+ &replacement,
+ stb);

- /* If we have string like output ... */
- if (output)
- {
- make_cleanup_py_decref (output);
-
- /* If this is a lazy string, extract it. For lazy
- strings we always print as a string, so set
- string_print. */
- if (gdbpy_is_lazy_string (output))
- {
- gdbpy_extract_lazy_string (output, &str_addr, &type,
- &len, &encoding);
- make_cleanup (free_current_contents, &encoding);
- string_print = 1;
- }
- else
- {
- /* If it is a regular (non-lazy) string, extract
- it and copy the contents into THEVALUE. If the
- hint says to print it as a string, set
- string_print. Otherwise just return the extracted
- string as a value. */
-
- char *s = python_string_to_target_string (output);
-
- if (s)
- {
- char *hint;
-
- hint = gdbpy_get_display_hint (value_formatter);
- if (hint)
- {
- if (!strcmp (hint, "string"))
- string_print = 1;
- xfree (hint);
- }
-
- len = strlen (s);
- thevalue = xmemdup (s, len + 1, len + 1);
- type = builtin_type (gdbarch)->builtin_char;
- xfree (s);
-
- if (!string_print)
- {
- do_cleanups (old_chain);
- return thevalue;
- }
-
- make_cleanup (xfree, thevalue);
- }
- else
- gdbpy_print_stack ();
- }
- }
- /* If the printer returned a replacement value, set VALUE
- to REPLACEMENT. If there is not a replacement value,
- just use the value passed to this function. */
- if (replacement)
- value = replacement;
- }
- }
- }
+ /* If we have string like output ... */
+ if (output)
+ {
+ make_cleanup_py_decref (output);
+
+ /* If this is a lazy string, extract it. For lazy
+ strings we always print as a string, so set
+ string_print. */
+ if (gdbpy_is_lazy_string (output))
+ {
+ gdbpy_extract_lazy_string (output, &str_addr, &type,
+ &len, &encoding);
+ make_cleanup (free_current_contents, &encoding);
+ string_print = 1;
+ }
+ else
+ {
+ /* If it is a regular (non-lazy) string, extract
+ it and copy the contents into THEVALUE. If the
+ hint says to print it as a string, set
+ string_print. Otherwise just return the extracted
+ string as a value. */
+
+ char *s = python_string_to_target_string (output);
+
+ if (s)
+ {
+ char *hint;
+
+ hint = gdbpy_get_display_hint (value_formatter);
+ if (hint)
+ {
+ if (!strcmp (hint, "string"))
+ string_print = 1;
+ xfree (hint);
+ }
+
+ len = strlen (s);
+ thevalue = xmemdup (s, len + 1, len + 1);
+ type = builtin_type (gdbarch)->builtin_char;
+ xfree (s);
+
+ if (!string_print)
+ {
+ do_cleanups (old_chain);
+ return thevalue;
+ }
+
+ make_cleanup (xfree, thevalue);
+ }
+ else
+ gdbpy_print_stack ();
+ }
+ }
+ /* If the printer returned a replacement value, set VALUE
+ to REPLACEMENT. If there is not a replacement value,
+ just use the value passed to this function. */
+ if (replacement)
+ value = replacement;
+ }
+ }
+ }
#endif

get_formatted_print_options (&opts, format_code[(int) format]);
--
1.8.1.4