Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [PATCH master/7.12] Throw error when ptrace fail in regsets_fetch_inferior_registers
@ 2016-08-03 13:19 Yao Qi
  2016-08-03 14:21 ` Pedro Alves
  0 siblings, 1 reply; 5+ messages in thread
From: Yao Qi @ 2016-08-03 13:19 UTC (permalink / raw)
  To: gdb-patches

When I run process-dies-while-detaching.exp with GDBserver, I see many
warnings printed by GDBserver,

ptrace(regsets_fetch_inferior_registers) PID=26183: No such process
ptrace(regsets_fetch_inferior_registers) PID=26183: No such process
ptrace(regsets_fetch_inferior_registers) PID=26184: No such process
ptrace(regsets_fetch_inferior_registers) PID=26184: No such process

regsets_fetch_inferior_registers is called when GDBserver resumes each
lwp.

 #2  0x0000000000428260 in regsets_fetch_inferior_registers (regsets_info=0x4690d0 <aarch64_regsets_info>, regcache=0x31832020)
    at /home/yao/SourceCode/gnu/gdb/git/gdb/gdbserver/linux-low.c:5412
 #3  0x00000000004070e8 in get_thread_regcache (thread=0x31832940, fetch=fetch@entry=1) at /home/yao/SourceCode/gnu/gdb/git/gdb/gdbserver/regcache.c:58
 #4  0x0000000000429c40 in linux_resume_one_lwp_throw (info=<optimized out>, signal=0, step=0, lwp=0x31832830)
    at /home/yao/SourceCode/gnu/gdb/git/gdb/gdbserver/linux-low.c:4463
 #5  linux_resume_one_lwp (lwp=0x31832830, step=<optimized out>, signal=<optimized out>, info=<optimized out>)
    at /home/yao/SourceCode/gnu/gdb/git/gdb/gdbserver/linux-low.c:4573

The is the case that threads are disappeared when GDB/GDBserver resumes
them.  Our fix nowadays is to throw exception, caller
linux_resume_one_lwp catches the exception, and swallow it if the lwp
is gone.  See linux-low.c:linux_resume_one_lwp.  So this patch fixes
the problem by throwing exception in regsets_fetch_inferior_registers.
Another caller of regsets_fetch_inferior_registers, linux_fetch_registers,
needs to catch the exception the same way as linux_resume_one_lwp does.

gdb/gdbserver:

2016-08-02  Yao Qi  <yao.qi@linaro.org>

	* linux-low.c (regsets_fetch_inferior_registers): Throw
	exception on ptrace fail.
	(linux_fetch_registers): Rename to ...
	(linux_fetch_registers_throw): ... it.
	(linux_fetch_registers): Call linux_fetch_registers_throw
	and catch the exception.  If check_ptrace_stopped_lwp_gone
	is false, throw it again.
---
 gdb/gdbserver/linux-low.c | 21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index e251ac4..c72b78c 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -5410,7 +5410,7 @@ regsets_fetch_inferior_registers (struct regsets_info *regsets_info,
 	      char s[256];
 	      sprintf (s, "ptrace(regsets_fetch_inferior_registers) PID=%d",
 		       pid);
-	      perror (s);
+	      perror_with_name (_(s));
 	    }
 	}
       else
@@ -5702,7 +5702,7 @@ usr_store_inferior_registers (const struct regs_info *regs_info,
 
 
 static void
-linux_fetch_registers (struct regcache *regcache, int regno)
+linux_fetch_registers_throw (struct regcache *regcache, int regno)
 {
   int use_regsets;
   int all = 0;
@@ -5735,6 +5735,23 @@ linux_fetch_registers (struct regcache *regcache, int regno)
 }
 
 static void
+linux_fetch_registers (struct regcache *regcache, int regno)
+{
+  TRY
+    {
+      linux_fetch_registers_throw (regcache, regno);
+    }
+  CATCH (ex, RETURN_MASK_ERROR)
+    {
+      struct lwp_info *lwp = get_thread_lwp (current_thread);
+
+      if (!check_ptrace_stopped_lwp_gone (lwp))
+	throw_exception (ex);
+    }
+  END_CATCH
+}
+
+static void
 linux_store_registers (struct regcache *regcache, int regno)
 {
   int use_regsets;
-- 
1.9.1


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH master/7.12] Throw error when ptrace fail in regsets_fetch_inferior_registers
  2016-08-03 13:19 [PATCH master/7.12] Throw error when ptrace fail in regsets_fetch_inferior_registers Yao Qi
@ 2016-08-03 14:21 ` Pedro Alves
  2016-08-03 15:43   ` Yao Qi
  0 siblings, 1 reply; 5+ messages in thread
From: Pedro Alves @ 2016-08-03 14:21 UTC (permalink / raw)
  To: Yao Qi, gdb-patches

On 08/03/2016 02:19 PM, Yao Qi wrote:
> When I run process-dies-while-detaching.exp with GDBserver, I see many
> warnings printed by GDBserver,
> 
> ptrace(regsets_fetch_inferior_registers) PID=26183: No such process
> ptrace(regsets_fetch_inferior_registers) PID=26183: No such process
> ptrace(regsets_fetch_inferior_registers) PID=26184: No such process
> ptrace(regsets_fetch_inferior_registers) PID=26184: No such process
> 
> regsets_fetch_inferior_registers is called when GDBserver resumes each
> lwp.
> 
>  #2  0x0000000000428260 in regsets_fetch_inferior_registers (regsets_info=0x4690d0 <aarch64_regsets_info>, regcache=0x31832020)
>     at /home/yao/SourceCode/gnu/gdb/git/gdb/gdbserver/linux-low.c:5412
>  #3  0x00000000004070e8 in get_thread_regcache (thread=0x31832940, fetch=fetch@entry=1) at /home/yao/SourceCode/gnu/gdb/git/gdb/gdbserver/regcache.c:58
>  #4  0x0000000000429c40 in linux_resume_one_lwp_throw (info=<optimized out>, signal=0, step=0, lwp=0x31832830)
>     at /home/yao/SourceCode/gnu/gdb/git/gdb/gdbserver/linux-low.c:4463
>  #5  linux_resume_one_lwp (lwp=0x31832830, step=<optimized out>, signal=<optimized out>, info=<optimized out>)
>     at /home/yao/SourceCode/gnu/gdb/git/gdb/gdbserver/linux-low.c:4573
> 
> The is the case that threads are disappeared when GDB/GDBserver resumes
> them.  Our fix nowadays is to throw exception, caller
> linux_resume_one_lwp catches the exception, and swallow it if the lwp
> is gone.  See linux-low.c:linux_resume_one_lwp.  So this patch fixes
> the problem by throwing exception in regsets_fetch_inferior_registers.
> Another caller of regsets_fetch_inferior_registers, linux_fetch_registers,
> needs to catch the exception the same way as linux_resume_one_lwp does.
> 

Throwing is useful when the exception needs to cross several layers.
Originally that was added because the exceptions had to cross through
multiple layers, including inf-ptrace.c and the regcache.

In cases where we have the ptrace errno code at hand, we can simply
check for ESRCH.  That is, in fact what regsets_store_inferior_registers
does.

	  else if (errno == ESRCH)
	    {
	      /* At this point, ESRCH should mean the process is
		 already gone, in which case we simply ignore attempts
		 to change its registers.  See also the related
		 comment in linux_resume_one_lwp.  */
	      free (buf);
	      return 0;
	    }


(store_register checks ESRCH too instead of throwing, as well
as linux_detach_one_lwp and attach_proc_task_lwp_callback.)

However, I don't think swallowing a register/write error is always the
best to do.

If we're resuming the program, then yes, we should swallow the error,
because now that the thread is resumed, we'll collect the exit
status shortly.

But if the thread is _not_ resumed, the user has the now-dead thread
selected, and does "info registers" or "p $somereg = 0xf00" -- then I
think we should report back the error all the way back to the user,
not swallow it and display random garbage for register contents, or
pretend the write succeeded.

So if we go the throw route, I think the catch should be somewhere
higher level, in the code that is reading/writing registers because
it is resuming the thread.  See how linux-nat.c:resume_stopped_resumed_lwps's
TRY block encloses more than one call that might throw.

It may be that in this case the register read is coming from gdb
directly (really no idea), which would mean that it's gdb that
would have to ignore the error, which would complicate things.

But until that is gone, I see no reason to prefer a throw/catch
instead of simply checking for ESRCH, mirroring
regsets_store_inferior_registers?

Thanks,
Pedro Alves


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH master/7.12] Throw error when ptrace fail in regsets_fetch_inferior_registers
  2016-08-03 14:21 ` Pedro Alves
