diff --git a/changes/issue40613 b/changes/issue40613 new file mode 100644 index 0000000000..76434beba2 --- /dev/null +++ b/changes/issue40613 @@ -0,0 +1,3 @@ + o Code simplifications and refactoring: + - Rely on actual error returned by the kernel when choosing what resource + exhaustion to log. Fixes issue 40613; Fix on tor-0.4.6.1-alpha. diff --git a/src/core/mainloop/connection.c b/src/core/mainloop/connection.c index b0b297ac57..f2fc5ea3fb 100644 --- a/src/core/mainloop/connection.c +++ b/src/core/mainloop/connection.c @@ -1256,34 +1256,10 @@ create_unix_sockaddr(const char *listenaddress, char **readable_address, } #endif /* defined(HAVE_SYS_UN_H) || defined(RUNNING_DOXYGEN) */ -/** - * A socket failed from resource exhaustion. - * - * Among other actions, warn that an accept or a connect has failed because - * we're running out of TCP sockets we can use on current system. Rate-limit - * these warnings so that we don't spam the log. */ +/* Log a rate-limited warning about resource exhaustion */ static void -socket_failed_from_resource_exhaustion(void) +warn_about_resource_exhaution(void) { - /* When we get to this point we know that a socket could not be - * established. However the kernel does not let us know whether the reason is - * because we ran out of TCP source ports, or because we exhausted all the - * FDs on this system, or for any other reason. - * - * For this reason, we are going to use the following heuristic: If our - * system supports a lot of sockets, we will assume that it's a problem of - * TCP port exhaustion. Otherwise, if our system does not support many - * sockets, we will assume that this is because of file descriptor - * exhaustion. - */ - if (get_max_sockets() > 65535) { - /* TCP port exhaustion */ - rep_hist_note_tcp_exhaustion(); - } else { - /* File descriptor exhaustion */ - rep_hist_note_overload(OVERLOAD_FD_EXHAUSTED); - } - #define WARN_TOO_MANY_CONNS_INTERVAL (6*60*60) static ratelim_t last_warned = RATELIM_INIT(WARN_TOO_MANY_CONNS_INTERVAL); char *m; @@ -1297,6 +1273,17 @@ socket_failed_from_resource_exhaustion(void) } } +/** + * A socket failed from file descriptor exhaustion. + * + * Note down file descriptor exhaustion and log a warning. */ +static inline void +socket_failed_from_fd_exhaustion(void) +{ + rep_hist_note_overload(OVERLOAD_FD_EXHAUSTED); + warn_about_resource_exhaution(); +} + #ifdef HAVE_SYS_UN_H #define UNIX_SOCKET_PURPOSE_CONTROL_SOCKET 0 @@ -1512,7 +1499,7 @@ connection_listener_new(const struct sockaddr *listensockaddr, if (!SOCKET_OK(s)) { int e = tor_socket_errno(s); if (ERRNO_IS_RESOURCE_LIMIT(e)) { - socket_failed_from_resource_exhaustion(); + socket_failed_from_fd_exhaustion(); /* * We'll call the OOS handler at the error exit, so set the * exhaustion flag for it. @@ -1638,7 +1625,7 @@ connection_listener_new(const struct sockaddr *listensockaddr, if (! SOCKET_OK(s)) { int e = tor_socket_errno(s); if (ERRNO_IS_RESOURCE_LIMIT(e)) { - socket_failed_from_resource_exhaustion(); + socket_failed_from_fd_exhaustion(); /* * We'll call the OOS handler at the error exit, so set the * exhaustion flag for it. @@ -1951,7 +1938,7 @@ connection_handle_listener_read(connection_t *conn, int new_type) connection_check_oos(get_n_open_sockets(), 0); return 0; } else if (ERRNO_IS_RESOURCE_LIMIT(e)) { - socket_failed_from_resource_exhaustion(); + socket_failed_from_fd_exhaustion(); /* Exhaustion; tell the OOS handler */ connection_check_oos(get_n_open_sockets(), 1); return 0; @@ -2220,7 +2207,7 @@ connection_connect_sockaddr,(connection_t *conn, */ *socket_error = tor_socket_errno(s); if (ERRNO_IS_RESOURCE_LIMIT(*socket_error)) { - socket_failed_from_resource_exhaustion(); + socket_failed_from_fd_exhaustion(); connection_check_oos(get_n_open_sockets(), 1); } else { log_warn(LD_NET,"Error creating network socket: %s",