Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [PATCH] Don't pretend infcalls don't set the inferior running (PR gdb/34082)
@ 2026-04-23 18:49 Pedro Alves
  2026-04-24  8:49 ` Andrew Burgess
  2026-05-08 14:49 ` Tom Tromey
  0 siblings, 2 replies; 7+ messages in thread
From: Pedro Alves @ 2026-04-23 18:49 UTC (permalink / raw)
  To: gdb-patches

Commit 2954dd2b73 ("thread_info::executing+resumed ->
thread_info::internal_state"), caused a regression in
gdb.threads/hand-call-new-thread.exp:

 ...
 (gdb) PASS: gdb.threads/hand-call-new-thread.exp: iter 1: no thread marked running
 p new_thread ()
 .../src/gdb/infrun.c:3742: internal-error: proceed: Assertion `!thread_is_in_step_over_chain (&tp)' failed.
 A problem internal to GDB has been detected,
 further debugging may prove unreliable.
 ----- Backtrace -----
 FAIL: gdb.threads/hand-call-new-thread.exp: iter 2: gdb-command<p new_thread ()> (GDB internal error)
 ...

This commit fixes it.

Let's say we have three threads, 1, 2, and 3.  User does:

 (gdb) continue

This makes GDB switch all three threads to THREAD_RUNNING.

If some of those threads, now running, spawns a new thread, that
thread is also set to state THREAD_RUNNING.  We end up with four
threads marked THREAD_RUNNING.

If e.g., threads 2 and 3 both hit a breakpoint that needs to be
stepped over (e.g., condition evals false), and there is only one
displaced-stepping slot, then one thread starts a displaced stepping
sequence, while the other is put in the step-over queue, waiting for
its turn.

Now, if meanwhile thread 1 hits a user-visible stop, GDB stops all
threads, and transitions all their states to THREAD_STOPPED.  Any
thread that was still waiting for its turn in the step-over queue is
removed from the queue.  That happens in the THREAD_RUNNING =>
THREAD_STOPPED transition, here:

  thread_state
  thread_info::set_state (thread_state state, bool suppress_notification)
  {
  ...
    switch (m_state)
      {
      case THREAD_STOPPED:
        if (thread_is_in_step_over_chain (this))
          global_thread_step_over_chain_remove (this);

The next time the user continues execution, if the breakpoint is still
inserted, proceed() sets them stepping the breakpoint again.  And
again, if there is more than one thread that needs to step-over, and
there aren't enough slots, some threads may end up in the step-over
queue.  Rinse, repeat.

All this works well with normal resumption commands, like continue,
step, next, etc.

The problem exposed by gdb.threads/hand-call-new-thread.exp is if you
resume execution with an infcall instead of a normal execution
command.  In that case, proceed() skips transitioning (pre-existing)
threads to THREAD_RUNNING, here:

  proceed (CORE_ADDR addr, enum gdb_signal siggnal)
  {
   ...
      /* Even if RESUME_PTID is a wildcard, and we end up resuming fewer
	 threads in RESUME_PTID are now running.  Unless we're calling an
	 inferior function, as in that case we pretend the inferior
	 doesn't run at all.  */
      if (!cur_thr->control.in_infcall)
	set_state (resume_target, resume_ptid, THREAD_RUNNING);

So later, when the call finishes for any reason (normal call finish,
or some other user-visible stop happens), and GDB transitions all
threads to THREAD_STOPPED, we hit the early return in
thread_info::set_state:

  thread_state
  thread_info::set_state (thread_state state, bool suppress_notification)
  {
    thread_state prev_state = m_state;
    if (prev_state == state)
      return prev_state;          // <== EARLY RETURN

    m_state = state;
    switch (m_state)
      {
      case THREAD_STOPPED:
        if (thread_is_in_step_over_chain (this))
          global_thread_step_over_chain_remove (this);  // NOT REACHED
        break;
      ...
      }
  }

... and so if any thread had been put in the step-over queue since the
last proceed(), it will incorrectly be left still in the step-over
queue, with THREAD_STOPPED state.

If/when the user re-resumes the program again, we trip the assertion
in proceed:

  (gdb) p new_thread ()
  ../../src/gdb/infrun.c:3742: internal-error: proceed: Assertion `!thread_is_in_step_over_chain (&tp)' failed.
  A problem internal to GDB has been detected,
  further debugging may prove unreliable.

Before commit 2954dd2b73 ("thread_info::executing+resumed ->
thread_info::internal_state"), this didn't happen because
set_running_thread(..., running=false) would remove threads from the
step-over queue unconditionally, even if they were already marked
stopped.

I think the right fix is to stop pretending that infcalls don't set
the target running.  I can't think of a reason we do that.  It really
does run.  Some thoughts:

- I added to code to skip set_running (nowadays 'set_state(...,
  THREAD_RUNNING))' for infcalls back in commit 4d9d9d0423 over 10
  years ago, but I honestly don't recall why.  My guess is that it
  must have been to keep backwards compatibility with something, and
  the code has probably changed sufficiently since then making it no
  longer necessary.

- infcalls are always synchronous, so the intermediate running state
  can't be observed with commands.

- MI still suppresses *running

  The running state could potentially be observed on frontends, with
  e.g., MI's *running => *stopped transitions, but if that is a
  problem, I think it should be handled by the interpreter layer not
  emiting the notifications, instead of hacking the threads's core
  state.  I.e., make it a presentation detail.

  I don't think it would be a problem for frontends to see *running
  during infcalls, but in any case, MI is already suppressing such
  notifications when they are caused by an infcall.  See
  mi_interp::on_target_resumed.

  So e.g., if we let the threads transition to THREAD_RUNNING, with
  MI, we still see no *running/*stopped:

    (gdb)
    p malloc(0)
    &"p malloc(0)\n"
    ~"$2 = (void *) 0x555555560320\n"
    ^done
    (gdb)

  I don't know if it'd be a problem for DAP, but I assume not too.

  Note how the code in proceed that skips setting threads to
  THREAD_RUNNING only applies to already-known threads.  Any new
  thread that appears while the infcall is ongoing will end up marked
  THREAD_RUNNING, causing frontend notifications.  This shows how
  hiding the running state doesn't really hide it completely.

So this is what this commit does.  It lets threads transition to
THREAD_RUNNING even during infcalls, fixing the problem described
above, as now there will be proper THREAD_RUNNING => THREAD_STOPPED
transitions when the infcall finishes.

It also tweaks the testcase to spawn 10 threads per infcall instead of
one.  This makes it much more likely to reproduce the problem on my
machine.  Without it, the test still passes for me, which is why I
didn't see the problem before merging 2954dd2b73.

Tested on x86-64 Linux, native and gdbserver.

Change-Id: I1bdc733ac865102d3f7bf0a4f7f56e6f7d75d457
commit-id:d2abd130
---
 gdb/infrun.c                                     |  9 +++------
 gdb/testsuite/gdb.threads/hand-call-new-thread.c | 16 +++++++++++-----
 2 files changed, 14 insertions(+), 11 deletions(-)

diff --git a/gdb/infrun.c b/gdb/infrun.c
index 6401df78e0a..0e359f0ed74 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -3688,11 +3688,8 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
   /* Even if RESUME_PTID is a wildcard, and we end up resuming fewer
      threads (e.g., we might need to set threads stepping over
      breakpoints first), from the user/frontend's point of view, all
-     threads in RESUME_PTID are now running.  Unless we're calling an
-     inferior function, as in that case we pretend the inferior
-     doesn't run at all.  */
-  if (!cur_thr->control.in_infcall)
-    set_state (resume_target, resume_ptid, THREAD_RUNNING);
+     threads in RESUME_PTID are now running.  */
+  set_state (resume_target, resume_ptid, THREAD_RUNNING);
 
   infrun_debug_printf ("addr=%s, signal=%s, resume_ptid=%s",
 		       paddress (gdbarch, addr),
@@ -6636,7 +6633,7 @@ restart_threads (struct thread_info *event_thread, inferior *inf)
 	  continue;
 	}
 
-      if (!(tp.state () == THREAD_RUNNING || tp.control.in_infcall))
+      if (tp.state () != THREAD_RUNNING)
 	{
 	  infrun_debug_printf ("restart threads: [%s] not meant to be running",
 			       tp.ptid.to_string ().c_str ());
diff --git a/gdb/testsuite/gdb.threads/hand-call-new-thread.c b/gdb/testsuite/gdb.threads/hand-call-new-thread.c
index 620322fff10..04154576351 100644
--- a/gdb/testsuite/gdb.threads/hand-call-new-thread.c
+++ b/gdb/testsuite/gdb.threads/hand-call-new-thread.c
@@ -34,14 +34,20 @@ thread_function (void *arg)
     foo ();
 }
 
+#define NTHREADS 10
+
 void
 new_thread (void)
 {
-  pthread_t thread;
-  int res;
-
-  res = pthread_create (&thread, NULL, thread_function, NULL);
-  assert (res == 0);
+  pthread_t thread[NTHREADS];
+  int i;
+
+  for (i = 0; i < NTHREADS; i++)
+    {
+      int res;
+      res = pthread_create (&thread[i], NULL, thread_function, NULL);
+      assert (res == 0);
+    }
 }
 
 int

base-commit: 8dc535c59fdbcf99e28703425e5c1c711e63a1f1
-- 
2.53.0


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

* Re: [PATCH] Don't pretend infcalls don't set the inferior running (PR gdb/34082)
  2026-04-23 18:49 [PATCH] Don't pretend infcalls don't set the inferior running (PR gdb/34082) Pedro Alves
@ 2026-04-24  8:49 ` Andrew Burgess
  2026-04-24 15:34   ` Pedro Alves
  2026-05-08 14:49 ` Tom Tromey
  1 sibling, 1 reply; 7+ messages in thread
From: Andrew Burgess @ 2026-04-24  8:49 UTC (permalink / raw)
  To: Pedro Alves, gdb-patches


Pedro,

Thanks for fixing this.  No real problems, one trivial nit, and a
question, see below...


Pedro Alves <pedro@palves.net> writes:

> Commit 2954dd2b73 ("thread_info::executing+resumed ->
> thread_info::internal_state"), caused a regression in
> gdb.threads/hand-call-new-thread.exp:
>
>  ...
>  (gdb) PASS: gdb.threads/hand-call-new-thread.exp: iter 1: no thread marked running
>  p new_thread ()
>  .../src/gdb/infrun.c:3742: internal-error: proceed: Assertion `!thread_is_in_step_over_chain (&tp)' failed.
>  A problem internal to GDB has been detected,
>  further debugging may prove unreliable.
>  ----- Backtrace -----
>  FAIL: gdb.threads/hand-call-new-thread.exp: iter 2: gdb-command<p new_thread ()> (GDB internal error)
>  ...
>
> This commit fixes it.
>
> Let's say we have three threads, 1, 2, and 3.  User does:
>
>  (gdb) continue
>
> This makes GDB switch all three threads to THREAD_RUNNING.
>
> If some of those threads, now running, spawns a new thread, that
> thread is also set to state THREAD_RUNNING.  We end up with four
> threads marked THREAD_RUNNING.
>
> If e.g., threads 2 and 3 both hit a breakpoint that needs to be
> stepped over (e.g., condition evals false), and there is only one
> displaced-stepping slot, then one thread starts a displaced stepping
> sequence, while the other is put in the step-over queue, waiting for
> its turn.
>
> Now, if meanwhile thread 1 hits a user-visible stop, GDB stops all
> threads, and transitions all their states to THREAD_STOPPED.  Any
> thread that was still waiting for its turn in the step-over queue is
> removed from the queue.  That happens in the THREAD_RUNNING =>
> THREAD_STOPPED transition, here:
>
>   thread_state
>   thread_info::set_state (thread_state state, bool suppress_notification)
>   {
>   ...
>     switch (m_state)
>       {
>       case THREAD_STOPPED:
>         if (thread_is_in_step_over_chain (this))
>           global_thread_step_over_chain_remove (this);
>
> The next time the user continues execution, if the breakpoint is still
> inserted, proceed() sets them stepping the breakpoint again.  And
> again, if there is more than one thread that needs to step-over, and
> there aren't enough slots, some threads may end up in the step-over
> queue.  Rinse, repeat.
>
> All this works well with normal resumption commands, like continue,
> step, next, etc.
>
> The problem exposed by gdb.threads/hand-call-new-thread.exp is if you
> resume execution with an infcall instead of a normal execution
> command.  In that case, proceed() skips transitioning (pre-existing)
> threads to THREAD_RUNNING, here:
>
>   proceed (CORE_ADDR addr, enum gdb_signal siggnal)
>   {
>    ...
>       /* Even if RESUME_PTID is a wildcard, and we end up resuming fewer
> 	 threads in RESUME_PTID are now running.  Unless we're calling an
> 	 inferior function, as in that case we pretend the inferior
> 	 doesn't run at all.  */
>       if (!cur_thr->control.in_infcall)
> 	set_state (resume_target, resume_ptid, THREAD_RUNNING);
>
> So later, when the call finishes for any reason (normal call finish,
> or some other user-visible stop happens), and GDB transitions all
> threads to THREAD_STOPPED, we hit the early return in
> thread_info::set_state:
>
>   thread_state
>   thread_info::set_state (thread_state state, bool suppress_notification)
>   {
>     thread_state prev_state = m_state;
>     if (prev_state == state)
>       return prev_state;          // <== EARLY RETURN
>
>     m_state = state;
>     switch (m_state)
>       {
>       case THREAD_STOPPED:
>         if (thread_is_in_step_over_chain (this))
>           global_thread_step_over_chain_remove (this);  // NOT REACHED
>         break;
>       ...
>       }
>   }
>
> ... and so if any thread had been put in the step-over queue since the
> last proceed(), it will incorrectly be left still in the step-over
> queue, with THREAD_STOPPED state.
>
> If/when the user re-resumes the program again, we trip the assertion
> in proceed:
>
>   (gdb) p new_thread ()
>   ../../src/gdb/infrun.c:3742: internal-error: proceed: Assertion `!thread_is_in_step_over_chain (&tp)' failed.
>   A problem internal to GDB has been detected,
>   further debugging may prove unreliable.
>
> Before commit 2954dd2b73 ("thread_info::executing+resumed ->
> thread_info::internal_state"), this didn't happen because
> set_running_thread(..., running=false) would remove threads from the
> step-over queue unconditionally, even if they were already marked
> stopped.
>
> I think the right fix is to stop pretending that infcalls don't set
> the target running.  I can't think of a reason we do that.  It really
> does run.  Some thoughts:
>
> - I added to code to skip set_running (nowadays 'set_state(...,

typo: "I added to code" -> "I added THE code" ?

>   THREAD_RUNNING))' for infcalls back in commit 4d9d9d0423 over 10
>   years ago, but I honestly don't recall why.  My guess is that it
>   must have been to keep backwards compatibility with something, and
>   the code has probably changed sufficiently since then making it no
>   longer necessary.
>
> - infcalls are always synchronous, so the intermediate running state
>   can't be observed with commands.

I assume you mean by this that infcalls are something the user initiates
from the prompt, and so while the infcall is running the user cannot
also ask to inspect the thread state.

I don't disagree with any of your conclusions, but, if an infcall is
made as part of a breakpoint condition, then than could run in the
background, asynchronously, while the user is also issuing other
commands.

Not that this changes anything.  In this situation the user believes
that the inferior is running in the background, so seeing the threads as
running is absolutely fine.  I'm just not convinced that the claims made
in this point "infcalls are always asynchronously" and "the intermediate
running state can' be observed" are correct.

But the patch itself makes a lot of sense, and looks good.

Approved-By: Andrew Burgess <aburgess@redhat.com>

Thanks,
Andrew


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

* Re: [PATCH] Don't pretend infcalls don't set the inferior running (PR gdb/34082)
  2026-04-24  8:49 ` Andrew Burgess
@ 2026-04-24 15:34   ` Pedro Alves
  2026-04-29  7:12     ` Andrew Burgess
  0 siblings, 1 reply; 7+ messages in thread
From: Pedro Alves @ 2026-04-24 15:34 UTC (permalink / raw)
  To: Andrew Burgess, gdb-patches

On 2026-04-24 09:49, Andrew Burgess wrote:
> 
> Pedro,
> 
> Thanks for fixing this.  No real problems, one trivial nit, and a
> question, see below...
> 
> 
> Pedro Alves <pedro@palves.net> writes:
>> I think the right fix is to stop pretending that infcalls don't set
>> the target running.  I can't think of a reason we do that.  It really
>> does run.  Some thoughts:
>>
>> - I added to code to skip set_running (nowadays 'set_state(...,
> 
> typo: "I added to code" -> "I added THE code" ?

Yes, thanks, fixed.

> 
>>   THREAD_RUNNING))' for infcalls back in commit 4d9d9d0423 over 10
>>   years ago, but I honestly don't recall why.  My guess is that it
>>   must have been to keep backwards compatibility with something, and
>>   the code has probably changed sufficiently since then making it no
>>   longer necessary.
>>
>> - infcalls are always synchronous, so the intermediate running state
>>   can't be observed with commands.
> 
> I assume you mean by this that infcalls are something the user initiates
> from the prompt, and so while the infcall is running the user cannot
> also ask to inspect the thread state.
> 
> I don't disagree with any of your conclusions, but, if an infcall is
> made as part of a breakpoint condition, then than could run in the
> background, asynchronously, while the user is also issuing other
> commands.

No, it really can't.  Try something like this:

~~~~~~~~~~~~~~~~~~~~~~~~
#include <unistd.h>

static int
foo (void)
{
  usleep (1);
  return 0;
}

int
return_false ()
{
  sleep (10);     // <===  each condition eval will do an infcall that takes 10s.
  return 0;
}

int
main (int argc, char **argv)
{
  while (1)
    foo ();
  return 0;
}
~~~~~~~~~~~~~~~~~~~~~~~~


$ gdb -q ./a.bout -ex "start"
...
Temporary breakpoint 1, main (argc=1, argv=0x7fffffffd888) at test.c:64
64          foo ();
(gdb) b foo if return_false ()
Breakpoint 2 at 0x5555555551b1: file test.c, line 26.
(gdb) c&
Continuing.
(gdb) info threads
* hangs for up to 10 seconds here *
info threads
  Id   Target Id                                             Frame 
* 1    Thread 0x7ffff7f8f740 (LWP 1821559) "hand-call-new-t" (running)
(gdb) 
  Id   Target Id                                             Frame 
* 1    Thread 0x7ffff7f8f740 (LWP 1821559) "hand-call-new-t" (running)
(gdb) p 1
* hangs for up to 10 seconds here *
p 1
$1 = 1
(gdb) 

You have to try it to get a feel, but what happens is that GDB does not react
to commands while the infcall is ongoing, leading to those up to 10 seconds "hangs".

See here, in infcall.c:run_inferior_call:


      /* Infcalls run synchronously, in the foreground.  */
      scoped_restore restore_prompt_state
	= make_scoped_restore (&current_ui->prompt_state, PROMPT_BLOCKED);

      ...
      proceed ();
      ...

      /* Inferior function calls are always synchronous, even if the
	 target supports asynchronous execution.  */
      wait_sync_command_done ();


There's an old 
"SNIP - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP"
line in infcall.c that suggests where we'd split the infcall machinery into a state machine.


But I think it'd be way more complicated than that hint suggests, infcalls happen in
the middle of expression evaluation, and the state for the expression is all on the stack.
We can't go back to the top event loop in the middle of an expression.  Not to mention 
we evaluate expressions all over the place, in the most innocuous-looking commands.
Any parse_and_eval with user input is potentially an infcall.


Also, if it were possible to issue command while a breakpoint condition is in the middle
of an infcall, the thread should still be considered THREAD_RUNNING up until the condition
evals false, meaning it really causes a user-visible stop.  So in that scenario, while
running the infcall, the thread would have been THREAD_RUNNING all the while, meaning,
there would be nothing new the user would be able to observe with this change.

> 
> Not that this changes anything.  In this situation the user believes
> that the inferior is running in the background, so seeing the threads as
> running is absolutely fine.  I'm just not convinced that the claims made
> in this point "infcalls are always asynchronously" and "the intermediate
> running state can' be observed" are correct.
> 
> But the patch itself makes a lot of sense, and looks good.
> 
> Approved-By: Andrew Burgess <aburgess@redhat.com>

Thanks.

Pedro Alves

> 
> Thanks,
> Andrew
> 


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

* Re: [PATCH] Don't pretend infcalls don't set the inferior running (PR gdb/34082)
  2026-04-24 15:34   ` Pedro Alves
@ 2026-04-29  7:12     ` Andrew Burgess
  0 siblings, 0 replies; 7+ messages in thread
From: Andrew Burgess @ 2026-04-29  7:12 UTC (permalink / raw)
  To: Pedro Alves, gdb-patches

Pedro Alves <pedro@palves.net> writes:

> On 2026-04-24 09:49, Andrew Burgess wrote:
>> 
>> Pedro,
>> 
>> Thanks for fixing this.  No real problems, one trivial nit, and a
>> question, see below...
>> 
>> 
>> Pedro Alves <pedro@palves.net> writes:
>>> I think the right fix is to stop pretending that infcalls don't set
>>> the target running.  I can't think of a reason we do that.  It really
>>> does run.  Some thoughts:
>>>
>>> - I added to code to skip set_running (nowadays 'set_state(...,
>> 
>> typo: "I added to code" -> "I added THE code" ?
>
> Yes, thanks, fixed.
>
>> 
>>>   THREAD_RUNNING))' for infcalls back in commit 4d9d9d0423 over 10
>>>   years ago, but I honestly don't recall why.  My guess is that it
>>>   must have been to keep backwards compatibility with something, and
>>>   the code has probably changed sufficiently since then making it no
>>>   longer necessary.
>>>
>>> - infcalls are always synchronous, so the intermediate running state
>>>   can't be observed with commands.
>> 
>> I assume you mean by this that infcalls are something the user initiates
>> from the prompt, and so while the infcall is running the user cannot
>> also ask to inspect the thread state.
>> 
>> I don't disagree with any of your conclusions, but, if an infcall is
>> made as part of a breakpoint condition, then than could run in the
>> background, asynchronously, while the user is also issuing other
>> commands.
>
> No, it really can't.  Try something like this:
>
> ~~~~~~~~~~~~~~~~~~~~~~~~
> #include <unistd.h>
>
> static int
> foo (void)
> {
>   usleep (1);
>   return 0;
> }
>
> int
> return_false ()
> {
>   sleep (10);     // <===  each condition eval will do an infcall that takes 10s.
>   return 0;
> }
>
> int
> main (int argc, char **argv)
> {
>   while (1)
>     foo ();
>   return 0;
> }
> ~~~~~~~~~~~~~~~~~~~~~~~~
>
>
> $ gdb -q ./a.bout -ex "start"
> ...
> Temporary breakpoint 1, main (argc=1, argv=0x7fffffffd888) at test.c:64
> 64          foo ();
> (gdb) b foo if return_false ()
> Breakpoint 2 at 0x5555555551b1: file test.c, line 26.
> (gdb) c&
> Continuing.
> (gdb) info threads
> * hangs for up to 10 seconds here *
> info threads
>   Id   Target Id                                             Frame 
> * 1    Thread 0x7ffff7f8f740 (LWP 1821559) "hand-call-new-t" (running)
> (gdb) 
>   Id   Target Id                                             Frame 
> * 1    Thread 0x7ffff7f8f740 (LWP 1821559) "hand-call-new-t" (running)
> (gdb) p 1
> * hangs for up to 10 seconds here *
> p 1
> $1 = 1
> (gdb) 
>
> You have to try it to get a feel, but what happens is that GDB does not react
> to commands while the infcall is ongoing, leading to those up to 10 seconds "hangs".
>
> See here, in infcall.c:run_inferior_call:
>
>
>       /* Infcalls run synchronously, in the foreground.  */
>       scoped_restore restore_prompt_state
> 	= make_scoped_restore (&current_ui->prompt_state, PROMPT_BLOCKED);
>
>       ...
>       proceed ();
>       ...
>
>       /* Inferior function calls are always synchronous, even if the
> 	 target supports asynchronous execution.  */
>       wait_sync_command_done ();
>
>
> There's an old 
> "SNIP - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP"
> line in infcall.c that suggests where we'd split the infcall machinery into a state machine.
>
>
> But I think it'd be way more complicated than that hint suggests, infcalls happen in
> the middle of expression evaluation, and the state for the expression is all on the stack.
> We can't go back to the top event loop in the middle of an expression.  Not to mention 
> we evaluate expressions all over the place, in the most innocuous-looking commands.
> Any parse_and_eval with user input is potentially an infcall.
>
>
> Also, if it were possible to issue command while a breakpoint condition is in the middle
> of an infcall, the thread should still be considered THREAD_RUNNING up until the condition
> evals false, meaning it really causes a user-visible stop.  So in that scenario, while
> running the infcall, the thread would have been THREAD_RUNNING all the while, meaning,
> there would be nothing new the user would be able to observe with this
> change.

Thanks for taking the time to explain this.  That all makes sense.

Thanks,
Andrew


>
>> 
>> Not that this changes anything.  In this situation the user believes
>> that the inferior is running in the background, so seeing the threads as
>> running is absolutely fine.  I'm just not convinced that the claims made
>> in this point "infcalls are always asynchronously" and "the intermediate
>> running state can' be observed" are correct.
>> 
>> But the patch itself makes a lot of sense, and looks good.
>> 
>> Approved-By: Andrew Burgess <aburgess@redhat.com>
>
> Thanks.
>
> Pedro Alves
>
>> 
>> Thanks,
>> Andrew
>> 


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

* Re: [PATCH] Don't pretend infcalls don't set the inferior running (PR gdb/34082)
  2026-04-23 18:49 [PATCH] Don't pretend infcalls don't set the inferior running (PR gdb/34082) Pedro Alves
  2026-04-24  8:49 ` Andrew Burgess
@ 2026-05-08 14:49 ` Tom Tromey
  2026-05-08 21:33   ` Pedro Alves
  1 sibling, 1 reply; 7+ messages in thread
From: Tom Tromey @ 2026-05-08 14:49 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

>>>>> "Pedro" == Pedro Alves <pedro@palves.net> writes:

Pedro> I think the right fix is to stop pretending that infcalls don't set
Pedro> the target running.  I can't think of a reason we do that.  It really
Pedro> does run.  Some thoughts:

This makes total sense to me, and I think it's a good direction.
However, unfortunately this patch caused some regressions in
compile.exp.

Looking at gdb.log it seems like maybe something isn't being updated on
an error path:

compile code *(volatile int *) 0 = 0;
The program being debugged received signal SIGSEGV, Segmentation fault
while in a function called from GDB.  GDB has restored the context
to what it was before the call.  To change this behavior use
"set unwind-on-signal off".  Evaluation of the expression containing
the function (_gdb_expr) will be abandoned.
(gdb) PASS: gdb.compile/compile.exp: compile code segfault second
break 132
Breakpoint 2 at 0x400521: file /home/tromey/gdb/build/gdb/testsuite/../../../binutils-gdb/gdb/testsuite/gdb.compile/compile.c, line 132.
(gdb) continue
Cannot execute this command while the selected thread is running.


After this point there are several such errors.

I'm happy to file a bug if you'd prefer.

Tom

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

* Re: [PATCH] Don't pretend infcalls don't set the inferior running (PR gdb/34082)
  2026-05-08 14:49 ` Tom Tromey
@ 2026-05-08 21:33   ` Pedro Alves
  2026-05-13 15:34     ` Tom Tromey
  0 siblings, 1 reply; 7+ messages in thread
From: Pedro Alves @ 2026-05-08 21:33 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 2026-05-08 15:49, Tom Tromey wrote:
>>>>>> "Pedro" == Pedro Alves <pedro@palves.net> writes:
> 
> Pedro> I think the right fix is to stop pretending that infcalls don't set
> Pedro> the target running.  I can't think of a reason we do that.  It really
> Pedro> does run.  Some thoughts:
> 
> This makes total sense to me, and I think it's a good direction.
> However, unfortunately this patch caused some regressions in
> compile.exp.
> 
> Looking at gdb.log it seems like maybe something isn't being updated on
> an error path:
> 
> compile code *(volatile int *) 0 = 0;
> The program being debugged received signal SIGSEGV, Segmentation fault
> while in a function called from GDB.  GDB has restored the context
> to what it was before the call.  To change this behavior use
> "set unwind-on-signal off".  Evaluation of the expression containing
> the function (_gdb_expr) will be abandoned.
> (gdb) PASS: gdb.compile/compile.exp: compile code segfault second
> break 132
> Breakpoint 2 at 0x400521: file /home/tromey/gdb/build/gdb/testsuite/../../../binutils-gdb/gdb/testsuite/gdb.compile/compile.c, line 132.
> (gdb) continue
> Cannot execute this command while the selected thread is running.
> 

Bah, my build doesn't have libcc1 support:

 PASS: gdb.compile/compile.exp: test compile code command without running inferior
 PASS: gdb.compile/compile.exp: test compile command without running inferior
 PASS: gdb.compile/compile.exp: test compile file command without running inferior
 UNTESTED: gdb.compile/compile.exp: compile command not supported (could not find libcc1)

I'll see if I can set that up.

Also sounds like we may be missing an infcall test that exercises this case without
relying on "compile".

> 
> After this point there are several such errors.
> 
> I'm happy to file a bug if you'd prefer.
> 
That'd be great!  I might not be able to look at this until later next week.  Thanks.

Pedro Alves


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

* Re: [PATCH] Don't pretend infcalls don't set the inferior running (PR gdb/34082)
  2026-05-08 21:33   ` Pedro Alves
@ 2026-05-13 15:34     ` Tom Tromey
  0 siblings, 0 replies; 7+ messages in thread
From: Tom Tromey @ 2026-05-13 15:34 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

>>>>> "Pedro" == Pedro Alves <pedro@palves.net> writes:
>> I'm happy to file a bug if you'd prefer.

Pedro> That'd be great!  I might not be able to look at this until later next week.  Thanks.

I CC'd you but FTR it is https://sourceware.org/bugzilla/show_bug.cgi?id=34148

Tom

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

end of thread, other threads:[~2026-05-13 15:35 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-04-23 18:49 [PATCH] Don't pretend infcalls don't set the inferior running (PR gdb/34082) Pedro Alves
2026-04-24  8:49 ` Andrew Burgess
2026-04-24 15:34   ` Pedro Alves
2026-04-29  7:12     ` Andrew Burgess
2026-05-08 14:49 ` Tom Tromey
2026-05-08 21:33   ` Pedro Alves
2026-05-13 15:34     ` Tom Tromey

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