@ 2016-08-03 15:43   ` Yao Qi
  2016-08-03 17:54     ` Pedro Alves
  0 siblings, 1 reply; 5+ messages in thread
From: Yao Qi @ 2016-08-03 15:43 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Yao Qi, gdb-patches

Pedro Alves <palves@redhat.com> writes:

> Throwing is useful when the exception needs to cross several layers.
> Originally that was added because the exceptions had to cross through
> multiple layers, including inf-ptrace.c and the regcache.
>
> In cases where we have the ptrace errno code at hand, we can simply
> check for ESRCH.  That is, in fact what regsets_store_inferior_registers
> does.
>
> 	  else if (errno == ESRCH)
> 	    {
> 	      /* At this point, ESRCH should mean the process is
> 		 already gone, in which case we simply ignore attempts
> 		 to change its registers.  See also the related
> 		 comment in linux_resume_one_lwp.  */
> 	      free (buf);
> 	      return 0;
> 	    }
>
>
> (store_register checks ESRCH too instead of throwing, as well
> as linux_detach_one_lwp and attach_proc_task_lwp_callback.)

The reason I choose throw exception is that
regsets_fetch_inferior_registers is called by linux_resume_one_lwp_throw
which throws exception when process is gone.  Even if
regsets_fetch_inferior_registers handles ESRCH quietly, the exception
will be thrown out somewhere else in the callees of
linux_resume_one_lwp_throw.  It is better to throw exception earlier to
avoid some unnecessary operations, for example, in
linux_resume_one_lwp_throw,

      struct regcache *regcache = get_thread_regcache (current_thread, 1);

      lwp->stop_pc = (*the_low_target.get_pc) (regcache);

      if (debug_threads)
	{
	  debug_printf ("  %s from pc 0x%lx\n", step ? "step" : "continue",
			(long) lwp->stop_pc);
	}

