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:
parent
1069ad51f4
commit
84603566b7
|
@ -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.
|
||||||
|
|
8
gdb/NEWS
8
gdb/NEWS
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
234
gdb/ser-tcp.c
234
gdb/ser-tcp.c
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue