mirror of
https://github.com/rkd77/elinks.git
synced 2024-12-04 14:46:47 -05:00
[interlink] speed up first elinks, and use pipe trigger for fork_on_start
When the first elinks session starts (whether fork_on_start or not), it tries to connect on AF_UNIX socket, to see if an existing master is present. The current code implements a retry loop with linear-increase retry backoff, 50ms *= attempts, with 3 attempts, total delay 300ms, before concluding master is not present. After forking for fork_on_start, we do have to wait for the new master to finish setup, so we can connect to it. This is the case where retry loop might be useful. However in fork_on_start=0 case, there should be no reason to ever wait: if we get ECONNREFUSED or ENOENT, the master simply is not there, we can go on about our business as the master. With fork_on_start=1 however, we will race with the child (that will become the new master), which has to complete its socket/bind/listen sequence. Therefore we typically have to wait another 50ms (first attempt delay), for a total of 350ms delay. In both cases, there does not seem to be a purpose to the initial connection attempt retry. Conclusion after connect() failure should be authoritative: there is no master. We do not race with anyone. If we have done fork_on_start and have to wait, we can instead open a pipe before forking, and wait for the "new" master (its child) to send us a byte over the pipe. Thus, we do not need to poll, but can simply block until we get the trigger, to indicate that AF_UNIX socket setup has completed. This speeds up the first start of elinks by 300ms for fork_on_start=0, and between 300-350ms for fork_on_start=1 (or possibly more, if the machine is loaded and child did not finish AF_UNIX setup in first 50ms).
This commit is contained in:
parent
b482b9e069
commit
3d1f020a3b
@ -321,11 +321,6 @@ setsock_reuse_addr(int fd)
|
|||||||
/* Number of connections in listen backlog. */
|
/* Number of connections in listen backlog. */
|
||||||
#define LISTEN_BACKLOG 100
|
#define LISTEN_BACKLOG 100
|
||||||
|
|
||||||
/* Max. number of connect attempts. */
|
|
||||||
#define MAX_CONNECT_TRIES 3
|
|
||||||
/* Base delay in useconds between connect attempts. */
|
|
||||||
#define CONNECT_TRIES_DELAY 50000
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
report_af_unix_error(const char *function, int error)
|
report_af_unix_error(const char *function, int error)
|
||||||
{
|
{
|
||||||
@ -443,31 +438,24 @@ free_and_error:
|
|||||||
static int
|
static int
|
||||||
connect_to_af_unix(void)
|
connect_to_af_unix(void)
|
||||||
{
|
{
|
||||||
int attempts = 0;
|
|
||||||
int pf = get_address(&s_info_connect, ADDR_IP_CLIENT);
|
int pf = get_address(&s_info_connect, ADDR_IP_CLIENT);
|
||||||
|
|
||||||
while (pf != -1 && attempts++ < MAX_CONNECT_TRIES) {
|
if (pf != -1) {
|
||||||
int saved_errno;
|
|
||||||
|
|
||||||
s_info_connect.fd = socket(pf, SOCK_STREAM, 0);
|
s_info_connect.fd = socket(pf, SOCK_STREAM, 0);
|
||||||
if (s_info_connect.fd == -1) {
|
if (s_info_connect.fd == -1) {
|
||||||
report_af_unix_error("socket()", errno);
|
report_af_unix_error("socket()", errno);
|
||||||
break;
|
} else {
|
||||||
}
|
if (connect(s_info_connect.fd, s_info_connect.addr,
|
||||||
|
s_info_connect.size) >= 0) {
|
||||||
if (connect(s_info_connect.fd, s_info_connect.addr,
|
|
||||||
s_info_connect.size) >= 0)
|
|
||||||
return s_info_connect.fd;
|
return s_info_connect.fd;
|
||||||
|
}
|
||||||
saved_errno = errno;
|
if (errno != ECONNREFUSED && errno != ENOENT) {
|
||||||
close(s_info_connect.fd);
|
report_af_unix_error("connect()", errno);
|
||||||
|
}
|
||||||
if (saved_errno != ECONNREFUSED && saved_errno != ENOENT) {
|
else if (close(s_info_connect.fd) == -1) {
|
||||||
report_af_unix_error("connect()", errno);
|
report_af_unix_error("close(afsock)", errno);
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
elinks_usleep(CONNECT_TRIES_DELAY * attempts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mem_free_set(&s_info_connect.addr, NULL);
|
mem_free_set(&s_info_connect.addr, NULL);
|
||||||
@ -517,6 +505,9 @@ done_interlink(void)
|
|||||||
int
|
int
|
||||||
init_interlink(void)
|
init_interlink(void)
|
||||||
{
|
{
|
||||||
|
int pipefds[2];
|
||||||
|
char trigger;
|
||||||
|
ssize_t n;
|
||||||
int fd = connect_to_af_unix();
|
int fd = connect_to_af_unix();
|
||||||
|
|
||||||
if (fd != -1 || remote_session_flags) return fd;
|
if (fd != -1 || remote_session_flags) return fd;
|
||||||
@ -525,12 +516,33 @@ init_interlink(void)
|
|||||||
|
|
||||||
if (get_opt_bool("ui.sessions.fork_on_start", NULL)) {
|
if (get_opt_bool("ui.sessions.fork_on_start", NULL)) {
|
||||||
|
|
||||||
pid_t pid = fork();
|
pid_t pid;
|
||||||
|
if (pipe(pipefds) == -1) {
|
||||||
|
report_af_unix_error("pipe()", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pid = fork();
|
||||||
|
|
||||||
if (pid == -1) return -1;
|
if (pid == -1) return -1;
|
||||||
|
|
||||||
if (pid > 0) {
|
if (pid > 0) {
|
||||||
|
int error = 0;
|
||||||
master_pid = pid;
|
master_pid = pid;
|
||||||
|
|
||||||
|
/* wait for forked child to complete the bind() */
|
||||||
|
if ((n = read(pipefds[0], &trigger, 1)) <= 0) {
|
||||||
|
if (n == 0) {
|
||||||
|
errno = EPIPE; /* write end closed */
|
||||||
|
}
|
||||||
|
report_af_unix_error("read()", errno);
|
||||||
|
error = 1;
|
||||||
|
}
|
||||||
|
if (close(pipefds[0]) == -1) {
|
||||||
|
report_af_unix_error("close(pipe_r)", errno);
|
||||||
|
error = 1;
|
||||||
|
}
|
||||||
|
if (error) return -1;
|
||||||
|
|
||||||
return connect_to_af_unix();
|
return connect_to_af_unix();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -539,6 +551,17 @@ init_interlink(void)
|
|||||||
close_terminal_pipes();
|
close_terminal_pipes();
|
||||||
}
|
}
|
||||||
bind_to_af_unix();
|
bind_to_af_unix();
|
||||||
|
if (get_opt_bool("ui.sessions.fork_on_start", NULL)) {
|
||||||
|
if ((n = write(pipefds[1], &trigger, 1)) <= 0) {
|
||||||
|
if (n == 0) {
|
||||||
|
errno = EPIPE; /* read end closed */
|
||||||
|
}
|
||||||
|
report_af_unix_error("write()", errno);
|
||||||
|
}
|
||||||
|
if (close(pipefds[1]) == -1) {
|
||||||
|
report_af_unix_error("close(pipe_w)", errno);
|
||||||
|
}
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -546,5 +569,3 @@ init_interlink(void)
|
|||||||
#undef MAX_BIND_TRIES
|
#undef MAX_BIND_TRIES
|
||||||
#undef BIND_TRIES_DELAY
|
#undef BIND_TRIES_DELAY
|
||||||
#undef LISTEN_BACKLOG
|
#undef LISTEN_BACKLOG
|
||||||
#undef MAX_CONNECT_TRIES
|
|
||||||
#undef CONNECT_TRIES_DELAY
|
|
||||||
|
Loading…
Reference in New Issue
Block a user