if we don't throw exception in regsets_fetch_inferior_registers,
lwp->stop_pc will have the garbage value, unless we check the status of
pc register in regcache in each backend, see whether its status is
REG_UNAVAILABLE or not.  Maybe, since lwp is gone, the value
lwp->stop_pc doesn't matter too much.

>
> However, I don't think swallowing a register/write error is always the
> best to do.
>
> If we're resuming the program, then yes, we should swallow the error,
> because now that the thread is resumed, we'll collect the exit
> status shortly.
>
> But if the thread is _not_ resumed, the user has the now-dead thread
> selected, and does "info registers" or "p $somereg = 0xf00" -- then I
> think we should report back the error all the way back to the user,
> not swallow it and display random garbage for register contents, or
> pretend the write succeeded.

nowadays, GDBserver does this in get_thread_regcache,

      /* Invalidate all registers, to prevent stale left-overs.  */
      memset (regcache->register_status, REG_UNAVAILABLE,
	      regcache->tdesc->num_registers);
      fetch_inferior_registers (regcache, -1);

if the thread is gone, the status of registers is REG_UNAVAILABLE.

>
> So if we go the throw route, I think the catch should be somewhere
> higher level, in the code that is reading/writing registers because
> it is resuming the thread.  See how linux-nat.c:resume_stopped_resumed_lwps's
> TRY block encloses more than one call that might throw.
>
> It may be that in this case the register read is coming from gdb
> directly (really no idea), which would mean that it's gdb that
> would have to ignore the error, which would complicate things.

Yes, I agree.

>
> But until that is gone, I see no reason to prefer a throw/catch
> instead of simply checking for ESRCH, mirroring
> regsets_store_inferior_registers?

OK, how about the patch below?

