This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFC: merged python exception handling patch


This patch merges my various python exception handling patches into one.

The parts of the patch have been discussed at some length in other
threads, but to recap, the idea is to make C-c work both when gdb is
executing gdb code, as well as when it is executing python code.

Built and regtested on x86-64 Fedora 16.

Tom

    	* defs.h (quit_flag): Conditionally declare.
    	(clear_quit_flag, check_quit_flag, set_quit_flag): New
    	macros.
    	(QUIT): Use them.
    	* event-top.c (command_handler): Use clear_quit_flag.
    	(handle_sigint): Use set_quit_flag.
    	(async_request_quit): Use check_quit_flag.  Don't check
    	immediate_quit.
    	* exceptions.c (throw_exception): Use clear_quit_flag.
    	* main.c (captured_main): Use clear_quit_flag.
    	* python/python.c (clear_quit_flag, set_quit_flag)
    	(check_quit_flag): New functions.
    	* remote-sim.c (gdb_os_poll_quit): Use check_quit_flag,
    	clear_quit_flag.
    	* remote.c (remote_wait_as): Use check_quit_flag,
    	clear_quit_flag.
    	(remote_start_remote): Call QUIT.
    	* symfile.c (load_progress): Use check_quit_flag.
    	* top.c (command_loop): Use clear_quit_flag.
    	(command_line_input): Call QUIT.
    	* utils.c (quit_flag): Conditionally define.
    	(prompt_for_continue): Call QUIT.  Use quit, not
    	async_request_quit.
    	* remote-mips.c (mips_expect_timeout): Call QUIT.
    	* monitor.c (monitor_expect): Call QUIT.

diff --git a/gdb/defs.h b/gdb/defs.h
index de34740..c7f3071 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -171,7 +171,36 @@ extern char *python_libdir;
 /* Search path for separate debug files.  */
 extern char *debug_file_directory;
 
+/* GDB has two methods for handling SIGINT.  When immediate_quit is
+   nonzero, a SIGINT results in an immediate longjmp out of the signal
+   handler.  Otherwise, SIGINT simply sets a flag; code that might
+   take a long time, and which ought to be interruptible, checks this
+   flag using the QUIT macro.
+   
+   If GDB is built with Python support, it uses Python's low-level
+   interface to implement the flag.  This approach makes it possible
+   for Python and GDB SIGINT handling to coexist seamlessly.
+
+   If GDB is built without Python, it instead uses its traditional
+   variables.
+   
+   The distinction between these two cases is hidden behind a few
+   macros, defined here.  */
+
+#ifndef HAVE_PYTHON
 extern int quit_flag;
+/* Clear the quit flag.  */
+#define clear_quit_flag() do { quit_flag = 0; } while (0)
+/* Evaluate to non-zero if the quit flag is set, zero otherwise.  */
+#define check_quit_flag() (quit_flag + 0)
+/* Set the quit flag.  */
+#define set_quit_flag() do { quit_flag = 1; } while (0)
+#else
+extern void clear_quit_flag (void);
+extern int check_quit_flag (void);
+extern void set_quit_flag (void);
+#endif /* HAVE_PYTHON */
+
 extern int immediate_quit;
 
 extern void quit (void);
@@ -184,7 +213,7 @@ extern void quit (void);
    needed.  */
 
 #define QUIT { \
-  if (quit_flag) quit (); \
+  if (check_quit_flag ()) quit (); \
   if (deprecated_interactive_hook) deprecated_interactive_hook (); \
 }
 
diff --git a/gdb/event-top.c b/gdb/event-top.c
index 52e7852..bc620e7 100644
--- a/gdb/event-top.c
+++ b/gdb/event-top.c
@@ -415,7 +415,7 @@ command_handler (char *command)
   int stdin_is_tty = ISATTY (stdin);
   struct cleanup *stat_chain;
 
-  quit_flag = 0;
+  clear_quit_flag ();
   if (instream == stdin && stdin_is_tty)
     reinitialize_more_filter ();
 
@@ -799,7 +799,7 @@ handle_sigint (int sig)
      set quit_flag to 1 here.  Then if QUIT is called before we get to
      the event loop, we will unwind as expected.  */
 
-  quit_flag = 1;
+  set_quit_flag ();
 
   /* If immediate_quit is set, we go ahead and process the SIGINT right
      away, even if we usually would defer this to the event loop.  The
@@ -828,10 +828,9 @@ async_request_quit (gdb_client_data arg)
   /* If the quit_flag has gotten reset back to 0 by the time we get
      back here, that means that an exception was thrown to unwind the
      current command before we got back to the event loop.  So there
-     is no reason to call quit again here, unless immediate_quit is
-     set.  */
+     is no reason to call quit again here.  */
 
-  if (quit_flag || immediate_quit)
+  if (check_quit_flag ())
     quit ();
 }
 
diff --git a/gdb/exceptions.c b/gdb/exceptions.c
index 7db9df9..b7cf9a2 100644
--- a/gdb/exceptions.c
+++ b/gdb/exceptions.c
@@ -221,7 +221,7 @@ exceptions_state_mc_action_iter_1 (void)
 void
 throw_exception (struct gdb_exception exception)
 {
-  quit_flag = 0;
+  clear_quit_flag ();
   immediate_quit = 0;
 
   do_cleanups (all_cleanups ());
diff --git a/gdb/main.c b/gdb/main.c
index d075694..326b101 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -331,7 +331,7 @@ captured_main (void *data)
   dirarg = (char **) xmalloc (dirsize * sizeof (*dirarg));
   ndir = 0;
 
-  quit_flag = 0;
+  clear_quit_flag ();
   saved_command_line = (char *) xmalloc (saved_command_line_size);
   saved_command_line[0] = '\0';
   instream = stdin;
diff --git a/gdb/monitor.c b/gdb/monitor.c
index d19a49c..4812736 100644
--- a/gdb/monitor.c
+++ b/gdb/monitor.c
@@ -512,6 +512,7 @@ monitor_expect (char *string, char *buf, int buflen)
     }
 
   immediate_quit++;
