public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Andrew Burgess <andrew.burgess@embecosm.com>
To: gdb-patches@sourceware.org
Subject: [PATCH 7/7] gdb: startup commands to control Python extension language
Date: Thu, 22 Apr 2021 22:02:48 +0100	[thread overview]
Message-ID: <baa30a387c74179380976d32b59df22f8768d300.1619125261.git.andrew.burgess@embecosm.com> (raw)
In-Reply-To: <cover.1619125261.git.andrew.burgess@embecosm.com>

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 */
+}
+
 \f
 
 /* 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


  parent reply	other threads:[~2021-04-23  8:38 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-22 21:02 [PATCH 0/7] New options to control how Python is initialized Andrew Burgess
2021-04-22 21:02 ` [PATCH 1/7] gdb: remove unused argument from gdb_init Andrew Burgess
2021-04-23 14:15   ` Tom Tromey
2021-04-22 21:02 ` [PATCH 2/7] gdb: ensure SIGINT is set to SIG_DFL during initialisation Andrew Burgess
2021-04-23 14:16   ` Tom Tromey
2021-04-22 21:02 ` [PATCH 3/7] gdb: delay python initialisation until gdbpy_finish_initialization Andrew Burgess
2021-04-23 14:26   ` Tom Tromey
2021-04-22 21:02 ` [PATCH 4/7] gdb delay guile initialization until gdbscm_finish_initialization Andrew Burgess
2021-04-23 14:29   ` Tom Tromey
2021-04-22 21:02 ` [PATCH 5/7] gdb: initialise extension languages after processing early startup files Andrew Burgess
2021-04-23 14:30   ` Tom Tromey
2021-04-22 21:02 ` [PATCH 6/7] gdb: extension languages finish_initialization to initialize Andrew Burgess
2021-04-23 14:31   ` Tom Tromey
2021-04-22 21:02 ` Andrew Burgess [this message]
2021-04-23 10:31   ` [PATCH 7/7] gdb: startup commands to control Python extension language Eli Zaretskii
2021-04-23 14:32   ` Tom Tromey
2021-04-29  8:32   ` Tom de Vries
2021-04-29  9:35     ` Andrew Burgess
2021-04-29  9:46     ` Andrew Burgess
2021-04-29 10:08       ` Tom de Vries
2021-05-02 10:31         ` Andrew Burgess
2021-05-02 18:15           ` Tom de Vries
2021-04-29 12:17       ` Eli Zaretskii
2021-04-29 12:32         ` Eli Zaretskii

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=baa30a387c74179380976d32b59df22f8768d300.1619125261.git.andrew.burgess@embecosm.com \
    --to=andrew.burgess@embecosm.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).