Blame SOURCES/gdb-python-gil.patch

f9426a
diff -dup -ruNp gdb-7.8-orig/gdb/doc/python.texi gdb-7.8/gdb/doc/python.texi
f9426a
--- gdb-7.8-orig/gdb/doc/python.texi	2014-08-13 22:04:14.162441271 +0200
f9426a
+++ gdb-7.8/gdb/doc/python.texi	2014-08-13 22:07:20.894643853 +0200
f9426a
@@ -228,6 +228,14 @@ returned as a string.  The default is @c
f9426a
 return value is @code{None}.  If @var{to_string} is @code{True}, the
f9426a
 @value{GDBN} virtual terminal will be temporarily set to unlimited width
f9426a
 and height, and its pagination will be disabled; @pxref{Screen Size}.
f9426a
+
f9426a
+The @var{release_gil} flag specifies whether @value{GDBN} ought to
f9426a
+release the Python GIL before executing the command.  This is useful
f9426a
+in multi-threaded Python programs where by default the Python
f9426a
+interpreter will acquire the GIL and lock other threads from
f9426a
+executing.  After the command has completed executing in @value{GDBN}
f9426a
+the Python GIL is reacquired. This flag must be a boolean value.  If
f9426a
+omitted, it defaults to @code{False}.
f9426a
 @end defun
f9426a
 
f9426a
 @findex gdb.breakpoints
f9426a
diff -dup -ruNp gdb-7.8-orig/gdb/python/python-internal.h gdb-7.8/gdb/python/python-internal.h
f9426a
--- gdb-7.8-orig/gdb/python/python-internal.h	2014-08-13 22:04:14.835441977 +0200
f9426a
+++ gdb-7.8/gdb/python/python-internal.h	2014-08-13 22:07:20.895643867 +0200
f9426a
@@ -143,6 +143,8 @@ typedef int Py_ssize_t;
f9426a
 #define PyGILState_Release(ARG) ((void)(ARG))
f9426a
 #define PyEval_InitThreads()
f9426a
 #define PyThreadState_Swap(ARG) ((void)(ARG))
f9426a
+#define PyEval_SaveThread() ((void)(ARG))
f9426a
+#define PyEval_RestoreThread(ARG) ((void)(ARG))
f9426a
 #define PyEval_ReleaseLock()
f9426a
 #endif
f9426a
 