-- 
Yao (齐尧)
From e5585c0c5544fc2ed3b8aa3b1d709530c9adda84 Mon Sep 17 00:00:00 2001
From: Yao Qi <yao.qi@linaro.org>
Date: Fri, 29 Jul 2016 09:59:40 +0100
Subject: [PATCH] Quiet ptrace error ESRCH in regsets_fetch_inferior_registers

When I run process-dies-while-detaching.exp with GDBserver, I see many
warnings printed by GDBserver,

ptrace(regsets_fetch_inferior_registers) PID=26183: No such process
ptrace(regsets_fetch_inferior_registers) PID=26183: No such process
ptrace(regsets_fetch_inferior_registers) PID=26184: No such process
ptrace(regsets_fetch_inferior_registers) PID=26184: No such process

regsets_fetch_inferior_registers is called when GDBserver resumes each
lwp.

 #2  0x0000000000428260 in regsets_fetch_inferior_registers (regsets_info=0x4690d0 <aarch64_regsets_info>, regcache=0x31832020)
    at /home/yao/SourceCode/gnu/gdb/git/gdb/gdbserver/linux-low.c:5412
 #3  0x00000000004070e8 in get_thread_regcache (thread=0x31832940, fetch=fetch@entry=1) at /home/yao/SourceCode/gnu/gdb/git/gdb/gdbserver/regcache.c:58
 #4  0x0000000000429c40 in linux_resume_one_lwp_throw (info=<optimized out>, signal=0, step=0, lwp=0x31832830)
    at /home/yao/SourceCode/gnu/gdb/git/gdb/gdbserver/linux-low.c:4463
 #5  linux_resume_one_lwp (lwp=0x31832830, step=<optimized out>, signal=<optimized out>, info=<optimized out>)
    at /home/yao/SourceCode/gnu/gdb/git/gdb/gdbserver/linux-low.c:4573

The is the case that threads are disappeared when GDB/GDBserver resumes
them.  We check errno for ESRCH, and don't print error messages, like
what we are doing in regsets_store_inferior_registers.

gdb/gdbserver:

2016-08-03  Yao Qi  <yao.qi@linaro.org>

	* linux-low.c (regsets_fetch_inferior_registers): Check
	errno is ESRCH or not.

diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index e251ac4..1839f99 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -5405,6 +5405,12 @@ regsets_fetch_inferior_registers (struct regsets_info *regsets_info,
 		 not "active".  This can happen in normal operation,
 		 so suppress the warning in this case.  */
 	    }
+	  else if (errno == ESRCH)
+	    {
+	      /* At this point, ESRCH should mean the process is
+		 already gone, in which case we simply ignore attempts
+		 to read its registers.  */
+	    }
 	  else
 	    {
 	      char s[256];


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH master/7.12] Throw error when ptrace fail in regsets_fetch_inferior_registers
  2016-08-03 15:43   ` Yao Qi
@ 2016-08-03 17:54     ` Pedro Alves
  2016-08-04 10:13       ` Yao Qi
  0 siblings, 1 reply; 5+ messages in thread
From: Pedro Alves @ 2016-08-03 17:54 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

On 08/03/2016 04:42 PM, Yao Qi wrote:

> OK, how about the patch below?

LGTM.

Thanks,
Pedro Alves


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH master/7.12] Throw error when ptrace fail in regsets_fetch_inferior_registers
  2016-08-03 17:54     ` Pedro Alves
@ 2016-08-04 10:13       ` Yao Qi
  0 siblings, 0 replies; 5+ messages in thread
From: Yao Qi @ 2016-08-04 10:13 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On Wed, Aug 3, 2016 at 6:54 PM, Pedro Alves <palves@redhat.com> wrote:
> On 08/03/2016 04:42 PM, Yao Qi wrote:
>
>> OK, how about the patch below?
>
> LGTM.
>

Thanks, patch is pushed in to master and 7.12.

-- 
Yao (齐尧)


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2016-08-04 10:13 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-08-03 13:19 [PATCH master/7.12] Throw error when ptrace fail in regsets_fetch_inferior_registers Yao Qi
2016-08-03 14:21 ` Pedro Alves
2016-08-03 15:43   ` Yao Qi
2016-08-03 17:54     ` Pedro Alves
2016-08-04 10:13       ` Yao Qi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox