mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-06-14 04:21:24 +00:00
Ignore SO_RCVTIMEO errors in emacsclient
* lib-src/emacsclient.c: Include <stdckdint.h> (timeout): Now signed, and initially -1. All uses changed. (decode_options): Do not worry about ERANGE or ranges, as other code now deal with this; the old code was wrong anyway as it mixed uintmax_t with INTMAX_MAX and INTMAX_MIN. But do check for syntax errors and negative values. (set_socket_timeout): Don’t time out if the timeout is 0 or enormous. Silently ignore errors (Bug#81160). (main): Allow --timeout=0, as per documentation.
This commit is contained in:
parent
8902361cba
commit
6db4271ee8
1 changed files with 22 additions and 20 deletions
|
|
@ -74,6 +74,7 @@ char *w32_getenv (const char *);
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <stdckdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
@ -146,8 +147,9 @@ static char const *socket_name;
|
||||||
/* If non-NULL, the filename of the authentication file. */
|
/* If non-NULL, the filename of the authentication file. */
|
||||||
static char const *server_file;
|
static char const *server_file;
|
||||||
|
|
||||||
/* Seconds to wait before timing out (0 means wait forever). */
|
/* Seconds to wait before timing out. Negative means no --timeout so
|
||||||
static uintmax_t timeout;
|
use DEFAULT_TIMEOUT, 0 means wait forever. */
|
||||||
|
static intmax_t timeout = -1;
|
||||||
|
|
||||||
/* If non-NULL, the tramp prefix emacs must use to find the files. */
|
/* If non-NULL, the tramp prefix emacs must use to find the files. */
|
||||||
static char const *tramp_prefix;
|
static char const *tramp_prefix;
|
||||||
|
|
@ -539,10 +541,8 @@ decode_options (int argc, char **argv)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'w':
|
case 'w':
|
||||||
timeout = strtoumax (optarg, &endptr, 10);
|
timeout = strtoimax (optarg, &endptr, 10);
|
||||||
if (timeout <= 0 ||
|
if (timeout < 0 || endptr == optarg || *endptr)
|
||||||
((timeout == INTMAX_MAX || timeout == INTMAX_MIN)
|
|
||||||
&& errno == ERANGE))
|
|
||||||
{
|
{
|
||||||
fprintf (stderr, "Invalid timeout: \"%s\"\n", optarg);
|
fprintf (stderr, "Invalid timeout: \"%s\"\n", optarg);
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
|
|
@ -1952,28 +1952,30 @@ start_daemon_and_retry_set_socket (void)
|
||||||
return emacs_socket;
|
return emacs_socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set SOCKET's timeout to SECONDS.
|
||||||
|
If SECONDS is zero or out of range, do not set the timeout.
|
||||||
|
Silently ignore errors, as POSIX says it is implementation-defined as
|
||||||
|
to whether SO_RCVTIMEO works. Although we could fall back on
|
||||||
|
non-blocking I/O if setsockopt fails, it's not worth the trouble. */
|
||||||
static void
|
static void
|
||||||
set_socket_timeout (HSOCKET socket, int seconds)
|
set_socket_timeout (HSOCKET socket, intmax_t seconds)
|
||||||
{
|
{
|
||||||
int ret;
|
if (seconds <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
#ifndef WINDOWSNT
|
#ifndef WINDOWSNT
|
||||||
struct timeval timeout;
|
struct timeval timeout;
|
||||||
timeout.tv_sec = seconds;
|
if (ckd_add (&timeout.tv_sec, seconds, 0))
|
||||||
|
return;
|
||||||
timeout.tv_usec = 0;
|
timeout.tv_usec = 0;
|
||||||
ret = setsockopt (socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof timeout);
|
setsockopt (socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof timeout);
|
||||||
#else
|
#else
|
||||||
DWORD timeout;
|
DWORD timeout;
|
||||||
|
|
||||||
if (seconds > INT_MAX / 1000)
|
if (ckd_mul (&timeout, seconds, 1000))
|
||||||
timeout = INT_MAX;
|
return;
|
||||||
else
|
setsockopt (socket, SOL_SOCKET, SO_RCVTIMEO, (char *) &timeout, sizeof timeout);
|
||||||
timeout = seconds * 1000;
|
|
||||||
ret = setsockopt (socket, SOL_SOCKET, SO_RCVTIMEO, (char *) &timeout, sizeof timeout);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ret < 0)
|
|
||||||
sock_err_message ("setsockopt");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
|
@ -2210,7 +2212,7 @@ main (int argc, char **argv)
|
||||||
}
|
}
|
||||||
fflush (stdout);
|
fflush (stdout);
|
||||||
|
|
||||||
set_socket_timeout (emacs_socket, timeout > 0 ? timeout : DEFAULT_TIMEOUT);
|
set_socket_timeout (emacs_socket, timeout < 0 ? DEFAULT_TIMEOUT : timeout);
|
||||||
bool saw_response = false;
|
bool saw_response = false;
|
||||||
ptrdiff_t nrecv = 0;
|
ptrdiff_t nrecv = 0;
|
||||||
|
|
||||||
|
|
@ -2236,7 +2238,7 @@ main (int argc, char **argv)
|
||||||
if (timeout > 0)
|
if (timeout > 0)
|
||||||
{
|
{
|
||||||
/* Don't retry if we were given a --timeout flag. */
|
/* Don't retry if we were given a --timeout flag. */
|
||||||
fprintf (stderr, "\nServer not responding; timed out after %ju seconds",
|
fprintf (stderr, "\nServer not responding; timed out after %jd seconds",
|
||||||
timeout);
|
timeout);
|
||||||
retry = false;
|
retry = false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue