Bugzilla – Attachment 2818 Details for
Bug 2576
ssh-agent enters busy loop when running out of fds
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
avoid busy-wait on per-process fd exhaustion
bz2576.diff (text/plain), 4.19 KB, created by
Damien Miller
on 2016-05-31 11:45:17 AEST
(
hide
)
Description:
avoid busy-wait on per-process fd exhaustion
Filename:
MIME Type:
Creator:
Damien Miller
Created:
2016-05-31 11:45:17 AEST
Size:
4.19 KB
patch
obsolete
>diff --git a/ssh-agent.c b/ssh-agent.c >index 1dc0cfa..32a7c86 100644 >--- a/ssh-agent.c >+++ b/ssh-agent.c >@@ -967,17 +967,19 @@ new_socket(sock_type type, int fd) > > static int > prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp, >- struct timeval **tvpp) >+ u_int *livep, u_int live_max, struct timeval **tvpp) > { > u_int i, sz; > int n = 0; > static struct timeval tv; > time_t deadline; > >- for (i = 0; i < sockets_alloc; i++) { >+ for (i = *livep = 0; i < sockets_alloc; i++) { > switch (sockets[i].type) { >- case AUTH_SOCKET: > case AUTH_CONNECTION: >+ (*livep)++; >+ /* FALLTHROUGH */ >+ case AUTH_SOCKET: > n = MAX(n, sockets[i].fd); > break; > case AUTH_UNUSED: >@@ -988,6 +990,9 @@ prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp, > } > } > >+ if (*livep >= live_max) >+ debug("%s: over fd limit %u >= %u", __func__, *livep, live_max); >+ > sz = howmany(n+1, NFDBITS) * sizeof(fd_mask); > if (*fdrp == NULL || sz > *nallocp) { > free(*fdrp); >@@ -1005,6 +1010,13 @@ prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp, > for (i = 0; i < sockets_alloc; i++) { > switch (sockets[i].type) { > case AUTH_SOCKET: >+ /* >+ * If we are over our FD limit then ignore >+ * new connections until some close. >+ */ >+ if (*livep >= live_max) >+ break; >+ /* FALLTHROUGH */ > case AUTH_CONNECTION: > FD_SET(sockets[i].fd, *fdrp); > if (sshbuf_len(sockets[i].output) > 0) >@@ -1029,7 +1041,7 @@ prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp, > } > > static void >-after_select(fd_set *readset, fd_set *writeset) >+after_select(fd_set *readset, fd_set *writeset, u_int *livep, u_int live_max) > { > struct sockaddr_un sunaddr; > socklen_t slen; >@@ -1046,6 +1058,10 @@ after_select(fd_set *readset, fd_set *writeset) > case AUTH_SOCKET: > if (FD_ISSET(sockets[i].fd, readset)) { > slen = sizeof(sunaddr); >+ if (*livep >= live_max) { >+ debug("over FD limit; skipping accept"); >+ break; >+ } > sock = accept(sockets[i].fd, > (struct sockaddr *)&sunaddr, &slen); > if (sock < 0) { >@@ -1053,6 +1069,7 @@ after_select(fd_set *readset, fd_set *writeset) > strerror(errno)); > break; > } >+ (*livep)++; > if (getpeereid(sock, &euid, &egid) < 0) { > error("getpeereid %d failed: %s", > sock, strerror(errno)); >@@ -1080,6 +1097,7 @@ after_select(fd_set *readset, fd_set *writeset) > continue; > if (len <= 0) { > close_socket(&sockets[i]); >+ (*livep)--; > break; > } > if ((r = sshbuf_consume(sockets[i].output, >@@ -1094,6 +1112,7 @@ after_select(fd_set *readset, fd_set *writeset) > continue; > if (len <= 0) { > close_socket(&sockets[i]); >+ (*livep)--; > break; > } > if ((r = sshbuf_put(sockets[i].input, >@@ -1179,6 +1198,7 @@ main(int ac, char **av) > struct timeval *tvp = NULL; > size_t len; > mode_t prev_mask; >+ u_int live = 0, live_max; > > ssh_malloc_init(); /* must be called before any mallocs */ > /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ >@@ -1275,6 +1295,17 @@ main(int ac, char **av) > } > parent_pid = getpid(); > >+ if (getrlimit(RLIMIT_NOFILE, &rlim) == -1) >+ fatal("%s: getrlimit: %s", __progname, strerror(errno)); >+ /* >+ * Minimum file descriptors: >+ * stdio (3) + listener (1) + syslog (1 maybe) + connection (1). >+ */ >+ if (rlim.rlim_cur < (3+1+1+1)) >+ fatal("%s: file descriptior rlimit %ld too low", >+ __progname, (long)rlim.rlim_cur); >+ live_max = rlim.rlim_cur - (3+1+1); >+ > if (agentsocket == NULL) { > /* Create private directory for agent socket */ > mktemp_proto(socket_dir, sizeof(socket_dir)); >@@ -1390,7 +1421,8 @@ skip: > fatal("%s: pledge: %s", __progname, strerror(errno)); > > while (1) { >- prepare_select(&readsetp, &writesetp, &max_fd, &nalloc, &tvp); >+ prepare_select(&readsetp, &writesetp, &max_fd, >+ &nalloc, &live, live_max, &tvp); > result = select(max_fd + 1, readsetp, writesetp, NULL, tvp); > saved_errno = errno; > if (parent_alive_interval != 0) >@@ -1401,7 +1433,7 @@ skip: > continue; > fatal("select: %s", strerror(saved_errno)); > } else if (result > 0) >- after_select(readsetp, writesetp); >+ after_select(readsetp, writesetp, &live, live_max); > } > /* NOTREACHED */ > }
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 2576
:
2818
|
3142