2009-01-06 Sandra Loosemore <sandra@codesourcery.com>

gdb/
	* ser-tcp.c: Adjust includes.
	(tcp_set_cmdlist, tcp_show_cmdlist): Declare.
	(tcp_auto_retry, tcp_retry_limit): Declare.
	(TIMEOUT): Remove, in favor of tcp_retry_limit.
	(POLL_INTERVAL): Increase to 5, in favor of backoff logic.
	(wait_for_connect): New function.
	(net_open): Use it.  Add auto-retry logic.
	(set_tcp_cmd, show_tcp_cmd): New functions.
	(_initialize_ser_tcp): Initialize new "set/show tcp auto-retry"
	and "set/show tcp connect-timeout" commands.
	* NEWS: Document new commands.

	gdb/doc/
	* gdb.texinfo (Remote Configuration): Document new
	"set/show tcp auto-retry" and "set/show tcp connect-timeout"
	commands.
This commit is contained in:
Sandra Loosemore 2009-01-06 17:07:08 +00:00
parent 1069ad51f4
commit 84603566b7
5 changed files with 242 additions and 60 deletions

View File

@ -1,3 +1,17 @@
2009-01-06 Sandra Loosemore <sandra@codesourcery.com>
* ser-tcp.c: Adjust includes.
(tcp_set_cmdlist, tcp_show_cmdlist): Declare.
(tcp_auto_retry, tcp_retry_limit): Declare.
(TIMEOUT): Remove, in favor of tcp_retry_limit.
(POLL_INTERVAL): Increase to 5, in favor of backoff logic.
(wait_for_connect): New function.
(net_open): Use it. Add auto-retry logic.
(set_tcp_cmd, show_tcp_cmd): New functions.
(_initialize_ser_tcp): Initialize new "set/show tcp auto-retry"
and "set/show tcp connect-timeout" commands.
* NEWS: Document new commands.
2009-01-05 Tom Tromey <tromey@redhat.com> 2009-01-05 Tom Tromey <tromey@redhat.com>
* python/python-internal.h (Py_ssize_t): Define as int. * python/python-internal.h (Py_ssize_t): Define as int.

View File

@ -169,6 +169,14 @@ set target-async
with GDB while the target is running. "show target-async" displays the with GDB while the target is running. "show target-async" displays the
current state of asynchronous execution of the target. current state of asynchronous execution of the target.
set tcp auto-retry (on|off)
show tcp auto-retry
set tcp connect-timeout
show tcp connect-timeout
These commands allow GDB to retry failed TCP connections to a remote stub
with a specified timeout period; this is useful if the stub is launched
in parallel with GDB but may not be ready to accept connections immediately.
macro define macro define
macro list macro list
macro undef macro undef

View File

@ -1,3 +1,9 @@
2009-01-06 Sandra Loosemore <sandra@codesourcery.com>
* gdb.texinfo (Remote Configuration): Document new
"set/show tcp auto-retry" and "set/show tcp connect-timeout"
commands.
2008-12-28 Pedro Alves <pedro@codesourcery.com> 2008-12-28 Pedro Alves <pedro@codesourcery.com>
* gdbint.texinfo (gdbarch_cannot_fetch_register): Don't mention * gdbint.texinfo (gdbarch_cannot_fetch_register): Don't mention

View File

