From 8732a244335488e672cf6dcdddf23d6b7454ce8d Mon Sep 17 00:00:00 2001 From: Nils Maier Date: Tue, 15 Jul 2014 08:16:13 +0200 Subject: [PATCH] Try to set sane limits for RLIMIT_NO_FILE E.g. on OSX the default is 256, which isn't exactly compatible with torrent downloads. Closes GH-257 --- configure.ac | 1 + doc/manual-src/en/aria2c.rst | 14 +++++++++++++ src/Context.cc | 38 ++++++++++++++++++++++++++++++++++++ src/OptionHandlerFactory.cc | 19 ++++++++++++++++++ src/prefs.cc | 2 ++ src/prefs.h | 2 ++ src/usage_text.h | 9 +++++++++ 7 files changed, 85 insertions(+) diff --git a/configure.ac b/configure.ac index 22181e45ad..8661376aca 100644 --- a/configure.ac +++ b/configure.ac @@ -646,6 +646,7 @@ AC_CHECK_HEADERS([argz.h \ strings.h \ sys/ioctl.h \ sys/param.h \ + sys/resource.h \ sys/signal.h \ sys/socket.h \ sys/time.h \ diff --git a/doc/manual-src/en/aria2c.rst b/doc/manual-src/en/aria2c.rst index e0ad416e18..6d07e951c2 100644 --- a/doc/manual-src/en/aria2c.rst +++ b/doc/manual-src/en/aria2c.rst @@ -1186,6 +1186,20 @@ Advanced Options you take commonly used values from RFC, network vendors' documentation, Wikipedia or any other source, use them as they are. +.. option:: --rlimit-nofile=NUM + + Set the soft limit of open file descriptors. + This open will only have effect when: + + a) The system supports it (posix) + b) The limit does not exceed the hard limit. + c) The specified limit is larger than the current soft limit. + + This is equivalent to setting nofile via ulimit, + except that it will never decrease the limit. + + This option is only available on systems supporting the rlimit API. + .. option:: --enable-color[=true|false] Enable color output for a terminal. diff --git a/src/Context.cc b/src/Context.cc index 8de8b577c3..7e0b0b2b95 100644 --- a/src/Context.cc +++ b/src/Context.cc @@ -37,6 +37,11 @@ #include #include +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif // HAVE_SYS_RESOURCE_H + + #include #include #include @@ -180,6 +185,39 @@ Context::Context(bool standalone, A2_LOG_INFO(usedLibs()); A2_LOG_INFO(MSG_LOGGING_STARTED); +#if defined(HAVE_SYS_RESOURCE_H) && defined(RLIMIT_NOFILE) + rlimit r = { 0, 0 }; + if (getrlimit(RLIMIT_NOFILE, &r) >= 0 && r.rlim_cur != RLIM_INFINITY) { + // Thanks portability, for making it easy :p + auto rlim_new = r.rlim_cur; // So we get the right type for free. + if (r.rlim_cur != RLIM_INFINITY) { + rlim_new = op->getAsInt(PREF_RLIMIT_NOFILE); + rlim_new = std::max(r.rlim_cur, rlim_new); + if (r.rlim_max != RLIM_INFINITY) { + rlim_new = std::min(r.rlim_max, rlim_new); + } + } + if (rlim_new != r.rlim_cur) { + if (setrlimit(RLIMIT_NOFILE, &r) != 0) { + int errNum = errno; + A2_LOG_WARN(fmt("Failed to set rlimit NO_FILE from %" PRIu64 " to " + "%" PRIu64 ": %s", + (uint64_t)r.rlim_cur, (uint64_t)rlim_new, + util::safeStrerror(errNum).c_str())); + } + else { + A2_LOG_DEBUG(fmt("Set rlimit NO_FILE from %" PRIu64 " to %" PRIu64, + (uint64_t)r.rlim_cur, (uint64_t)rlim_new)); + } + } + else { + rlim_new = op->getAsInt(PREF_RLIMIT_NOFILE); + A2_LOG_DEBUG(fmt("Not setting rlimit NO_FILE: %" PRIu64 " >= %" PRIu64, + (uint64_t)r.rlim_cur, (uint64_t)rlim_new)); + } + } +#endif // defined(HAVE_SYS_RESOURCE_H) && defined(RLIMIT_NOFILE) + if(op->getAsBool(PREF_DISABLE_IPV6)) { SocketCore::setProtocolFamily(AF_INET); // Get rid of AI_ADDRCONFIG. It causes name resolution error diff --git a/src/OptionHandlerFactory.cc b/src/OptionHandlerFactory.cc index 409f2eabf3..f89a1c440d 100644 --- a/src/OptionHandlerFactory.cc +++ b/src/OptionHandlerFactory.cc @@ -755,6 +755,25 @@ std::vector OptionHandlerFactory::createOptionHandlers() op->addTag(TAG_ADVANCED); handlers.push_back(op); } +#ifdef HAVE_SYS_RESOURCE_H + { + OptionHandler* op(new NumberOptionHandler + (PREF_RLIMIT_NOFILE, + TEXT_RLIMIT_NOFILE, + // Somewhat sane default that most *nix use. + // Some other *nix, like OSX, have insane defaults like + // 256, hence better *not* get the default value from + // getrlimit(). + "1024", + // 1 should not be a problem in practise, since the code + // will only adjust if the specified value > the current + // soft limit. + // And sane systems have a default soft limit > 1. + 1)); + op->addTag(TAG_ADVANCED); + handlers.push_back(op); + } +#endif // HAVE_SYS_RESOURCE_H { OptionHandler* op(new BooleanOptionHandler (PREF_SELECT_LEAST_USED_HOST, diff --git a/src/prefs.cc b/src/prefs.cc index 8367f38d4d..4ceea78aef 100644 --- a/src/prefs.cc +++ b/src/prefs.cc @@ -365,6 +365,8 @@ PrefPtr PREF_RPC_SECRET = makePref("rpc-secret"); PrefPtr PREF_DSCP = makePref("dscp"); // values: true | false PrefPtr PREF_PAUSE_METADATA = makePref("pause-metadata"); +// values: 1*digit +PrefPtr PREF_RLIMIT_NOFILE = makePref("rlimit-nofile"); /** * FTP related preferences diff --git a/src/prefs.h b/src/prefs.h index dfdb949437..071e165158 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -302,6 +302,8 @@ extern PrefPtr PREF_RPC_SECRET; extern PrefPtr PREF_DSCP; // values: true | false extern PrefPtr PREF_PAUSE_METADATA; +// values: 1*digit +extern PrefPtr PREF_RLIMIT_NOFILE; /** * FTP related preferences diff --git a/src/usage_text.h b/src/usage_text.h index 8bb25dff86..fc28f75812 100644 --- a/src/usage_text.h +++ b/src/usage_text.h @@ -980,6 +980,15 @@ " commonly used values from RFC, network vendors'\n" \ " documentation, Wikipedia or any other source,\n" \ " use them as they are.") +#define TEXT_RLIMIT_NOFILE \ + _(" --rlimit-nofile=NUM Set the soft limit of open file descriptors.\n" \ + " This open will only have effect when:\n" \ + " a) The system supports it (posix)\n" \ + " b) The limit does not exceed the hard limit.\n" \ + " c) The specified limit is larger than the\n" \ + " current soft limit.\n" \ + " This is equivalent to setting nofile via ulimit,\n" \ + " except that it will never decrease the limit.") #define TEXT_PAUSE_METADATA \ _(" --pause-metadata[=true|false]\n" \ " Pause downloads created as a result of metadata\n" \