Fix swallowed "Quit" when inserting breakpoints

If GDB is inserting a breakpoint and you type Ctrl-C at the exact
"right" time, you'll hit a QUIT call in target_read, and the
breakpoint insertion is cancelled.  However, the related TRY/CATCH
code in insert_bp_location does:

 		  CATCH (e, RETURN_MASK_ALL)
 		    {
		      bp_err = e.error;
		      bp_err_message = e.message;
		    }

The problem with that is that a RETURN_QUIT exception has e.error ==
0, which means that further below, in the places that check for error
with:

      if (bp_err != GDB_NO_ERROR)

because GDB_NO_ERROR == 0, GDB continues as if the breakpoint was
inserted succesfully, and resumes the inferior.  Since the breakpoint
wasn't inserted the inferior runs free, out of our control...

Fix this by having insert_bp_location store a copy of the whole
exception instead of just a error/message parts, and then checking
"gdb_exception::reason" instead.

This was exposed by the new gdb.base/bp-cmds-continue-ctrl-c.exp
testcase added later in the series.

gdb/ChangeLog:
2017-11-16  Pedro Alves  <palves@redhat.com>

	* breakpoint.c (insert_bp_location): Replace bp_err and
	bp_err_message locals by a gdb_exception local.
This commit is contained in:
Pedro Alves
2017-11-16 18:44:42 +00:00
parent e2c33ac745
commit 688fca4fe6
2 changed files with 26 additions and 20 deletions

View File

@ -1,3 +1,8 @@
2017-11-16 Pedro Alves <palves@redhat.com>
* breakpoint.c (insert_bp_location): Replace bp_err and
bp_err_message locals by a gdb_exception local.
2017-11-16 Pedro Alves <palves@redhat.com> 2017-11-16 Pedro Alves <palves@redhat.com>
* inflow.c (scoped_ignore_sigttou): New class. * inflow.c (scoped_ignore_sigttou): New class.

View File

@ -2458,8 +2458,7 @@ insert_bp_location (struct bp_location *bl,
int *hw_breakpoint_error, int *hw_breakpoint_error,
int *hw_bp_error_explained_already) int *hw_bp_error_explained_already)
{ {
enum errors bp_err = GDB_NO_ERROR; gdb_exception bp_excpt = exception_none;
const char *bp_err_message = NULL;
if (!should_be_inserted (bl) || (bl->inserted && !bl->needs_update)) if (!should_be_inserted (bl) || (bl->inserted && !bl->needs_update))
return 0; return 0;
@ -2568,12 +2567,11 @@ insert_bp_location (struct bp_location *bl,
val = bl->owner->ops->insert_location (bl); val = bl->owner->ops->insert_location (bl);
if (val) if (val)
bp_err = GENERIC_ERROR; bp_excpt = gdb_exception {RETURN_ERROR, GENERIC_ERROR};
} }
CATCH (e, RETURN_MASK_ALL) CATCH (e, RETURN_MASK_ALL)
{ {
bp_err = e.error; bp_excpt = e;
bp_err_message = e.message;
} }
END_CATCH END_CATCH
} }
@ -2608,16 +2606,16 @@ insert_bp_location (struct bp_location *bl,
val = target_insert_breakpoint (bl->gdbarch, val = target_insert_breakpoint (bl->gdbarch,
&bl->overlay_target_info); &bl->overlay_target_info);
if (val) if (val)
bp_err = GENERIC_ERROR; bp_excpt
= gdb_exception {RETURN_ERROR, GENERIC_ERROR};
} }
CATCH (e, RETURN_MASK_ALL) CATCH (e, RETURN_MASK_ALL)
{ {
bp_err = e.error; bp_excpt = e;
bp_err_message = e.message;
} }
END_CATCH END_CATCH
if (bp_err != GDB_NO_ERROR) if (bp_excpt.reason != 0)
fprintf_unfiltered (tmp_error_stream, fprintf_unfiltered (tmp_error_stream,
"Overlay breakpoint %d " "Overlay breakpoint %d "
"failed: in ROM?\n", "failed: in ROM?\n",
@ -2634,12 +2632,11 @@ insert_bp_location (struct bp_location *bl,
val = bl->owner->ops->insert_location (bl); val = bl->owner->ops->insert_location (bl);
if (val) if (val)
bp_err = GENERIC_ERROR; bp_excpt = gdb_exception {RETURN_ERROR, GENERIC_ERROR};
} }
CATCH (e, RETURN_MASK_ALL) CATCH (e, RETURN_MASK_ALL)
{ {
bp_err = e.error; bp_excpt = e;
bp_err_message = e.message;
} }
END_CATCH END_CATCH
} }
@ -2651,7 +2648,7 @@ insert_bp_location (struct bp_location *bl,
} }
} }
if (bp_err != GDB_NO_ERROR) if (bp_excpt.reason != 0)
{ {
/* Can't set the breakpoint. */ /* Can't set the breakpoint. */
@ -2663,7 +2660,9 @@ insert_bp_location (struct bp_location *bl,
breakpoint insertion failed (e.g., the remote target breakpoint insertion failed (e.g., the remote target
doesn't define error codes), so we must treat generic doesn't define error codes), so we must treat generic
errors as memory errors. */ errors as memory errors. */
if ((bp_err == GENERIC_ERROR || bp_err == MEMORY_ERROR) if (bp_excpt.reason == RETURN_ERROR
&& (bp_excpt.error == GENERIC_ERROR
|| bp_excpt.error == MEMORY_ERROR)
&& bl->loc_type == bp_loc_software_breakpoint && bl->loc_type == bp_loc_software_breakpoint
&& (solib_name_from_address (bl->pspace, bl->address) && (solib_name_from_address (bl->pspace, bl->address)
|| shared_objfile_contains_address_p (bl->pspace, || shared_objfile_contains_address_p (bl->pspace,
@ -2691,16 +2690,18 @@ insert_bp_location (struct bp_location *bl,
if (bl->loc_type == bp_loc_hardware_breakpoint) if (bl->loc_type == bp_loc_hardware_breakpoint)
{ {
*hw_breakpoint_error = 1; *hw_breakpoint_error = 1;
*hw_bp_error_explained_already = bp_err_message != NULL; *hw_bp_error_explained_already = bp_excpt.message != NULL;
fprintf_unfiltered (tmp_error_stream, fprintf_unfiltered (tmp_error_stream,
"Cannot insert hardware breakpoint %d%s", "Cannot insert hardware breakpoint %d%s",
bl->owner->number, bp_err_message ? ":" : ".\n"); bl->owner->number,
if (bp_err_message != NULL) bp_excpt.message ? ":" : ".\n");
fprintf_unfiltered (tmp_error_stream, "%s.\n", bp_err_message); if (bp_excpt.message != NULL)
fprintf_unfiltered (tmp_error_stream, "%s.\n",
bp_excpt.message);
} }
else else
{ {
if (bp_err_message == NULL) if (bp_excpt.message == NULL)
{ {
std::string message std::string message
= memory_error_message (TARGET_XFER_E_IO, = memory_error_message (TARGET_XFER_E_IO,
@ -2716,7 +2717,7 @@ insert_bp_location (struct bp_location *bl,
fprintf_unfiltered (tmp_error_stream, fprintf_unfiltered (tmp_error_stream,
"Cannot insert breakpoint %d: %s\n", "Cannot insert breakpoint %d: %s\n",
bl->owner->number, bl->owner->number,
bp_err_message); bp_excpt.message);
} }
} }
return 1; return 1;