@ -14206,6 +14206,36 @@ Select the file used for @code{run} with @code{target
extended-remote}. This should be set to a filename valid on the extended-remote}. This should be set to a filename valid on the
target system. If it is not set, the target will use a default target system. If it is not set, the target will use a default
filename (e.g.@: the last program run). filename (e.g.@: the last program run).
@kindex set tcp
@kindex show tcp
@item set tcp auto-retry on
@cindex auto-retry, for remote TCP target
Enable auto-retry for remote TCP connections. This is useful if the remote
debugging agent is launched in parallel with @value{GDBN}; there is a race
condition because the agent may not become ready to accept the connection
before @value{GDBN} attempts to connect. When auto-retry is
enabled, if the initial attempt to connect fails, @value{GDBN} reattempts
to establish the connection using the timeout specified by
@code{set tcp connect-timeout}.
@item set tcp auto-retry off
Do not auto-retry failed TCP connections.
@item show tcp auto-retry
Show the current auto-retry setting.
@item set tcp connect-timeout @var{seconds}
@cindex connection timeout, for remote TCP target
@cindex timeout, for remote target connection
Set the timeout for establishing a TCP connection to the remote target to
@var{seconds}. The timeout affects both polling to retry failed connections
(enabled by @code{set tcp auto-retry on}) and waiting for connections
that are merely slow to complete, and represents an approximate cumulative
value.
@item show tcp connect-timeout
Show the current connection timeout setting.
@end table @end table
@cindex remote packets, enabling and disabling @cindex remote packets, enabling and disabling

View File