f9426a
diff -dup -ruNp gdb-7.8-orig/gdb/python/python.c gdb-7.8/gdb/python/python.c
f9426a
--- gdb-7.8-orig/gdb/python/python.c	2014-08-13 22:04:14.164441273 +0200
f9426a
+++ gdb-7.8/gdb/python/python.c	2014-08-13 22:07:20.895643867 +0200
f9426a
@@ -620,14 +620,19 @@ execute_gdb_command (PyObject *self, PyO
f9426a
 {
f9426a
   const char *arg;
f9426a
   PyObject *from_tty_obj = NULL, *to_string_obj = NULL;
f9426a
-  int from_tty, to_string;
f9426a
+  PyObject *release_gil_obj = NULL;
f9426a
+  int from_tty, to_string, release_gil;
f9426a
   volatile struct gdb_exception except;
f9426a
-  static char *keywords[] = {"command", "from_tty", "to_string", NULL };
f9426a
+  static char *keywords[] = {"command", "from_tty", "to_string",
f9426a
+			     "release_gil", NULL };
f9426a
   char *result = NULL;
f9426a
+  /* Initialize it just to avoid a GCC false warning.  */
f9426a
+  PyThreadState *state = NULL;
f9426a
 
f9426a
-  if (! PyArg_ParseTupleAndKeywords (args, kw, "s|O!O!", keywords, &arg,
f9426a
+  if (! PyArg_ParseTupleAndKeywords (args, kw, "s|O!O!O!", keywords, &arg,
f9426a
 				     &PyBool_Type, &from_tty_obj,
f9426a
-				     &PyBool_Type, &to_string_obj))
f9426a
+				     &PyBool_Type, &to_string_obj,
f9426a
+				     &PyBool_Type, &release_gil_obj))
f9426a
     return NULL;
f9426a
 
f9426a
   from_tty = 0;
f9426a
@@ -648,12 +652,28 @@ execute_gdb_command (PyObject *self, PyO
f9426a
       to_string = cmp;
f9426a
     }
f9426a
 
f9426a
+  release_gil = 0;
f9426a
+  if (release_gil_obj)
f9426a
+    {
f9426a
+      int cmp = PyObject_IsTrue (release_gil_obj);
f9426a
+      if (cmp < 0)
f9426a
+	return NULL;
f9426a
+      release_gil = cmp;
f9426a
+    }
f9426a
+
f9426a
   TRY_CATCH (except, RETURN_MASK_ALL)
f9426a
     {
f9426a
       /* Copy the argument text in case the command modifies it.  */
f9426a
       char *copy = xstrdup (arg);
f9426a
       struct cleanup *cleanup = make_cleanup (xfree, copy);
f9426a
 
f9426a
+      /* In the case of long running GDB commands, allow the user to
f9426a
+	 release the Python GIL acquired by Python.  Restore the GIL
f9426a
+	 after the command has completed before handing back to
f9426a
+	 Python.  */
f9426a
+      if (release_gil)
f9426a
+	state = PyEval_SaveThread();
f9426a
+
f9426a
       make_cleanup_restore_integer (&interpreter_async);
f9426a
       interpreter_async = 0;
f9426a
 
f9426a
@@ -666,9 +686,21 @@ execute_gdb_command (PyObject *self, PyO
f9426a
 	  execute_command (copy, from_tty);
f9426a
 	}
f9426a
 
f9426a
+      /* Reacquire the GIL if it was released earlier.  */
f9426a
+      if (release_gil)
f9426a
+	PyEval_RestoreThread (state);
f9426a
+
f9426a
       do_cleanups (cleanup);
f9426a
     }
f9426a
-  GDB_PY_HANDLE_EXCEPTION (except);
f9426a
+  if (except.reason < 0)
f9426a
+    {
f9426a
+      /* Reacquire the GIL if it was released earlier.  */
f9426a
+      if (release_gil)
f9426a
+	PyEval_RestoreThread (state);
f9426a
+
f9426a
+      gdbpy_convert_exception (except);
f9426a
+      return NULL;
f9426a
+    }
f9426a
 
f9426a
   /* Do any commands attached to breakpoint we stopped at.  */
f9426a
   bpstat_do_actions ();
f9426a
diff -dup -ruNp gdb-7.8-orig/gdb/testsuite/gdb.python/py-gil-mthread.c gdb-7.8/gdb/testsuite/gdb.python/py-gil-mthread.c
f9426a
--- gdb-7.8-orig/gdb/testsuite/gdb.python/py-gil-mthread.c	1970-01-01 01:00:00.000000000 +0100
f9426a
+++ gdb-7.8/gdb/testsuite/gdb.python/py-gil-mthread.c	2014-08-13 22:33:05.052648912 +0200
f9426a
@@ -0,0 +1,12 @@
f9426a
+#include <stdio.h>
f9426a
+
f9426a
+int
f9426a
+main (void)
f9426a
+{
f9426a
+  int i;
f9426a
+  for (i = 0; i < 10; i++)
f9426a
+    {
f9426a
+      sleep (1); /* break-here */
f9426a
+      printf ("Sleeping %d\n", i);
f9426a
+    }
f9426a
+}
f9426a
diff -dup -ruNp gdb-7.8-orig/gdb/testsuite/gdb.python/py-gil-mthread.exp gdb-7.8/gdb/testsuite/gdb.python/py-gil-mthread.exp
f9426a
--- gdb-7.8-orig/gdb/testsuite/gdb.python/py-gil-mthread.exp	1970-01-01 01:00:00.000000000 +0100
f9426a
+++ gdb-7.8/gdb/testsuite/gdb.python/py-gil-mthread.exp	2014-08-13 22:33:00.660641300 +0200
f9426a
@@ -0,0 +1,69 @@
f9426a
+# Copyright (C) 2014 Free Software Foundation, Inc.
f9426a
+
f9426a
+# This program is free software; you can redistribute it and/or modify
f9426a
+# it under the terms of the GNU General Public License as published by
f9426a
+# the Free Software Foundation; either version 3 of the License, or
f9426a
+# (at your option) any later version.
f9426a
+#
f9426a
+# This program is distributed in the hope that it will be useful,
f9426a
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
f9426a
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
f9426a
+# GNU General Public License for more details.
f9426a
+#
f9426a
+# You should have received a copy of the GNU General Public License
f9426a
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
f9426a
+
f9426a
+standard_testfile .c .py
f9426a
+set executable $testfile
f9426a
+
f9426a
+if { [prepare_for_testing $testfile.exp $executable $srcfile] } {
f9426a
+    return -1
f9426a
+}
f9426a
+
f9426a
+# Skip all tests if Python scripting is not enabled.
f9426a
+if { [skip_python_tests] } { continue }
f9426a
+
f9426a
+if ![runto_main] {
f9426a
+    return -1
f9426a
+}
f9426a
+
f9426a
+gdb_breakpoint $srcfile:[gdb_get_line_number "break-here"] temporary
f9426a
+gdb_continue_to_breakpoint "break-here" ".* break-here .*"
f9426a
+
f9426a
+set test "response"
f9426a
+set timeout 60
f9426a
+set sleeping_last -1
f9426a
+set hello_last 0
f9426a
+set minimal 5
f9426a
+gdb_test_multiple "python execfile('$srcdir/$subdir/$srcfile2')" $test {
f9426a
+    -re "Error: unable to start thread\r\n" {
f9426a
+	fail $test
f9426a
+	# Not $gdb_prompt-synced!
f9426a
+    }
f9426a
+    -re "Sleeping (\[0-9\]+)\r\n" {
f9426a
+	set n $expect_out(1,string)
f9426a
+	if { $sleeping_last + 1 != $n } {
f9426a
+	    fail $test
f9426a
+	} else {
f9426a
+	    set sleeping_last $n
f9426a
+	    if { $sleeping_last >= $minimal && $hello_last >= $minimal } {
f9426a
+		pass $test
f9426a
+	    } else {
f9426a
+		exp_continue
f9426a
+	    }
f9426a
+	}
f9426a
+    }
f9426a
+    -re "Hello \\( (\[0-9\]+) \\)\r\n" {
f9426a
+	set n $expect_out(1,string)
f9426a
+	if { $hello_last + 1 != $n } {
f9426a
+	    fail $test
f9426a
+	} else {
f9426a
+	    set hello_last $n
f9426a
+	    if { $sleeping_last >= $minimal && $hello_last >= $minimal } {
f9426a
+		pass $test
f9426a
+	    } else {
f9426a
+		exp_continue
f9426a
+	    }
f9426a
+	}
f9426a
+    }
f9426a
+}
f9426a
diff -dup -ruNp gdb-7.8-orig/gdb/testsuite/gdb.python/py-gil-mthread.py gdb-7.8/gdb/testsuite/gdb.python/py-gil-mthread.py
f9426a
--- gdb-7.8-orig/gdb/testsuite/gdb.python/py-gil-mthread.py	1970-01-01 01:00:00.000000000 +0100
f9426a
+++ gdb-7.8/gdb/testsuite/gdb.python/py-gil-mthread.py	2014-08-13 22:33:08.996654320 +0200
f9426a
@@ -0,0 +1,22 @@
f9426a
+import thread
f9426a
+import time
f9426a
+import gdb
f9426a
+
f9426a
+# Define a function for the thread
f9426a
+def print_thread_hello():
f9426a
+   count = 0
f9426a
+   while count < 10:
f9426a
+      time.sleep(1)
f9426a
+      count += 1
f9426a
+      print "Hello (", count, ")"
f9426a
+
f9426a
+# Create a threads a continue
f9426a
+try:
f9426a
+   thread.start_new_thread( print_thread_hello, ())
f9426a
+   gdb.execute ("continue", release_gil=True)
f9426a
+   
f9426a
+except:
f9426a
+   print "Error: unable to start thread"
f9426a
+
f9426a
+while 1:
f9426a
+   pass