+  QUIT;
   while (1)
     {
       if (buf)
diff --git a/gdb/python/python.c b/gdb/python/python.c
index c66efe4..4a2b518 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -151,6 +151,31 @@ ensure_python_env (struct gdbarch *gdbarch,
   return make_cleanup (restore_python_env, env);
 }
 
+/* Clear the quit flag.  */
+
+void
+clear_quit_flag (void)
+{
+  /* This clears the flag as a side effect.  */
+  PyOS_InterruptOccurred ();
+}
+
+/* Set the quit flag.  */
+
+void
+set_quit_flag (void)
+{
+  PyErr_SetInterrupt ();
+}
+
+/* Return true if the quit flag has been set, false otherwise.  */
+
+int
+check_quit_flag (void)
+{
+  return PyOS_InterruptOccurred ();
+}
+
 /* A wrapper around PyRun_SimpleFile.  FILE is the Python script to run
    named FILENAME.
 
diff --git a/gdb/remote-mips.c b/gdb/remote-mips.c
index db4381b..7819f3f 100644
--- a/gdb/remote-mips.c
+++ b/gdb/remote-mips.c
@@ -588,6 +588,7 @@ mips_expect_timeout (const char *string, int timeout)
     }
 
   immediate_quit++;
+  QUIT;
   while (1)
     {
       int c;
diff --git a/gdb/remote-sim.c b/gdb/remote-sim.c
index b3890b8..87910d9 100644
--- a/gdb/remote-sim.c
+++ b/gdb/remote-sim.c
@@ -950,9 +950,9 @@ gdb_os_poll_quit (host_callback *p)
   if (deprecated_ui_loop_hook != NULL)
     deprecated_ui_loop_hook (0);
 
-  if (quit_flag)		/* gdb's idea of quit */
+  if (check_quit_flag ())	/* gdb's idea of quit */
     {
-      quit_flag = 0;		/* we've stolen it */
+      clear_quit_flag ();	/* we've stolen it */
       return 1;
     }
   return 0;
diff --git a/gdb/remote.c b/gdb/remote.c
index a974dc1..a2dfb01 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -3271,6 +3271,7 @@ remote_start_remote (int from_tty, struct target_ops *target, int extended_p)
   char *wait_status = NULL;
 
   immediate_quit++;		/* Allow user to interrupt it.  */
+  QUIT;
 
   if (interrupt_on_connect)
     send_interrupt_sequence ();
@@ -5714,9 +5715,9 @@ remote_wait_as (ptid_t ptid, struct target_waitstatus *status, int options)
 	  ofunc = signal (SIGINT, remote_interrupt);
 	  /* If the user hit C-c before this packet, or between packets,
 	     pretend that it was hit right here.  */
-	  if (quit_flag)
+	  if (check_quit_flag ())
 	    {
-	      quit_flag = 0;
+	      clear_quit_flag ();
 	      remote_interrupt (SIGINT);
 	    }
 	}
diff --git a/gdb/symfile.c b/gdb/symfile.c
index da068a1..97f86f7 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -1986,7 +1986,7 @@ load_progress (ULONGEST bytes, void *untyped_arg)
   args->buffer += bytes;
   totals->write_count += 1;
   args->section_sent += bytes;
-  if (quit_flag
+  if (check_quit_flag ()
       || (deprecated_ui_load_progress_hook != NULL
 	  && deprecated_ui_load_progress_hook (args->section_name,
 					       args->section_sent)))
diff --git a/gdb/top.c b/gdb/top.c
index 8251d1b..7084116 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -569,7 +569,7 @@ command_loop (void)
       if (window_hook && instream == stdin)
 	(*window_hook) (instream, get_prompt ());
 
-      quit_flag = 0;
+      clear_quit_flag ();
       if (instream == stdin && stdin_is_tty)
 	reinitialize_more_filter ();
       old_chain = make_cleanup (null_cleanup, 0);
@@ -944,6 +944,7 @@ command_line_input (char *prompt_arg, int repeat, char *annotation_suffix)
   /* Control-C quits instantly if typed while in this loop
      since it should not wait until the user types a newline.  */
   immediate_quit++;
+  QUIT;
 #ifdef STOP_SIGNAL
   if (job_control)
     signal (STOP_SIGNAL, handle_stop_sig);
diff --git a/gdb/utils.c b/gdb/utils.c
index 607d7bc..9445ba7 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -122,9 +122,11 @@ static int debug_timestamp = 0;
 
 int job_control;
 
+#ifndef HAVE_PYTHON
 /* Nonzero means a quit has been requested.  */
 
 int quit_flag;
+#endif /* HAVE_PYTHON */
 
 /* Nonzero means quit immediately if Control-C is typed now, rather
    than waiting until QUIT is executed.  Be careful in setting this;
@@ -1845,6 +1847,7 @@ prompt_for_continue (void)
   reinitialize_more_filter ();
 
   immediate_quit++;
+  QUIT;
   /* On a real operating system, the user can quit with SIGINT.
      But not on GO32.
 
@@ -1873,7 +1876,7 @@ prompt_for_continue (void)
       while (*p == ' ' || *p == '\t')
 	++p;
       if (p[0] == 'q')
-	async_request_quit (0);
+	quit ();
       xfree (ignore);
     }
   immediate_quit--;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]