From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 2859 invoked by alias); 30 Dec 2008 21:04:15 -0000 Received: (qmail 2822 invoked by uid 22791); 30 Dec 2008 21:04:12 -0000 X-SWARE-Spam-Status: No, hits=-1.9 required=5.0 tests=AWL,BAYES_00,J_CHICKENPOX_37,SPF_PASS X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (65.74.133.4) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 30 Dec 2008 21:03:36 +0000 Received: (qmail 29432 invoked from network); 30 Dec 2008 21:03:33 -0000 Received: from unknown (HELO bullfrog.localdomain) (sandra@127.0.0.2) by mail.codesourcery.com with ESMTPA; 30 Dec 2008 21:03:33 -0000 Message-ID: <495A8C5D.6070603@codesourcery.com> Date: Tue, 30 Dec 2008 21:04:00 -0000 From: Sandra Loosemore User-Agent: Thunderbird 2.0.0.4 (X11/20070604) MIME-Version: 1.0 To: gdb-patches@sourceware.org CC: Joel Brobecker , drow@false.org Subject: RFA: auto-retry TCP connections, take 2 Content-Type: multipart/mixed; boundary="------------070307030209070804050701" Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2008-12/txt/msg00464.txt.bz2 This is a multi-part message in MIME format. --------------070307030209070804050701 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-length: 366 Here's a new patch, revised per the previous discussion to rename the new commands. Moving them out of "set/show remote" into a new "set/show tcp" prefix cleaned up the implementation logic a bit, so it's probably the right choice. The rest of the patch, with the actual retry/timeout logic, is unchanged from the previous version. OK to check in? -Sandra --------------070307030209070804050701 Content-Type: text/x-log; name="gdb.log" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="gdb.log" Content-length: 698 2008-12-30 Sandra Loosemore 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. --------------070307030209070804050701 Content-Type: text/x-patch; name="gdb-mainline.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="gdb-mainline.patch" Content-length: 9372 Index: gdb/NEWS =================================================================== RCS file: /cvs/src/src/gdb/NEWS,v retrieving revision 1.296 diff -r1.296 NEWS 171a172,179 > 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. > Index: gdb/ser-tcp.c =================================================================== RCS file: /cvs/src/src/gdb/ser-tcp.c,v retrieving revision 1.30 diff -r1.30 ser-tcp.c 24a25,27 > #include "gdbcmd.h" > #include "cli/cli-decode.h" > #include "cli/cli-setshow.h" 51a55 > #include "gdb_select.h" 59,60c63,75 < /* seconds to wait for connect */ < #define TIMEOUT 15 --- > /* For "set tcp" and "show tcp". */ > > 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; > 62c77,149 < #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; > } 78a166 > int polls = 0; 110a199,205 > sockaddr.sin_family = PF_INET; > sockaddr.sin_port = htons (port); > memcpy (&sockaddr.sin_addr.s_addr, hostent->h_addr, > sizeof (struct in_addr)); > > retry: > 119,123d213 < sockaddr.sin_family = PF_INET; < sockaddr.sin_port = htons (port); < memcpy (&sockaddr.sin_addr.s_addr, hostent->h_addr, < sizeof (struct in_addr)); < 131c221,222 < if (n < 0 --- > if (n < 0) > { 133,135c224 < /* Under Windows, calling "connect" with a non-blocking socket < results in WSAEWOULDBLOCK, not WSAEINPROGRESS. */ < && WSAGetLastError() != WSAEWOULDBLOCK --- > int err = WSAGetLastError(); 137c226 < && errno != EINPROGRESS --- > int err = errno; 139,140c228,231 < ) < { --- > > /* Maybe we're waiting for the remote target to become ready to > accept connections. */ > if (tcp_auto_retry 142c233,235 < errno = WSAGetLastError(); --- > && err == WSAECONNREFUSED > #else > && err == ECONNREFUSED 144,146c237,241 < net_close (scb); < return -1; < } --- > && wait_for_connect (NULL, &polls) >= 0) > { > close (scb->fd); > goto retry; > } 148,154c243,256 < if (n) < { < /* looks like we need to wait for the connect */ < struct timeval t; < fd_set rset, wset, eset; < int polls = 0; < FD_ZERO (&rset); --- > if ( > #ifdef USE_WIN32API > /* Under Windows, calling "connect" with a non-blocking socket > results in WSAEWOULDBLOCK, not WSAEINPROGRESS. */ > err != WSAEWOULDBLOCK > #else > err != EINPROGRESS > #endif > ) > { > errno = err; > net_close (scb); > return -1; > } 155a258 > /* looks like we need to wait for the connect */ 158,186c261 < /* 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) < { < if (deprecated_ui_loop_hook (0)) < { < errno = EINTR; < net_close (scb); < return -1; < } < } < < 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++; --- > n = wait_for_connect (scb, &polls); 188,189c263,264 < while (n == 0 && polls <= TIMEOUT * POLL_INTERVAL); < if (n < 0 || polls > TIMEOUT * POLL_INTERVAL) --- > while (n == 0); > if (n < 0) 191,192d265 < if (polls > TIMEOUT * POLL_INTERVAL) < errno = ETIMEDOUT; 209a283,294 > /* 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; > } 266a352,366 > /* 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); > } > > 273d372 < return; 299a399,423 > > 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); Index: gdb/doc/gdb.texinfo =================================================================== RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v retrieving revision 1.541 diff -r1.541 gdb.texinfo 14208a14209,14238 > > @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. --------------070307030209070804050701--