@ -22,6 +22,9 @@
#include "serial.h" #include "serial.h"
#include "ser-base.h" #include "ser-base.h"
#include "ser-tcp.h" #include "ser-tcp.h"
#include "gdbcmd.h"
#include "cli/cli-decode.h"
#include "cli/cli-setshow.h"
#include <sys/types.h> #include <sys/types.h>
@ -49,6 +52,7 @@
#include <signal.h> #include <signal.h>
#include "gdb_string.h" #include "gdb_string.h"
#include "gdb_select.h"
#ifndef HAVE_SOCKLEN_T #ifndef HAVE_SOCKLEN_T
typedef int socklen_t; typedef int socklen_t;
@ -56,10 +60,93 @@ typedef int socklen_t;
void _initialize_ser_tcp (void); void _initialize_ser_tcp (void);
/* seconds to wait for connect */ /* For "set tcp" and "show tcp". */
#define TIMEOUT 15
static struct cmd_list_element *tcp_set_cmdlist;
static struct cmd_list_element *tcp_show_cmdlist;
/* Whether to auto-retry refused connections. */
static int tcp_auto_retry = 1;
/* Timeout period for connections, in seconds. */
static int tcp_retry_limit = 15;
/* how many times per second to poll deprecated_ui_loop_hook */ /* how many times per second to poll deprecated_ui_loop_hook */
#define POLL_INTERVAL 2
#define POLL_INTERVAL 5
/* Helper function to wait a while. If SCB is non-null, wait on its
file descriptor. Otherwise just wait on a timeout, updating *POLLS.
Returns -1 on timeout or interrupt, otherwise the value of select. */
static int
wait_for_connect (struct serial *scb, int *polls)
{
struct timeval t;
int n;
/* While we wait for the connect to complete,
poll the UI so it can update or the user can
interrupt. */
if (deprecated_ui_loop_hook && deprecated_ui_loop_hook (0))
{
errno = EINTR;
return -1;
}
/* Check for timeout. */
if (*polls > tcp_retry_limit * POLL_INTERVAL)
{
errno = ETIMEDOUT;
return -1;
}
/* Back off to polling once per second after the first POLL_INTERVAL
polls. */
if (*polls < POLL_INTERVAL)
{
t.tv_sec = 0;
t.tv_usec = 1000000 / POLL_INTERVAL;
}
else
{
t.tv_sec = 1;
t.tv_usec = 0;
}
if (scb)
{
fd_set rset, wset, eset;
FD_ZERO (&rset);
FD_SET (scb->fd, &rset);
wset = rset;
eset = rset;
/* POSIX systems return connection success or failure by signalling
wset. Windows systems return success in wset and failure in
eset.
We must call select here, rather than gdb_select, because
the serial structure has not yet been initialized - the
MinGW select wrapper will not know that this FD refers
to a socket. */
n = select (scb->fd + 1, &rset, &wset, &eset, &t);
}
else
/* Use gdb_select here, since we have no file descriptors, and on
Windows, plain select doesn't work in that case. */
n = gdb_select (0, NULL, NULL, NULL, &t);
/* If we didn't time out, only count it as one poll. */
if (n > 0 || *polls < POLL_INTERVAL)
(*polls)++;
else
(*polls) += POLL_INTERVAL;
return n;
}
/* Open a tcp socket */ /* Open a tcp socket */
@ -76,6 +163,7 @@ net_open (struct serial *scb, const char *name)
#else #else
int ioarg; int ioarg;
#endif #endif
int polls = 0;
use_udp = 0; use_udp = 0;
if (strncmp (name, "udp:", 4) == 0) if (strncmp (name, "udp:", 4) == 0)
@ -108,6 +196,13 @@ net_open (struct serial *scb, const char *name)
return -1; return -1;
} }
sockaddr.sin_family = PF_INET;
sockaddr.sin_port = htons (port);
memcpy (&sockaddr.sin_addr.s_addr, hostent->h_addr,
sizeof (struct in_addr));
retry:
if (use_udp) if (use_udp)
scb->fd = socket (PF_INET, SOCK_DGRAM, 0); scb->fd = socket (PF_INET, SOCK_DGRAM, 0);
else else
@ -116,11 +211,6 @@ net_open (struct serial *scb, const char *name)
if (scb->fd < 0) if (scb->fd < 0)
return -1; return -1;
sockaddr.sin_family = PF_INET;
sockaddr.sin_port = htons (port);
memcpy (&sockaddr.sin_addr.s_addr, hostent->h_addr,
sizeof (struct in_addr));
/* set socket nonblocking */ /* set socket nonblocking */
ioarg = 1; ioarg = 1;
ioctl (scb->fd, FIONBIO, &ioarg); ioctl (scb->fd, FIONBIO, &ioarg);
@ -128,68 +218,51 @@ net_open (struct serial *scb, const char *name)
/* Use Non-blocking connect. connect() will return 0 if connected already. */ /* Use Non-blocking connect. connect() will return 0 if connected already. */
n = connect (scb->fd, (struct sockaddr *) &sockaddr, sizeof (sockaddr)); n = connect (scb->fd, (struct sockaddr *) &sockaddr, sizeof (sockaddr));
if (n < 0 if (n < 0)
{
#ifdef USE_WIN32API
int err = WSAGetLastError();
#else
int err = errno;
#endif
/* Maybe we're waiting for the remote target to become ready to
accept connections. */
if (tcp_auto_retry
#ifdef USE_WIN32API
&& err == WSAECONNREFUSED
#else
&& err == ECONNREFUSED
#endif
&& wait_for_connect (NULL, &polls) >= 0)
{
close (scb->fd);
goto retry;
}
if (
#ifdef USE_WIN32API #ifdef USE_WIN32API
/* Under Windows, calling "connect" with a non-blocking socket /* Under Windows, calling "connect" with a non-blocking socket
results in WSAEWOULDBLOCK, not WSAEINPROGRESS. */ results in WSAEWOULDBLOCK, not WSAEINPROGRESS. */
&& WSAGetLastError() != WSAEWOULDBLOCK err != WSAEWOULDBLOCK
#else #else
&& errno != EINPROGRESS err != EINPROGRESS
#endif #endif
) )
{ {
#ifdef USE_WIN32API errno = err;
errno = WSAGetLastError();
#endif
net_close (scb); net_close (scb);
return -1; return -1;
} }
if (n)
{
/* looks like we need to wait for the connect */ /* looks like we need to wait for the connect */
struct timeval t;
fd_set rset, wset, eset;
int polls = 0;
FD_ZERO (&rset);
do do
{ {
/* While we wait for the connect to complete, n = wait_for_connect (scb, &polls);
poll the UI so it can update or the user can
interrupt. */
if (deprecated_ui_loop_hook)
{
if (deprecated_ui_loop_hook (0))
{
errno = EINTR;
net_close (scb);
return -1;
} }
} while (n == 0);
if (n < 0)
FD_SET (scb->fd, &rset);
wset = rset;
eset = rset;
t.tv_sec = 0;
t.tv_usec = 1000000 / POLL_INTERVAL;
/* POSIX systems return connection success or failure by signalling
wset. Windows systems return success in wset and failure in
eset.
We must call select here, rather than gdb_select, because
the serial structure has not yet been initialized - the
MinGW select wrapper will not know that this FD refers
to a socket. */
n = select (scb->fd + 1, &rset, &wset, &eset, &t);
polls++;
}
while (n == 0 && polls <= TIMEOUT * POLL_INTERVAL);
if (n < 0 || polls > TIMEOUT * POLL_INTERVAL)
{ {
if (polls > TIMEOUT * POLL_INTERVAL)
errno = ETIMEDOUT;
net_close (scb); net_close (scb);
return -1; return -1;
} }
@ -207,6 +280,18 @@ net_open (struct serial *scb, const char *name)
res = getsockopt (scb->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len); res = getsockopt (scb->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len);
if (res < 0 || err) if (res < 0 || err)
{ {
/* Maybe the target still isn't ready to accept the connection. */
if (tcp_auto_retry
#ifdef USE_WIN32API
&& err == WSAECONNREFUSED
#else
&& err == ECONNREFUSED
#endif
&& wait_for_connect (NULL, &polls) >= 0)
{
close (scb->fd);
goto retry;
}
if (err) if (err)
errno = err; errno = err;
net_close (scb); net_close (scb);
@ -264,13 +349,27 @@ ser_tcp_send_break (struct serial *scb)
return (serial_write (scb, "\377\363", 2)); return (serial_write (scb, "\377\363", 2));
} }
/* Support for "set tcp" and "show tcp" commands. */
static void
set_tcp_cmd (char *args, int from_tty)
{
help_list (tcp_set_cmdlist, "set tcp ", -1, gdb_stdout);
}
static void
show_tcp_cmd (char *args, int from_tty)
{
help_list (tcp_show_cmdlist, "show tcp ", -1, gdb_stdout);
}
void void
_initialize_ser_tcp (void) _initialize_ser_tcp (void)
{ {
#ifdef USE_WIN32API #ifdef USE_WIN32API
/* Do nothing; the TCP serial operations will be initialized in /* Do nothing; the TCP serial operations will be initialized in
ser-mingw.c. */ ser-mingw.c. */
return;
#else #else
struct serial_ops *ops; struct serial_ops *ops;
ops = XMALLOC (struct serial_ops); ops = XMALLOC (struct serial_ops);
@ -297,4 +396,29 @@ _initialize_ser_tcp (void)
ops->write_prim = net_write_prim; ops->write_prim = net_write_prim;
serial_add_interface (ops); serial_add_interface (ops);
#endif /* USE_WIN32API */ #endif /* USE_WIN32API */
add_prefix_cmd ("tcp", class_maintenance, set_tcp_cmd, _("\
TCP protocol specific variables\n\
Configure variables specific to remote TCP connections"),
&tcp_set_cmdlist, "set tcp ",
0 /* allow-unknown */, &setlist);
add_prefix_cmd ("tcp", class_maintenance, show_tcp_cmd, _("\
TCP protocol specific variables\n\
Configure variables specific to remote TCP connections"),
&tcp_show_cmdlist, "show tcp ",
0 /* allow-unknown */, &showlist);
add_setshow_boolean_cmd ("auto-retry", class_obscure,
&tcp_auto_retry, _("\
Set auto-retry on socket connect"), _("\
Show auto-retry on socket connect"),
NULL, NULL, NULL,
&tcp_set_cmdlist, &tcp_show_cmdlist);
add_setshow_uinteger_cmd ("connect-timeout", class_obscure,
&tcp_retry_limit, _("\
Set timeout limit for socket connection"), _("\
Show timeout limit for socket connection"),
NULL, NULL, NULL,
&tcp_set_cmdlist, &tcp_show_cmdlist);
} }