فهرست منبع

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
Nils Maier 11 سال پیش
والد
کامیت
8732a24433
7فایلهای تغییر یافته به همراه85 افزوده شده و 0 حذف شده
  1. 1 0
      configure.ac
  2. 14 0
      doc/manual-src/en/aria2c.rst
  3. 38 0
      src/Context.cc
  4. 19 0
      src/OptionHandlerFactory.cc
  5. 2 0
      src/prefs.cc
  6. 2 0
      src/prefs.h
  7. 9 0
      src/usage_text.h

+ 1 - 0
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 \

+ 14 - 0
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.

+ 38 - 0
src/Context.cc

@@ -37,6 +37,11 @@
 #include <unistd.h>
 #include <getopt.h>
 
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif // HAVE_SYS_RESOURCE_H
+
+
 #include <numeric>
 #include <vector>
 #include <iostream>
@@ -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

+ 19 - 0
src/OptionHandlerFactory.cc

@@ -755,6 +755,25 @@ std::vector<OptionHandler*> 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,

+ 2 - 0
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

+ 2 - 0
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

+ 9 - 0
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" \