Bug 20039 - Using MI/all-stop, can't interrupt multi-threaded program after continue
Summary: Using MI/all-stop, can't interrupt multi-threaded program after continue
Status: RESOLVED FIXED
Alias: None
Product: gdb
Classification: Unclassified
Component: gdb (show other bugs)
Version: 7.11
: P2 normal
Target Milestone: 7.11.1
Assignee: Simon Marchi
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-05-03 13:57 UTC by Simon Marchi
Modified: 2016-05-18 14:31 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
Source to reproduce (197 bytes, text/x-csrc)
2016-05-03 13:57 UTC, Simon Marchi
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Simon Marchi 2016-05-03 13:57:43 UTC
Created attachment 9233 [details]
Source to reproduce

This bug affects gdb 7.11, but not the current master.

In these conditions:

- all-stop
- multi-threaded inferior
- using MI

It is not possible to interrupt a program after doing a continue.  I attached a small source file, here are the steps to reproduce:

$ gcc test.c -pthread -o test
$ ./gdb -nx -i mi test

Then, type:

- run
- ctrl-C
- continue
- ctrl-C

The last ctrl-C fails to interrupt the program.

I was a bit surprised, but bisecting found that the problem started with this commit:

  7e0aa6aa9983c745aedc203db0cc360a0ad47cac
  List inferiors/threads/pspaces in ascending order

Since this patch does not look directly related to the problem, I suppose the bug was already there and it only uncovered it.

The bug was later fixed in master by:

  5fe966540d6b748f825774868463003700f0c878
  Use target_terminal_ours_for_output in MI

