Package: transmission
Version: 2.94-2
Severity: wishlist
Tags: upstream patch

For a long time Transmission has had a hardcoded limit for the number of open
files. It was set to the value of FD_SETSIZE, which is usually 1024 on most
systems.

The hardcoded value was not enough for some of heavy use cases, and many users
have voiced their displeasure with the current situation. I suggest a patch
that fixes the issue because of which the limitation was added to Transmission
in the first place. Attached patch has been tested against Transmission 2.94
that is currently available from Buster repos.

I have submitted this patch upstream several months ago, but the upstream
development is rather slow and nobody reacted to my pull request yet. I suggest
adding this fix to the Transmission package in Debian because it is (a) simple
enough and (b) would make a lot of users happy. If the maintainer decides
`debian/patches` is not a suitable place to distribute this patch the page at
b.d.o will still be useful as a reference for those interested in fixing the
NOFILE limit in Transmission.

Links:

- Pull request to upstream:
  <https://github.com/transmission/transmission/pull/893>
- Initial issue where the limitation was first introduced:
  <https://trac.transmissionbt.com/ticket/4164>
- Reports from users unhappy with the current situation:
    - <https://trac.transmissionbt.com/ticket/4294>
    - <https://trac.transmissionbt.com/ticket/4311>
    - <https://trac.transmissionbt.com/ticket/4316>
    - <https://trac.transmissionbt.com/ticket/4341>
    - <https://trac.transmissionbt.com/ticket/5056>
    - <https://trac.transmissionbt.com/ticket/5161>
    - <https://trac.transmissionbt.com/ticket/5306>
    - <https://trac.transmissionbt.com/ticket/5898>
    - <https://forum.transmissionbt.com/viewtopic.php?f=1&t=14073>
    - <https://forum.transmissionbt.com/viewtopic.php?f=1&t=17820>
    - <https://forum.transmissionbt.com/viewtopic.php?f=4&t=17826>
    - <https://github.com/cfpp2p/transmission/issues/11>
    - <https://github.com/transmission/transmission/issues/309>
    - <https://github.com/transmission/transmission/issues/633>
    - <https://github.com/transmission/transmission/issues/871>
>From 907f368360ae8514e7d4652b999a00a3cf9c6741 Mon Sep 17 00:00:00 2001
From: Vitaly Potyarkin <sio....@gmail.com>
Date: Fri, 14 Jun 2019 14:49:26 +0300
Subject: [PATCH] Lift 1024 open files limit (switch to curl polling API)

Backported from https://github.com/transmission/transmission/pull/893
---
 CMakeLists.txt            |  2 +-
 configure.ac              |  2 +-
 libtransmission/fdlimit.c | 22 ------------
 libtransmission/web.c     | 74 ++++++++++-----------------------------
 4 files changed, 20 insertions(+), 80 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index da28e31..c2e4ec2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -94,7 +94,7 @@ string(SUBSTRING "${TR_VCS_REVISION}" 0 10 TR_VCS_REVISION)
 
 set_property(GLOBAL PROPERTY USE_FOLDERS ON)
 
-set(CURL_MINIMUM            7.15.4)
+set(CURL_MINIMUM            7.28.0)
 set(EVENT2_MINIMUM          2.0.10)
 set(OPENSSL_MINIMUM         0.9.7)
 set(CYASSL_MINIMUM          3.0)
diff --git a/configure.ac b/configure.ac
index df8cb50..277db00 100644
--- a/configure.ac
+++ b/configure.ac
@@ -39,7 +39,7 @@ AM_CONDITIONAL(HAVE_REVISION_FILE, test -f REVISION)
 ##
 ##
 
-CURL_MINIMUM=7.15.4
+CURL_MINIMUM=7.28.0
 AC_SUBST(CURL_MINIMUM)
 LIBEVENT_MINIMUM=2.0.10
 AC_SUBST(LIBEVENT_MINIMUM)
diff --git a/libtransmission/fdlimit.c b/libtransmission/fdlimit.c
index e181e53..17c28d0 100644
--- a/libtransmission/fdlimit.c
+++ b/libtransmission/fdlimit.c
@@ -12,11 +12,6 @@
 #include <inttypes.h>
 #include <string.h>
 
-#ifndef _WIN32
- #include <sys/time.h> /* getrlimit */
- #include <sys/resource.h> /* getrlimit */
-#endif
-
 #include "transmission.h"
 #include "error.h"
 #include "error-types.h"
@@ -364,23 +359,6 @@ ensureSessionFdInfoExists (tr_session * session)
       i = tr_new0 (struct tr_fdInfo, 1);
       fileset_construct (&i->fileset, FILE_CACHE_SIZE);
       session->fdInfo = i;
