[PATCH 7/7] gdb: startup commands to control Python extension language
Andrew Burgess
andrew.burgess@embecosm.com
Thu Apr 22 21:02:48 GMT 2021
Add two new commands to GDB that can be placed into the early
initialization to control how Python starts up. The new options are:
set python ignore-environment on|off
set python dont-write-bytecode auto|on|off
show python ignore-environment
show python dont-write-bytecode
These can be used from GDB's startup file to control how the Python
extension language behaves. These options are equivalent to the -E
and -B flags to python respectively, their descriptions from the
Python man page:
-E Ignore environment variables like PYTHONPATH and PYTHONHOME
that modify the behavior of the interpreter.
-B Don't write .pyc files on import.
gdb/ChangeLog:
* NEWS: Mention new commands.
* python/python.c (python_ignore_environment): New static global.
(show_python_ignore_environment): New function.
(set_python_ignore_environment): New function.
(python_dont_write_bytecode): New static global.
(show_python_dont_write_bytecode): New function.
(set_python_dont_write_bytecode): New function.
(_initialize_python): Register new commands.
gdb/doc/ChangeLog:
* python.texinfo (Python Commands): Mention new commands.
gdb/testsuite/ChangeLog:
* gdb.python/py-startup-opt.exp: New file.
---
gdb/ChangeLog | 11 ++
gdb/NEWS | 16 +++
gdb/doc/ChangeLog | 4 +
gdb/doc/python.texi | 38 +++++++
gdb/python/python.c | 98 ++++++++++++++++
gdb/testsuite/ChangeLog | 4 +
gdb/testsuite/gdb.python/py-startup-opt.exp | 118 ++++++++++++++++++++
7 files changed, 289 insertions(+)
create mode 100644 gdb/testsuite/gdb.python/py-startup-opt.exp
diff --git a/gdb/NEWS b/gdb/NEWS
index faccf40dd41..a1b83ad9fce 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -101,6 +101,22 @@ show startup-quietly
initialization file (e.g. ~/.config/gdb/gdbearlyinit) in order to
affect GDB.
+set python ignore-environment on|off
+show python ignore-environment
+ When 'on', this causes GDB's builtin Python to ignore any
+ environment variables that would otherwise effect how Python
+ behaves. This command needs to be added to an early initialization
+ file (e.g. ~/.config/gdb/gdbearlyinit) in order to affect GDB.
+
+set python dont-write-bytecode auto|on|off
+show python dont-write-bytecode
+ When 'on', this causes GDB's builtin Python to not write any
+ byte-code (.pyc files) to disk. This command needs to be added to
+ an early initialization file (e.g. ~/.config/gdb/gdbearlyinit) in
+ order to affect GDB. When 'off' byte-code will always be written.
+ When set to 'auto' (the default) Python will check the
+ PYTHONDONTWRITEBYTECODE. environment variable.
+
* Changed commands
break [PROBE_MODIFIER] [LOCATION] [thread THREADNUM]
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
index 9135d415dd1..aa5dc55bb60 100644
--- a/gdb/doc/python.texi
+++ b/gdb/doc/python.texi
@@ -103,6 +103,44 @@
full Python stack printing is enabled; if @code{none}, then Python stack
and message printing is disabled; if @code{message}, the default, only
the message component of the error is printed.
+
+@kindex set python ignore-environment
+@item set python ignore-environment @r{[}on@r{|}off@r{]}
+By default this option is @samp{off}, and, when @value{GDBN}
+initializes its internal Python interpreter, the Python interpreter
+will check the environment for variables that will effect how it
+behaves, for example @samp{PYTHONHOME}, and
+@samp{PYTHONPATH}@footnote{See the ENVIRONMENT VARIABLES section of
+@code{man 1 python} for a comprehensive list.}.
+
+If this option is set to @samp{on} before Python is initialized then
+Python will ignore all such environment variables. As Python is
+initialized early during @value{GDBN}'s startup process, then this
+option must be placed into the early initialization file
+(@pxref{Initialization Files}) to have the desired effect.
+
+This option is equivalent to passing @samp{-E} to the real
+@samp{python} executable.
+
+@kindex set python dont-write-bytecode
+@item set python dont-write-bytecode @r{[}auto@r{|}on@r{|}off@r{]}
+When this option is @samp{off}, then, once @value{GDBN} has
+initialized the Python interpreter, the interpreter will byte-compile
+any Python modules that it imports and write the byte code to disk in
+@code{.pyc} files.
+
+If this option is set to @samp{on} before Python is initialized then
+Python will no longer write the byte code to disk. As Python is
+initialized early during @value{GDBN}'s startup process, then this
+option must be placed into the early initialization file
+(@pxref{Initialization Files}) to have the desired effect.
+
+By default this option is set to @samp{auto}, in this mode Python will
+check the environment variable @samp{PYTHONDONTWRITEBYTECODE} to see
+if it should write out byte-code or not.
+
+This option is equivalent to passing @samp{-B} to the real
+@samp{python} executable.
@end table
It is also possible to execute a Python script from the @value{GDBN}
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 1d0d86d5c49..c46d68b73ed 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -1578,6 +1578,80 @@ python_command (const char *arg, int from_tty)
#endif /* HAVE_PYTHON */
+/* When this is turned on before Python is initialised then Python will
+ ignore any environment variables related to Python. This is equivalent
+ to passing `-E' to the python program. */
+static bool python_ignore_environment = false;
+
+/* Implement 'show python ignore-environment'. */
+
+static void
+show_python_ignore_environment (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ fprintf_filtered (file, _("Python's ignore-environment setting is %s.\n"),
+ value);
+}
+
+/* Implement 'set python ignore-environment'. This sets Python's internal
+ flag no matter when the command is issued, however, if this is used
+ after Py_Initialize has been called then most of the environment will
+ already have been read. */
+
+static void
+set_python_ignore_environment (const char *args, int from_tty,
+ struct cmd_list_element *c)
+{
+#ifdef HAVE_PYTHON
+ Py_IgnoreEnvironmentFlag = python_ignore_environment ? 1 : 0;
+#endif
+}
+
+/* When this is turned on before Python is initialised then Python will
+ not write `.pyc' files on import of a module. */
+static enum auto_boolean python_dont_write_bytecode = AUTO_BOOLEAN_AUTO;
+
+/* Implement 'show python dont-write-bytecode'. */
+
+static void
+show_python_dont_write_bytecode (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ if (python_dont_write_bytecode == AUTO_BOOLEAN_AUTO)
+ {
+ const char *auto_string
+ = (python_ignore_environment
+ || getenv ("PYTHONDONTWRITEBYTECODE") == nullptr) ? "off" : "on";
+
+ fprintf_filtered (file,
+ _("Python's dont-write-bytecode setting is %s (currently %s).\n"),
+ value, auto_string);
+ }
+ else
+ fprintf_filtered (file, _("Python's dont-write-bytecode setting is %s.\n"),
+ value);
+}
+
+/* Implement 'set python dont-write-bytecode'. This sets Python's internal
+ flag no matter when the command is issued, however, if this is used
+ after Py_Initialize has been called then many modules could already
+ have been imported and their byte code written out. */
+
+static void
+set_python_dont_write_bytecode (const char *args, int from_tty,
+ struct cmd_list_element *c)
+{
+#ifdef HAVE_PYTHON
+ if (python_dont_write_bytecode == AUTO_BOOLEAN_AUTO)
+ Py_DontWriteBytecodeFlag
+ = (!python_ignore_environment
+ && getenv ("PYTHONDONTWRITEBYTECODE") != nullptr) ? 1 : 0;
+ else
+ Py_DontWriteBytecodeFlag
+ = python_dont_write_bytecode == AUTO_BOOLEAN_TRUE ? 1 : 0;
+#endif /* HAVE_PYTHON */
+}
+
/* Lists for 'set python' commands. */
@@ -1880,6 +1954,30 @@ message == an error message without a stack will be printed."),
NULL, NULL,
&user_set_python_list,
&user_show_python_list);
+
+ add_setshow_boolean_cmd ("ignore-environment", no_class,
+ &python_ignore_environment, _("\
+Set whether the Python interpreter should ignore environment variables."), _(" \
+Show whether the Python interpreter showlist ignore environment variables."), _(" \
+When enabled GDB's Python interpreter will ignore any Python related\n \
+flags in the environment. This is equivalent to passing `-E' to a\n \
+python executable."),
+ set_python_ignore_environment,
+ show_python_ignore_environment,
+ &user_set_python_list,
+ &user_show_python_list);
+
+ add_setshow_auto_boolean_cmd ("dont-write-bytecode", no_class,
+ &python_dont_write_bytecode, _("\
+Set whether the Python interpreter should ignore environment variables."), _(" \
+Show whether the Python interpreter showlist ignore environment variables."), _(" \
+When enabled GDB's Python interpreter will ignore any Python related\n \
+flags in the environment. This is equivalent to passing `-E' to a\n \
+python executable."),
+ set_python_dont_write_bytecode,
+ show_python_dont_write_bytecode,
+ &user_set_python_list,
+ &user_show_python_list);
}
#ifdef HAVE_PYTHON
diff --git a/gdb/testsuite/gdb.python/py-startup-opt.exp b/gdb/testsuite/gdb.python/py-startup-opt.exp
new file mode 100644
index 00000000000..842add30807
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-startup-opt.exp
@@ -0,0 +1,118 @@
+# Copyright 2021 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Test the flags within GDB that can be used to control how Python is
+# initialized.
+
+gdb_start
+
+# Skip all tests if Python scripting is not enabled.
+if { [skip_python_tests] } { continue }
+
+gdb_exit
+
+# Return a list containing two directory paths for newly created home
+# directories.
+#
+# The first directory is a HOME style home directory, it contains a
+# .gdbearlyinit file containing CONTENT.
+#
+# The second directory is an XDG_CONFIG_HOME style home directory, it
+# contains a sub-directory gdb/, inside which is a file gdbearlyinit
+# that also contains CONTENT.
+#
+# The PREFIX is used in both directory names and should be unique for
+# each call to this function.
+proc setup_home_directories { prefix content } {
+ set home_dir [standard_output_file "${prefix}-home"]
+ set xdg_home_dir [standard_output_file "${prefix}-xdg"]
+
+ file mkdir $home_dir
+ file mkdir "$xdg_home_dir/gdb"
+
+ # Write the content into the HOME directory.
+ set fd [open "$home_dir/.gdbearlyinit" w]
+ puts $fd $content
+ close $fd
+
+ # Copy this from the HOME directory into the XDG_CONFIG_HOME
+ # directory.
+ file copy -force "$home_dir/.gdbearlyinit" "$xdg_home_dir/gdb/gdbearlyinit"
+
+ return [list $home_dir $xdg_home_dir]
+}
+
+# Start GDB and check the status of the Python system flags that we
+# can control from within GDB.
+proc test_python_settings { exp_state } {
+ gdb_start
+
+ gdb_test_no_output "python import sys"
+
+ foreach_with_prefix attr {ignore_environment dont_write_bytecode} {
+ gdb_test_multiline "testname" \
+ "python" "" \
+ "if hasattr(sys, 'flags') and getattr(sys.flags, '${attr}', False):" "" \
+ " print (\"${attr} is on\")" "" \
+ "else:" "" \
+ " print (\"${attr} is off\")" "" \
+ "end" "${attr} is ${exp_state}"
+ }
+
+ gdb_exit
+}
+
+save_vars { env(TERM) } {
+ # We need an ANSI-capable terminal to get the output.
+ setenv TERM ansi
+
+ # Check the features are off by default.
+ test_python_settings "off"
+
+ # Create an empty directory we can use as HOME for some of the
+ # tests below. When we set XDG_CONFIG_HOME we still need to point
+ # HOME at something otherwise GDB complains that it doesn't know
+ # where to create the index cache.
+ set empty_home_dir [standard_output_file fake-empty-home]
+
+ # Create two directories to use for the style setting test.
+ set dirs [setup_home_directories "style" \
+ [multi_line_input \
+ "set python dont-write-bytecode on" \
+ "set python ignore-environment on"]]
+ set home_dir [lindex $dirs 0]
+ set xdg_home_dir [lindex $dirs 1]
+
+ # Now arrange to use the fake home directory early init file.
+ save_vars { INTERNAL_GDBFLAGS env(HOME) env(XDG_CONFIG_HOME) } {
+ set INTERNAL_GDBFLAGS [string map {"-nx" ""} $INTERNAL_GDBFLAGS]
+
+ with_test_prefix "using HOME config" {
+ # Now test GDB when using the HOME directory.
+ set env(HOME) $home_dir
+ unset -nocomplain env(XDG_CONFIG_HOME)
+ test_python_settings "on"
+ }
+
+ with_test_prefix "using XDG_CONFIG_HOME config" {
+ # Now test using the XDG_CONFIG_HOME folder. We still need to
+ # have a HOME directory set otherwise GDB will issue an error
+ # about not knowing where to place the index cache.
+ set env(XDG_CONFIG_HOME) $xdg_home_dir
+ set env(HOME) $empty_home_dir
+ test_python_settings "on"
+ }
+ }
+}
--
2.25.4
More information about the Gdb-patches
mailing list