|
@@ -138,6 +138,11 @@
|
|
|
#include "strlcat.c"
|
|
|
#endif
|
|
|
|
|
|
+/* When set_max_file_descriptors() is called, update this with the max file
|
|
|
+ * descriptor value so we can use it to check the limit when opening a new
|
|
|
+ * socket. Default value is what Debian sets as the default hard limit. */
|
|
|
+static int max_sockets = 1024;
|
|
|
+
|
|
|
/** As open(path, flags, mode), but return an fd with the close-on-exec mode
|
|
|
* set. */
|
|
|
int
|
|
@@ -1194,6 +1199,18 @@ tor_open_socket_with_extensions(int domain, int type, int protocol,
|
|
|
int cloexec, int nonblock)
|
|
|
{
|
|
|
tor_socket_t s;
|
|
|
+
|
|
|
+ /* We are about to create a new file descriptor so make sure we have
|
|
|
+ * enough of them. */
|
|
|
+ if (get_n_open_sockets() >= max_sockets - 1) {
|
|
|
+#ifdef _WIN32
|
|
|
+ WSASetLastError(WSAEMFILE);
|
|
|
+#else
|
|
|
+ errno = EMFILE;
|
|
|
+#endif
|
|
|
+ return TOR_INVALID_SOCKET;
|
|
|
+ }
|
|
|
+
|
|
|
#if defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK)
|
|
|
int ext_flags = (cloexec ? SOCK_CLOEXEC : 0) |
|
|
|
(nonblock ? SOCK_NONBLOCK : 0);
|
|
@@ -1265,6 +1282,18 @@ tor_accept_socket_with_extensions(tor_socket_t sockfd, struct sockaddr *addr,
|
|
|
socklen_t *len, int cloexec, int nonblock)
|
|
|
{
|
|
|
tor_socket_t s;
|
|
|
+
|
|
|
+ /* We are about to create a new file descriptor so make sure we have
|
|
|
+ * enough of them. */
|
|
|
+ if (get_n_open_sockets() >= max_sockets - 1) {
|
|
|
+#ifdef _WIN32
|
|
|
+ WSASetLastError(WSAEMFILE);
|
|
|
+#else
|
|
|
+ errno = EMFILE;
|
|
|
+#endif
|
|
|
+ return TOR_INVALID_SOCKET;
|
|
|
+ }
|
|
|
+
|
|
|
#if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK)
|
|
|
int ext_flags = (cloexec ? SOCK_CLOEXEC : 0) |
|
|
|
(nonblock ? SOCK_NONBLOCK : 0);
|
|
@@ -1560,6 +1589,12 @@ tor_ersatz_socketpair(int family, int type, int protocol, tor_socket_t fd[2])
|
|
|
int
|
|
|
set_max_file_descriptors(rlim_t limit, int *max_out)
|
|
|
{
|
|
|
+ if (limit < ULIMIT_BUFFER) {
|
|
|
+ log_warn(LD_CONFIG,
|
|
|
+ "ConnLimit must be at least %d. Failing.", ULIMIT_BUFFER);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
/* Define some maximum connections values for systems where we cannot
|
|
|
* automatically determine a limit. Re Cygwin, see
|
|
|
* http://archives.seul.org/or/talk/Aug-2006/msg00210.html
|
|
@@ -1599,7 +1634,7 @@ set_max_file_descriptors(rlim_t limit, int *max_out)
|
|
|
limit = rlim.rlim_max;
|
|
|
if (limit > INT_MAX)
|
|
|
limit = INT_MAX;
|
|
|
- *max_out = (int)limit - ULIMIT_BUFFER;
|
|
|
+ *max_out = max_sockets = (int)limit - ULIMIT_BUFFER;
|
|
|
return 0;
|
|
|
}
|
|
|
if (rlim.rlim_max < limit) {
|
|
@@ -1613,6 +1648,9 @@ set_max_file_descriptors(rlim_t limit, int *max_out)
|
|
|
log_info(LD_NET,"Raising max file descriptors from %lu to %lu.",
|
|
|
(unsigned long)rlim.rlim_cur, (unsigned long)rlim.rlim_max);
|
|
|
}
|
|
|
+ /* Set the current limit value so if the attempt to set the limit to the
|
|
|
+ * max fails at least we'll have a valid value of maximum sockets. */
|
|
|
+ max_sockets = rlim.rlim_cur - ULIMIT_BUFFER;
|
|
|
rlim.rlim_cur = rlim.rlim_max;
|
|
|
|
|
|
if (setrlimit(RLIMIT_NOFILE, &rlim) != 0) {
|
|
@@ -1646,15 +1684,10 @@ set_max_file_descriptors(rlim_t limit, int *max_out)
|
|
|
limit = rlim.rlim_cur;
|
|
|
#endif /* HAVE_GETRLIMIT */
|
|
|
|
|
|
- if (limit < ULIMIT_BUFFER) {
|
|
|
- log_warn(LD_CONFIG,
|
|
|
- "ConnLimit must be at least %d. Failing.", ULIMIT_BUFFER);
|
|
|
- return -1;
|
|
|
- }
|
|
|
if (limit > INT_MAX)
|
|
|
limit = INT_MAX;
|
|
|
tor_assert(max_out);
|
|
|
- *max_out = (int)limit - ULIMIT_BUFFER;
|
|
|
+ *max_out = max_sockets = (int)limit - ULIMIT_BUFFER;
|
|
|
return 0;
|
|
|
}
|
|
|
|