-
-#ifndef _WIN32
-      /* set the open-file limit to the largest safe size wrt FD_SETSIZE */
-      struct rlimit limit;
-      if (!getrlimit (RLIMIT_NOFILE, &limit))
-        {
-          const int old_limit = (int) limit.rlim_cur;
-          const int new_limit = MIN (limit.rlim_max, FD_SETSIZE);
-          if (new_limit != old_limit)
-            {
-              limit.rlim_cur = new_limit;
-              setrlimit (RLIMIT_NOFILE, &limit);
-              getrlimit (RLIMIT_NOFILE, &limit);
-              tr_logAddInfo ("Changed open file limit from %d to %d", 
old_limit, (int)limit.rlim_cur);
-            }
-        }
-#endif
     }
 }
 
diff --git a/libtransmission/web.c b/libtransmission/web.c
index c7f0627..65c1d09 100644
--- a/libtransmission/web.c
+++ b/libtransmission/web.c
@@ -10,12 +10,6 @@
 #include <assert.h>
 #include <string.h> /* strlen (), strstr () */
 
-#ifdef _WIN32
-  #include <ws2tcpip.h>
-#else
-  #include <sys/select.h>
-#endif
-
 #include <curl/curl.h>
 
 #include <event2/buffer.h>
@@ -334,41 +328,6 @@ tr_webRunWebseed (tr_torrent        * tor,
                         buffer);
 }
 
-/**
- * Portability wrapper for select ().
- *
- * http://msdn.microsoft.com/en-us/library/ms740141%28VS.85%29.aspx
- * On win32, any two of the parameters, readfds, writefds, or exceptfds,
- * can be given as null. At least one must be non-null, and any non-null
- * descriptor set must contain at least one handle to a socket.
- */
-static void
-tr_select (int nfds,
-           fd_set * r_fd_set, fd_set * w_fd_set, fd_set * c_fd_set,
-           struct timeval  * t)
-{
-#ifdef _WIN32
-  (void) nfds;
-
-  if (!r_fd_set->fd_count && !w_fd_set->fd_count && !c_fd_set->fd_count)
-    {
-      const long int msec = t->tv_sec*1000 + t->tv_usec/1000;
-      tr_wait_msec (msec);
-    }
-  else if (select (0, r_fd_set->fd_count ? r_fd_set : NULL,
-                      w_fd_set->fd_count ? w_fd_set : NULL,
-                      c_fd_set->fd_count ? c_fd_set : NULL, t) < 0)
-    {
-      char errstr[512];
-      const int e = EVUTIL_SOCKET_ERROR ();
-      tr_net_strerror (errstr, sizeof (errstr), e);
-      dbgmsg ("Error: select (%d) %s", e, errstr);
-    }
-#else
-  select (nfds, r_fd_set, w_fd_set, c_fd_set, t);
-#endif
-}
-
 static void
 tr_webThreadFunc (void * vsession)
 {
@@ -378,6 +337,7 @@ tr_webThreadFunc (void * vsession)
   int taskCount = 0;
   struct tr_web_task * task;
   tr_session * session = vsession;
+  uint32_t repeats = 0;

   /* try to enable ssl for https support; but if that fails,
    * try a plain vanilla init */
@@ -410,6 +370,7 @@ tr_webThreadFunc (void * vsession)
   for (;;)
     {
       long msec;
+      int numfds;
       int unused;
       CURLMsg * msg;
       CURLMcode mcode;
@@ -459,24 +420,25 @@ tr_webThreadFunc (void * vsession)
         msec = 100; /* on shutdown, call perform () more frequently */
       if (msec > 0)
         {
-          int usec;
-          int max_fd;
-          struct timeval t;
-          fd_set r_fd_set, w_fd_set, c_fd_set;
-
-          max_fd = 0;
-          FD_ZERO (&r_fd_set);
-          FD_ZERO (&w_fd_set);
-          FD_ZERO (&c_fd_set);
-          curl_multi_fdset (multi, &r_fd_set, &w_fd_set, &c_fd_set, &max_fd);
-
           if (msec > THREADFUNC_MAX_SLEEP_MSEC)
             msec = THREADFUNC_MAX_SLEEP_MSEC;
 
-          usec = msec * 1000;
-          t.tv_sec =  usec / 1000000;
-          t.tv_usec = usec % 1000000;
-          tr_select (max_fd+1, &r_fd_set, &w_fd_set, &c_fd_set, &t);
+          curl_multi_wait(multi, NULL, 0, msec, &numfds);
+          if (!numfds)
+          {
+              repeats++;
+              if (repeats > 1)
+              {
+                  /* curl_multi_wait() returns immediately if there are
+                   * no fds to wait for, so we need an explicit wait here
+                   * to emulate select() behavior */
+                  tr_wait_msec(MIN(msec, THREADFUNC_MAX_SLEEP_MSEC / 2));
+              }
+          }
+          else
+          {
+              repeats = 0;
+          }
         }
 
       /* call curl_multi_perform () */
-- 
2.21.0.windows.1

Reply via email to