This last patch was pushed as part of big series, but I think it's valid on its own.  I tried cherry-picking it to the gdb-7.11-branch, and it fixes the problem there.
Comment 1 Pedro Alves 2016-05-03 14:03:34 UTC
Fine with me to backport it.
Comment 2 Simon Marchi 2016-05-03 14:20:51 UTC
Thanks, I'll first do some proper testing, and backport it if everything is fine.
Comment 3 Marc Dumais 2016-05-03 14:25:01 UTC
(In reply to Pedro Alves from comment #1)
> Fine with me to backport it.

Pedro, do you think this fix can be included in gdb 7.11.1? CDT is affected.
Comment 4 Pedro Alves 2016-05-03 14:27:21 UTC
Add your test to the testsuite would be great, of course.
Comment 5 Pedro Alves 2016-05-03 14:27:56 UTC
Yup, it's a regression so I think it's appropriate.  Backporting to the 7.11 branch means it'll be included in 7.11.1.
Comment 6 Sourceware Commits 2016-05-16 21:04:02 UTC
The gdb-7.11-branch branch has been updated by Simon Marchi <simark@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=7f8e34d8604098e221f342cf162898fb25499900

commit 7f8e34d8604098e221f342cf162898fb25499900
Author: Pedro Alves <palves@redhat.com>
Date:   Mon May 16 16:51:34 2016 -0400

    Use target_terminal_ours_for_output in MI
    
    The MI code only does output, so leave raw/cooked mode alone, as well
    as the SIGINT handler.  Restore terminal settings after output, while
    at it.  Also, a couple events missed calling target_terminal_ours
    before output, even.
    
    [Backported to the 7.11 branch by Simon Marchi, as it fixes PR 20039.]
    
    gdb/ChangeLog:
    YYYY-MM-DD  Pedro Alves  <palves@redhat.com>
    
    	* mi/mi-interp.c (mi_new_thread): Put
    	target_terminal_ours_for_output in effect while outputting.
    	(mi_thread_exit): Use target_terminal_ours_for_output instead of
    	target_terminal_ours.
    	(mi_record_changed, mi_inferior_added, mi_inferior_appeared)
    	(mi_inferior_exit, mi_inferior_removed, mi_traceframe_changed)
    	(mi_tsv_created, mi_tsv_deleted, mi_tsv_modified)
    	(mi_breakpoint_created, mi_breakpoint_deleted)
    	(mi_breakpoint_modified, mi_solib_loaded, mi_solib_unloaded)
    	(mi_command_param_changed, mi_memory_changed)
    	(report_initial_inferior): Use target_terminal_ours_for_output
    	instead of target_terminal_ours.  Restore terminal settings.
    	* mi/mi-main.c (mi_execute_command): Use
    	target_terminal_ours_for_output instead of target_terminal_ours.
    	Restore terminal settings.
Comment 7 Sourceware Commits 2016-05-18 14:15:30 UTC
The master branch has been updated by Simon Marchi <simark@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=28addb40c77db5a5873172b62b6b7b43e5e05014

commit 28addb40c77db5a5873172b62b6b7b43e5e05014
Author: Simon Marchi <simon.marchi@ericsson.com>
Date:   Tue May 17 17:07:20 2016 -0400

    Fix double prompt output after run control MI commands with mi-async on (PR 20045)
    
    When you use a run control command (-exec-run, -exec-continue,
    -exec-next, ...) with mi-async on, an extra (gdb) prompt is displayed:
    
      -exec-continue
      ^running
      *running,thread-id="all"
      (gdb)
      (gdb)
    
    It doesn't seem to be a big problem for front-ends, since this behavior
    started in gdb 7.9 and we haven't heard anything about that.  However,
    it caused me some trouble while writing a test for PR 20039 [1].
    
    The problem comes from an extra (gdb) prompt that we write when running
    in mi-async off mode to emulate a past buggy behavior.  When executing a
    run control command synchronously, previous gdbs always printed a prompt
    right away, even though they are not ready to accept new MI commands
    until the target stops.  Only at this time should they display a prompt.
    But to keep backwards compatibility apparently, we print it anyway.
    Since commit 198297aaf, the condition that decides whether we should
    print that "bogus" prompt or not has become true, even when running with
    mi-async on.  Since we already print a prompt at the end of the
    asynchronous command execution, it results in two prompts for one
    command.
    
    The proposed fix is to call target_can_async_p instead of
    target_is_async_p, to make the condition:
    
      if (!target_can_async_p () || sync_execution)
        ... show prompt ...
    
    That shows the prompt if we are emulating a synchronous command on top
    of an asynchronous target (sync_execution) or if the target simply can't
    run asynchronously (!target_can_async_p ()).
    
    Note that this code is changed and this bug fixed by Pedro's separate
    console series, but I think it would be nice to have it fixed in the
    mean time.
    
    I ran the gdb.mi directory of the testsuite with mi-async on and off, I
    didn't see any regressions.
    
    gdb/ChangeLog:
    
    	* mi/mi-main.c (mi_on_resume): Call target_can_async_p instead
    	of target_is_async_p.
    
    [1] https://sourceware.org/ml/gdb-patches/2016-05/msg00075.html
Comment 8 Sourceware Commits 2016-05-18 14:15:37 UTC
The master branch has been updated by Simon Marchi <simark@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=9e8f9b05add4517189d7724ff3ed7c16f7b04daf

commit 9e8f9b05add4517189d7724ff3ed7c16f7b04daf
Author: Simon Marchi <simon.marchi@ericsson.com>
Date:   Wed May 18 10:13:12 2016 -0400

    Add mi-threads-interrupt.exp test (PR 20039)
    
    Add a new test for PR 20039.  The test spawns new threads, then tries to
    interrupt, continue, and interrupt again.  This use case was fixed by
    commit 5fe966540d6b748f825774868463003700f0c878 in master, but gdb 7.11
    is affected (so if you try it on the gdb-7.11-branch right now, the test
    will fail).
    
    New in v2, the test now handles mi-async on mode properly.  The failure
    was specific to mi-async off, but I don't think it's bad to test the
    same thing under async on mode.  I added a little hack when running in
    async mode to work around bug 20045.
    
    I also removed one continue/interrupt pair, as a single one was enough to
    trigger the problem.
    
    gdb/testsuite/ChangeLog:
    
    	* gdb.mi/mi-threads-interrupt.c: New file.
    	* gdb.mi/mi-threads-interrupt.exp: New file.
Comment 9 Sourceware Commits 2016-05-18 14:21:52 UTC
The gdb-7.11-branch branch has been updated by Simon Marchi <simark@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=f0a8d0dc70eddbf1e323e8c07f5092ff5e327548

commit f0a8d0dc70eddbf1e323e8c07f5092ff5e327548
Author: Simon Marchi <simon.marchi@ericsson.com>
Date:   Tue May 17 17:07:20 2016 -0400

    Fix double prompt output after run control MI commands with mi-async on (PR 20045)
    
    When you use a run control command (-exec-run, -exec-continue,
    -exec-next, ...) with mi-async on, an extra (gdb) prompt is displayed:
    
      -exec-continue
      ^running
      *running,thread-id="all"
      (gdb)
      (gdb)
    
    It doesn't seem to be a big problem for front-ends, since this behavior
    started in gdb 7.9 and we haven't heard anything about that.  However,
    it caused me some trouble while writing a test for PR 20039 [1].
    
    The problem comes from an extra (gdb) prompt that we write when running
    in mi-async off mode to emulate a past buggy behavior.  When executing a
    run control command synchronously, previous gdbs always printed a prompt
    right away, even though they are not ready to accept new MI commands
    until the target stops.  Only at this time should they display a prompt.
    But to keep backwards compatibility apparently, we print it anyway.
    Since commit 198297aaf, the condition that decides whether we should
    print that "bogus" prompt or not has become true, even when running with
    mi-async on.  Since we already print a prompt at the end of the
    asynchronous command execution, it results in two prompts for one
    command.
    
    The proposed fix is to call target_can_async_p instead of
    target_is_async_p, to make the condition:
    
      if (!target_can_async_p () || sync_execution)
        ... show prompt ...
    
    That shows the prompt if we are emulating a synchronous command on top
    of an asynchronous target (sync_execution) or if the target simply can't
    run asynchronously (!target_can_async_p ()).
    
    Note that this code is changed and this bug fixed by Pedro's separate
    console series, but I think it would be nice to have it fixed in the
    mean time.
    
    I ran the gdb.mi directory of the testsuite with mi-async on and off, I
    didn't see any regressions.
    
    gdb/ChangeLog:
    
    	* mi/mi-main.c (mi_on_resume): Call target_can_async_p instead
    	of target_is_async_p.
    
    [1] https://sourceware.org/ml/gdb-patches/2016-05/msg00075.html
Comment 10 Sourceware Commits 2016-05-18 14:21:58 UTC
The gdb-7.11-branch branch has been updated by Simon Marchi <simark@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=cf2cd51217c0b99f5370708cc3932c12a1f4edad

commit cf2cd51217c0b99f5370708cc3932c12a1f4edad
Author: Simon Marchi <simon.marchi@ericsson.com>
Date:   Wed May 18 10:13:12 2016 -0400

    Add mi-threads-interrupt.exp test (PR 20039)
    
    Add a new test for PR 20039.  The test spawns new threads, then tries to
    interrupt, continue, and interrupt again.  This use case was fixed by
    commit 5fe966540d6b748f825774868463003700f0c878 in master, but gdb 7.11
    is affected (so if you try it on the gdb-7.11-branch right now, the test
    will fail).
    
    New in v2, the test now handles mi-async on mode properly.  The failure
    was specific to mi-async off, but I don't think it's bad to test the
    same thing under async on mode.  I added a little hack when running in
    async mode to work around bug 20045.
    
    I also removed one continue/interrupt pair, as a single one was enough to
    trigger the problem.
    
    gdb/testsuite/ChangeLog:
    
    	* gdb.mi/mi-threads-interrupt.c: New file.
    	* gdb.mi/mi-threads-interrupt.exp: New file.
Comment 11 Simon Marchi 2016-05-18 14:31:29 UTC
Fix pushed.