Bug 18804 - Remote file transfers are not interruptible
Summary: Remote file transfers are not interruptible
Status: RESOLVED FIXED
Alias: None
Product: gdb
Classification: Unclassified
Component: gdb (show other bugs)
Version: HEAD
: P2 normal
Target Milestone: 7.10
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-08-11 10:48 UTC by Gary Benson
Modified: 2015-08-25 15:31 UTC (History)
1 user (show)

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


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Gary Benson 2015-08-11 10:48:39 UTC
Remote file transfers are not interruptible.  If a user with a slow link causes GDB to transfer a large file they have no choice but to wait it out.  This is more of a problem than before now that GDB attempts to locate and read binaries from remote targets without the user having to explicitly request it.

First reported in https://sourceware.org/ml/gdb/2015-07/msg00038.html
Comment 1 Sourceware Commits 2015-08-25 15:29:59 UTC
The gdb-7.10-branch branch has been updated by Pedro Alves <palves@sourceware.org>:

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

commit 026ca0231ae6dcc107ec496ed677bd1b00474a2f
Author: Pedro Alves <palves@redhat.com>
Date:   Tue Aug 25 16:19:56 2015 +0100

    remote: allow aborting long operations (e.g., file transfers)
    
    Currently, when remote debugging, if you type Ctrl-C just while the
    target stopped for an internal event, and GDB is busy doing something
    that takes a while (e.g., fetching chunks of a shared library off of
    the target, with vFile, to process ELF headers and debug info), the
    Ctrl-C is lost.
    
    The patch hooks up the QUIT macro to a new target method that lets the
    target react to the double-Ctrl-C before the event loop is reached,
    which allows reacting to a double-Ctrl-C even when GDB is busy doing
    some long operation and not waiting for a stop reply.  That end result
    is:
    
     (gdb) c
     Continuing.
     ^C
     ^C
     Interrupted while waiting for the program.
     Give up waiting? (y or n) y
     Quit
     (gdb) info threads
       Id   Target Id         Frame
     * 1    Thread 11673      0x00007ffff7deb240 in _dl_debug_state () from target:/lib64/ld-linux-x86-64.so.2
     (gdb)
    
    If, however, GDB is waiting for a stop reply (because the target has
    been resumed, with e.g., vCont;c), but the target isn't responding, we
    now get:
    
     (gdb) c
     Continuing.
     ^C
     ^C
     The target is not responding to interrupt requests.
     Stop debugging it? (y or n) y
     Disconnected from target.
     (gdb) info threads
     No threads.
    
    This offers to disconnect, because when we're waiting for a stop
    reply, there's nothing else we can send the target other than an
    interrupt request.  And if that doesn't work, there's nothing else we
    can do.
    
    The Ctrl-C is presently lost because until we get to a user-visible
    stop, the SIGINT handler that is installed is the one that forwards
    the interrupt to the remote side, with the \003 "packet" [1].  But,
    gdbserver ignores an interrupt request if the program is stopped.
    Still, even if it didn't, the server can only report back a
    stop-because-of-SIGINT when the program is next resumed.  And it may
    take a while to actually re-resume the target.
    
    [1] - In the old sync days, the remote target would react to a
    double-Ctrl-C by asking users whether they wanted to give up waiting
    and disconnect.  The code is still there, but it it isn't reacheable
    on most hosts, which support serial connections in async mode
    (probably only DJGPP doesn't).  Even then, in sync mode, remote.c's
    SIGINT handler is only installed while the target is resumed, and is
    removed as soon as the target sends back a stop reply.  That means
    that a Ctrl-C just while GDB is processing an internal event can end
    up with an odd "Quit" at the prompt instead of "Program stopped by
    SIGINT".  In contrast, in async mode, remote.c's SIGINT handler is set
    up as long as target_terminal_inferior or
    target_terminal_ours_for_output are in effect (IOW, until we get a
    user-visible stop and call target_terminal_ours), so the user
    shouldn't get back a spurious Quit.  However, it's still desirable to
    be able to interrupt a long-running GDB operation, if GDB takes a
    while to re-resume the target or get back to the event loop.
    
    Tested on x86_64 Fedora 20.
    
    gdb/ChangeLog:
    2015-08-24  Pedro Alves  <palves@redhat.com>
    
    	PR gdb/18804
    	* defs.h (maybe_quit): Declare.
    	(QUIT): Now calls maybe_quit.
    	* event-loop.c (clear_async_signal_handler)
    	(async_signal_handler_is_marked): New functions.
    	* event-loop.h (async_signal_handler_is_marked)
    	(clear_async_signal_handler): New declarations.
    	* remote.c (remote_check_pending_interrupt): New function.
    	(interrupt_query): Use make_cleanup_restore_target_terminal.  No
    	longer check whether the target is async.  If waiting for a stop
    	reply, and a Ctrl-C as been sent to the target, offer to
    	disconnect, and throw TARGET_CLOSE_ERROR instead of a quit.
    	Otherwise do not disconnect and throw a quit.
    	(_initialize_remote): Install remote_check_pending_interrupt as
    	to_check_pending_interrupt.
    	* target.c (target_check_pending_interrupt): New function.
    	* target.h (struct target_ops) <to_check_pending_interrupt>: New
    	field.
    	(target_check_pending_interrupt): New declaration.
    	* utils.c (maybe_quit): New function.
    	* target-delegates.c: Regenerate.
Comment 2 Pedro Alves 2015-08-25 15:31:08 UTC
Fixed, master and 7.10.