public inbox for gdb@sourceware.org
 help / color / mirror / Atom feed
From: Pedro Alves <palves@redhat.com>
To: Andreas Arnez <arnez@linux.vnet.ibm.com>
Cc: jan.kratochvil@redhat.com, gdb@sourceware.org
Subject: Re: Strange behavior of sigstep-threads.exp?
Date: Mon, 12 Nov 2012 16:38:00 -0000	[thread overview]
Message-ID: <50A125FD.8090504@redhat.com> (raw)
In-Reply-To: <878vacnlem.fsf@linux.vnet.ibm.com>

On 11/08/2012 03:50 PM, Andreas Arnez wrote:
> On x86-64 with upstream GDB, I'm observing what I consider strange
> behavior of the sigstep-threads.exp test case.
> 
> Here's an excerpt from the log file:
> 
>   32        var++;                /* step-1 */
>   (gdb) disable $step1
>   (gdb) step
> 
>   Program received signal SIGUSR1, User defined signal 1.
> 
>   Program received signal SIGUSR1, User defined signal 1.
> 
>   Program received signal SIGUSR1, User defined signal 1.
> 
>   Program received signal SIGUSR1, User defined signal 1.
>   33        tgkill (getpid (), gettid (), SIGUSR1);       /* step-2 */
> 
> It seems that running from step-1 to step-2 produced four SIGUSR1.  And
> in total ca. 3 times as many signals are encountered than we pass
> tgkill()'s:
> 
>   $ grep tgkill gdb.log | wc
>       100    1000    5900
>   $ grep 'Program received signal SIGUSR1' gdb.log | wc
>       310    2480   17670
> 
> From the code I wouldn't expect that.  Is this a known bug or expected
> behavior?  Note that the test case doesn't fail, since it doesn't care
> about the number of incoming signals.

static void
handler (int signo)	/* step-0 */
{			/* step-0 */
  var++;		/* step-1 */
  tgkill (getpid (), gettid (), SIGUSR1);	/* step-2 */
}

static void *
start (void *arg)
{
  tgkill (getpid (), gettid (), SIGUSR1);
  assert (0);
  return NULL;
}

int
main (void)
{
  pthread_t thread;

  signal (SIGUSR1, handler);

  pthread_create (&thread, NULL, start, NULL);
  start (NULL);	/* main-start */
  return 0;
}

There are two threads in the test.  The main thread, and another
spawned by pthread_create.  They both start at "start", and
send SIGUSR1 to themselves.  The SIGUSR1 handler sends a
SIGUSR1 to the current thread, so each thread is constantly re-entering
"handler" ad infinitum.

The test does "handle SIGUSR1 nostop print pass", which means that
control is never passed to the user whenever the program gets a
SIGUSR1, but GDB still prints the signal (the "Program received ..." lines).

The test then steps _one_ of the threads (the one that happens to reach
the "step-1" line first), let's call it thread #1.  This "step" involves
multiple single-steps behind the scenes.  Whenever each of those single-steps
is done, the other thread (let's call it thread #2) is allowed to run free (the
"set scheduler-locking off" setting).  Occasionally, that other thread
will run enough to send itself another SIGUSR1.  And then, occasionally
GDB will see that SIGUSR1 in thread #2, print "Program received", and
go back to single-stepping thread #1, until it reaches a different line.

So "grep tgkill gdb.log" will only count the "step"s that have passed
through the "tgkill (getpid (), ..." line, while "grep 'Program received
signal SIGUSR1'" counts both threads sending themselves SIGUSR1.

Moreover, since thread #2 is "continued", while thread #1 is
single-stepped, it is expected that thread #2 makes progress faster, hence
the 3 to 1 ratio you see.  I see 4 to 1 on my machine even.

> On s390x the test case actually fails sometimes.  In those cases, when
> stepping from step-1 to step-2, a ton of SIGUSR1 are indicated, and then
> the inferior seems to stop at the closing brace of the handler()
> function instead of the tgkill().

That does sound like something's wrong.  Hacking the the test to force
"set debug infrun 1" and "set debug lin-lwp 1" would be my first move.

I wonder if this makes a difference?

 gdb/infrun.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/gdb/infrun.c b/gdb/infrun.c
index de2cf19..9621b84 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -4698,8 +4698,10 @@ process_event_stop_test:
 	  ecs->event_thread = tp;
 	  ecs->ptid = tp->ptid;
 	  context_switch (ecs->ptid);
-	  keep_going (ecs);
-	  return;
+
+	  /* Keep checking.  The stepped thread might have already
+	     reached its destination, but not have reported it yet.
+	     If we just kept going, we could end up overstepping.  */
 	}
     }


  reply	other threads:[~2012-11-12 16:38 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-11-08 15:51 Andreas Arnez
2012-11-12 16:38 ` Pedro Alves [this message]
2012-11-13 15:21   ` Andreas Arnez
2012-11-14 16:15     ` Pedro Alves
2012-11-21 18:47       ` Andreas Arnez
2012-11-21 19:19         ` Pedro Alves

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=50A125FD.8090504@redhat.com \
    --to=palves@redhat.com \
    --cc=arnez@linux.vnet.ibm.com \
    --cc=gdb@sourceware.org \
    --cc=jan.kratochvil@redhat.com \
    /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).