Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package rtorrent for openSUSE:Factory 
checked in at 2026-08-09 21:34:35
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/rtorrent (Old)
 and      /work/SRC/openSUSE:Factory/.rtorrent.new.16738 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "rtorrent"

Sun Aug  9 21:34:35 2026 rev:38 rq:1370095 version:0.16.20

Changes:
--------
--- /work/SRC/openSUSE:Factory/rtorrent/rtorrent.changes        2026-08-04 
21:39:49.459516628 +0200
+++ /work/SRC/openSUSE:Factory/.rtorrent.new.16738/rtorrent.changes     
2026-08-09 21:36:54.241438720 +0200
@@ -1,0 +2,6 @@
+Thu Aug  6 16:07:29 UTC 2026 - Jan Engelhardt <[email protected]>
+
+- Update to release 0.16.20
+  * Fix deprecated command redirects (rtorrent -D)
+
+-------------------------------------------------------------------

Old:
----
  rtorrent-0.16.19.tar.gz

New:
----
  rtorrent-0.16.20.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ rtorrent.spec ++++++
--- /var/tmp/diff_new_pack.i9z1W6/_old  2026-08-09 21:36:54.769456699 +0200
+++ /var/tmp/diff_new_pack.i9z1W6/_new  2026-08-09 21:36:54.769456699 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           rtorrent
-Version:        0.16.19
+Version:        0.16.20
 Release:        0
 Summary:        Console-based BitTorrent client
 License:        SUSE-GPL-2.0+-with-openssl-exception

++++++ _scmsync.obsinfo ++++++
--- /var/tmp/diff_new_pack.i9z1W6/_old  2026-08-09 21:36:54.805457925 +0200
+++ /var/tmp/diff_new_pack.i9z1W6/_new  2026-08-09 21:36:54.809458061 +0200
@@ -1,5 +1,5 @@
-mtime: 1785832157
-commit: 5d77aae2e6b4ba66eb4d93fc67bfab15c460ccdbc3af7665fdfd7b4885b79e23
+mtime: 1786035608
+commit: 2951d11e902a9038c32e98496525cc9500bc02337c054c22798b1da70e9756ee
 url: https://src.opensuse.org/jengelh/rtorrent
 revision: master
 

++++++ build.specials.obscpio ++++++

++++++ build.specials.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/.gitignore new/.gitignore
--- old/.gitignore      1970-01-01 01:00:00.000000000 +0100
+++ new/.gitignore      2026-08-06 19:00:08.000000000 +0200
@@ -0,0 +1 @@
+.osc

++++++ rtorrent-0.16.19.tar.gz -> rtorrent-0.16.20.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.19/configure 
new/rtorrent-0.16.20/configure
--- old/rtorrent-0.16.19/configure      2026-08-02 11:21:41.000000000 +0200
+++ new/rtorrent-0.16.20/configure      2026-08-06 10:35:01.000000000 +0200
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.72 for rtorrent 0.16.19.
+# Generated by GNU Autoconf 2.72 for rtorrent 0.16.20.
 #
 # Report bugs to <[email protected]>.
 #
@@ -614,8 +614,8 @@
 # Identity of this package.
 PACKAGE_NAME='rtorrent'
 PACKAGE_TARNAME='rtorrent'
-PACKAGE_VERSION='0.16.19'
-PACKAGE_STRING='rtorrent 0.16.19'
+PACKAGE_VERSION='0.16.20'
+PACKAGE_STRING='rtorrent 0.16.20'
 PACKAGE_BUGREPORT='[email protected]'
 PACKAGE_URL=''
 
@@ -1421,7 +1421,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-'configure' configures rtorrent 0.16.19 to adapt to many kinds of systems.
+'configure' configures rtorrent 0.16.20 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1492,7 +1492,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of rtorrent 0.16.19:";;
+     short | recursive ) echo "Configuration of rtorrent 0.16.20:";;
    esac
   cat <<\_ACEOF
 
@@ -1644,7 +1644,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-rtorrent configure 0.16.19
+rtorrent configure 0.16.20
 generated by GNU Autoconf 2.72
 
 Copyright (C) 2023 Free Software Foundation, Inc.
@@ -2273,7 +2273,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by rtorrent $as_me 0.16.19, which was
+It was created by rtorrent $as_me 0.16.20, which was
 generated by GNU Autoconf 2.72.  Invocation command line was
 
   $ $0$ac_configure_args_raw
@@ -3966,7 +3966,7 @@
 
 # Define the identity of the package.
  PACKAGE='rtorrent'
- VERSION='0.16.19'
+ VERSION='0.16.20'
 
 
 printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h
@@ -18708,7 +18708,7 @@
 fi
 
 
-printf "%s\n" "#define API_VERSION 24" >>confdefs.h
+printf "%s\n" "#define API_VERSION 25" >>confdefs.h
 
 
 
@@ -21491,19 +21491,19 @@
 fi
 
 pkg_failed=no
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libtorrent >= 
0.16.19" >&5
-printf %s "checking for libtorrent >= 0.16.19... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libtorrent >= 
0.16.20" >&5
+printf %s "checking for libtorrent >= 0.16.20... " >&6; }
 
 if test -n "$DEPENDENCIES_CFLAGS"; then
     pkg_cv_DEPENDENCIES_CFLAGS="$DEPENDENCIES_CFLAGS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists 
--print-errors \"libtorrent >= 0.16.19\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "libtorrent >= 0.16.19") 2>&5
+    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists 
--print-errors \"libtorrent >= 0.16.20\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libtorrent >= 0.16.20") 2>&5
   ac_status=$?
   printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_DEPENDENCIES_CFLAGS=`$PKG_CONFIG --cflags "libtorrent >= 0.16.19" 
2>/dev/null`
+  pkg_cv_DEPENDENCIES_CFLAGS=`$PKG_CONFIG --cflags "libtorrent >= 0.16.20" 
2>/dev/null`
                      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -21515,12 +21515,12 @@
     pkg_cv_DEPENDENCIES_LIBS="$DEPENDENCIES_LIBS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists 
--print-errors \"libtorrent >= 0.16.19\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "libtorrent >= 0.16.19") 2>&5
+    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists 
--print-errors \"libtorrent >= 0.16.20\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libtorrent >= 0.16.20") 2>&5
   ac_status=$?
   printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_DEPENDENCIES_LIBS=`$PKG_CONFIG --libs "libtorrent >= 0.16.19" 
2>/dev/null`
+  pkg_cv_DEPENDENCIES_LIBS=`$PKG_CONFIG --libs "libtorrent >= 0.16.20" 
2>/dev/null`
                      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -21541,14 +21541,14 @@
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-                DEPENDENCIES_PKG_ERRORS=`$PKG_CONFIG --short-errors 
--print-errors --cflags --libs "libtorrent >= 0.16.19" 2>&1`
+                DEPENDENCIES_PKG_ERRORS=`$PKG_CONFIG --short-errors 
--print-errors --cflags --libs "libtorrent >= 0.16.20" 2>&1`
         else
-                DEPENDENCIES_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags 
--libs "libtorrent >= 0.16.19" 2>&1`
+                DEPENDENCIES_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags 
--libs "libtorrent >= 0.16.20" 2>&1`
         fi
         # Put the nasty error message in config.log where it belongs
         echo "$DEPENDENCIES_PKG_ERRORS" >&5
 
-        as_fn_error $? "Package requirements (libtorrent >= 0.16.19) were not 
met:
+        as_fn_error $? "Package requirements (libtorrent >= 0.16.20) were not 
met:
 
 $DEPENDENCIES_PKG_ERRORS
 
@@ -23548,7 +23548,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by rtorrent $as_me 0.16.19, which was
+This file was extended by rtorrent $as_me 0.16.20, which was
 generated by GNU Autoconf 2.72.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -23616,7 +23616,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config='$ac_cs_config_escaped'
 ac_cs_version="\\
-rtorrent config.status 0.16.19
+rtorrent config.status 0.16.20
 configured by $0, generated by GNU Autoconf 2.72,
   with options \\"\$ac_cs_config\\"
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.19/configure.ac 
new/rtorrent-0.16.20/configure.ac
--- old/rtorrent-0.16.19/configure.ac   2026-08-02 11:03:01.000000000 +0200
+++ new/rtorrent-0.16.20/configure.ac   2026-08-06 10:14:12.000000000 +0200
@@ -1,6 +1,6 @@
 m4_pattern_allow([PKG_CHECK_EXISTS])
 
-AC_INIT([rtorrent],[0.16.19],[[email protected]])
+AC_INIT([rtorrent],[0.16.20],[[email protected]])
 
 AC_CONFIG_HEADERS([config.h])
 AC_CONFIG_MACRO_DIRS([scripts])
@@ -14,7 +14,7 @@
 
 PKG_PROG_PKG_CONFIG
 
-AC_DEFINE([API_VERSION], [24], [api version])
+AC_DEFINE([API_VERSION], [25], [api version])
 
 RAK_CHECK_CFLAGS
 RAK_CHECK_CXXFLAGS
@@ -47,7 +47,7 @@
 
 PKG_CHECK_MODULES([CPPUNIT], [cppunit],, [no_cppunit="yes"])
 PKG_CHECK_MODULES([ZLIB], [zlib])
-PKG_CHECK_MODULES([DEPENDENCIES], [libtorrent >= 0.16.19])
+PKG_CHECK_MODULES([DEPENDENCIES], [libtorrent >= 0.16.20])
 
 AC_LANG_PUSH(C++)
 TORRENT_WITH_XMLRPC_C
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.19/src/Makefile.am 
new/rtorrent-0.16.20/src/Makefile.am
--- old/rtorrent-0.16.19/src/Makefile.am        2026-08-02 11:03:01.000000000 
+0200
+++ new/rtorrent-0.16.20/src/Makefile.am        2026-08-06 10:14:12.000000000 
+0200
@@ -174,6 +174,8 @@
        utils/list_focus.h \
        utils/lockfile.cc \
        utils/lockfile.h \
+       utils/waitpid_queue.cc \
+       utils/waitpid_queue.h \
        utils/watch_ready_queue.cc \
        utils/watch_ready_queue.h \
        \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.19/src/Makefile.in 
new/rtorrent-0.16.20/src/Makefile.in
--- old/rtorrent-0.16.19/src/Makefile.in        2026-08-02 11:21:42.000000000 
+0200
+++ new/rtorrent-0.16.20/src/Makefile.in        2026-08-06 10:35:03.000000000 
+0200
@@ -196,6 +196,7 @@
        utils/file_status_cache.cc utils/file_status_cache.h \
        utils/functional.h utils/gzip.cc utils/gzip.h \
        utils/list_focus.h utils/lockfile.cc utils/lockfile.h \
+       utils/waitpid_queue.cc utils/waitpid_queue.h \
        utils/watch_ready_queue.cc utils/watch_ready_queue.h \
        command_download.cc command_dynamic.cc command_events.cc \
        command_file.cc command_ip.cc command_helpers.cc \
@@ -256,17 +257,17 @@
        ui/element_transfer_list.$(OBJEXT) ui/root.$(OBJEXT) \
        utils/base64.$(OBJEXT) utils/directory.$(OBJEXT) \
        utils/file_status_cache.$(OBJEXT) utils/gzip.$(OBJEXT) \
-       utils/lockfile.$(OBJEXT) utils/watch_ready_queue.$(OBJEXT) \
-       command_download.$(OBJEXT) command_dynamic.$(OBJEXT) \
-       command_events.$(OBJEXT) command_file.$(OBJEXT) \
-       command_ip.$(OBJEXT) command_helpers.$(OBJEXT) \
-       command_groups.$(OBJEXT) command_local.$(OBJEXT) \
-       command_logging.$(OBJEXT) command_network.$(OBJEXT) \
-       command_peer.$(OBJEXT) command_throttle.$(OBJEXT) \
-       command_tracker.$(OBJEXT) command_scheduler.$(OBJEXT) \
-       command_ui.$(OBJEXT) control.$(OBJEXT) globals.$(OBJEXT) \
-       option_parser.$(OBJEXT) setup.$(OBJEXT) \
-       signal_handler.$(OBJEXT) $(am__objects_1)
+       utils/lockfile.$(OBJEXT) utils/waitpid_queue.$(OBJEXT) \
+       utils/watch_ready_queue.$(OBJEXT) command_download.$(OBJEXT) \
+       command_dynamic.$(OBJEXT) command_events.$(OBJEXT) \
+       command_file.$(OBJEXT) command_ip.$(OBJEXT) \
+       command_helpers.$(OBJEXT) command_groups.$(OBJEXT) \
+       command_local.$(OBJEXT) command_logging.$(OBJEXT) \
+       command_network.$(OBJEXT) command_peer.$(OBJEXT) \
+       command_throttle.$(OBJEXT) command_tracker.$(OBJEXT) \
+       command_scheduler.$(OBJEXT) command_ui.$(OBJEXT) \
+       control.$(OBJEXT) globals.$(OBJEXT) option_parser.$(OBJEXT) \
+       setup.$(OBJEXT) signal_handler.$(OBJEXT) $(am__objects_1)
 libsub_root_a_OBJECTS = $(am_libsub_root_a_OBJECTS)
 am_rtorrent_OBJECTS = main.$(OBJEXT)
 rtorrent_OBJECTS = $(am_rtorrent_OBJECTS)
@@ -357,7 +358,7 @@
        ui/$(DEPDIR)/element_transfer_list.Po ui/$(DEPDIR)/root.Po \
        utils/$(DEPDIR)/base64.Po utils/$(DEPDIR)/directory.Po \
        utils/$(DEPDIR)/file_status_cache.Po utils/$(DEPDIR)/gzip.Po \
-       utils/$(DEPDIR)/lockfile.Po \
+       utils/$(DEPDIR)/lockfile.Po utils/$(DEPDIR)/waitpid_queue.Po \
        utils/$(DEPDIR)/watch_ready_queue.Po
 am__mv = mv -f
 CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
@@ -653,6 +654,7 @@
        utils/file_status_cache.cc utils/file_status_cache.h \
        utils/functional.h utils/gzip.cc utils/gzip.h \
        utils/list_focus.h utils/lockfile.cc utils/lockfile.h \
+       utils/waitpid_queue.cc utils/waitpid_queue.h \
        utils/watch_ready_queue.cc utils/watch_ready_queue.h \
        command_download.cc command_dynamic.cc command_events.cc \
        command_file.cc command_ip.cc command_helpers.cc \
@@ -946,6 +948,8 @@
        utils/$(DEPDIR)/$(am__dirstamp)
 utils/lockfile.$(OBJEXT): utils/$(am__dirstamp) \
        utils/$(DEPDIR)/$(am__dirstamp)
+utils/waitpid_queue.$(OBJEXT): utils/$(am__dirstamp) \
+       utils/$(DEPDIR)/$(am__dirstamp)
 utils/watch_ready_queue.$(OBJEXT): utils/$(am__dirstamp) \
        utils/$(DEPDIR)/$(am__dirstamp)
 display/curses_stub.$(OBJEXT): display/$(am__dirstamp) \
@@ -1074,6 +1078,7 @@
 @AMDEP_TRUE@@am__include@ 
@am__quote@utils/$(DEPDIR)/file_status_cache.Po@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/gzip.Po@am__quote@ # 
am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/lockfile.Po@am__quote@ # 
am--include-marker
+@AMDEP_TRUE@@am__include@ 
@am__quote@utils/$(DEPDIR)/waitpid_queue.Po@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ 
@am__quote@utils/$(DEPDIR)/watch_ready_queue.Po@am__quote@ # am--include-marker
 
 $(am__depfiles_remade):
@@ -1356,6 +1361,7 @@
        -rm -f utils/$(DEPDIR)/file_status_cache.Po
        -rm -f utils/$(DEPDIR)/gzip.Po
        -rm -f utils/$(DEPDIR)/lockfile.Po
+       -rm -f utils/$(DEPDIR)/waitpid_queue.Po
        -rm -f utils/$(DEPDIR)/watch_ready_queue.Po
        -rm -f Makefile
 distclean-am: clean-am distclean-compile distclean-generic \
@@ -1501,6 +1507,7 @@
        -rm -f utils/$(DEPDIR)/file_status_cache.Po
        -rm -f utils/$(DEPDIR)/gzip.Po
        -rm -f utils/$(DEPDIR)/lockfile.Po
+       -rm -f utils/$(DEPDIR)/waitpid_queue.Po
        -rm -f utils/$(DEPDIR)/watch_ready_queue.Po
        -rm -f Makefile
 maintainer-clean-am: distclean-am maintainer-clean-generic
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.19/src/command_local.cc 
new/rtorrent-0.16.20/src/command_local.cc
--- old/rtorrent-0.16.19/src/command_local.cc   2026-08-02 11:03:01.000000000 
+0200
+++ new/rtorrent-0.16.20/src/command_local.cc   2026-08-06 10:14:12.000000000 
+0200
@@ -243,6 +243,8 @@
   CMD_ANY         ("system.sockets.max_size",         [](auto, auto)        { 
return torrent::runtime::socket_manager()->max_size(); });
   CMD_ANY_VALUE_V ("system.sockets.max_size.set",     [](auto, auto& value) { 
return torrent::runtime::socket_manager()->set_max_size_and_adjust(value); });
   CMD_ANY_V       ("system.sockets.adjust_alloc",     [](auto, auto)        { 
torrent::runtime::socket_manager()->adjust_allocation(); });
+  CMD_ANY         ("system.sockets.reserved_alloc",   [](auto, auto)        { 
return torrent::runtime::socket_manager()->reserved_allocation(); });
+  CMD_ANY         ("system.sockets.available_alloc",  [](auto, auto)        { 
return torrent::runtime::socket_manager()->available_allocation(); });
 
   for (uint32_t i = 0; i < torrent::runtime::SocketManager::category_count; 
++i) {
     auto category      = 
static_cast<torrent::runtime::socket_manager_category_t>(i);
@@ -251,8 +253,10 @@
     CMD_ANY        (category_name + ".size",      [category](auto, auto) { 
return torrent::runtime::socket_manager()->category_managed_size(category); });
     CMD_ANY        (category_name + ".max_size",  [category](auto, auto) { 
return torrent::runtime::socket_manager()->category_max_size(category); });
 
-    if (i == 0)
+    if (i == 0) {
+      CMD_ANY      (category_name + ".min_alloc",   [](auto, auto) { return 
torrent::runtime::socket_manager()->generic_min_allocation(); });
       continue;
+    }
 
     CMD_ANY        (category_name + ".min_alloc",     [category](auto, auto) { 
return torrent::runtime::socket_manager()->category_min_allocation(category); 
});
     CMD_ANY        (category_name + ".max_alloc",     [category](auto, auto) { 
return torrent::runtime::socket_manager()->category_max_allocation(category); 
});
@@ -348,6 +352,8 @@
 
   rpc::rpc.mark_safe("system.sockets.size");
   rpc::rpc.mark_safe("system.sockets.max_size");
+  rpc::rpc.mark_safe("system.sockets.reserved_alloc");
+  rpc::rpc.mark_safe("system.sockets.available_alloc");
 
   for (uint32_t i = 0; i < torrent::runtime::SocketManager::category_count; 
++i) {
     auto category_name = "system.sockets." + 
torrent::option_to_str_or_throw(torrent::OPTION_SOCKET_CATEGORY, i);
@@ -355,8 +361,10 @@
     rpc::rpc.mark_safe(category_name + ".size");
     rpc::rpc.mark_safe(category_name + ".max_size");
 
-    if (i == 0)
+    if (i == 0) {
+      rpc::rpc.mark_safe(category_name + ".min_alloc");
       continue;
+    }
 
     rpc::rpc.mark_safe(category_name + ".min_alloc");
     rpc::rpc.mark_safe(category_name + ".max_alloc");
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.19/src/control.h 
new/rtorrent-0.16.20/src/control.h
--- old/rtorrent-0.16.19/src/control.h  2026-08-02 11:03:01.000000000 +0200
+++ new/rtorrent-0.16.20/src/control.h  2026-08-06 10:14:12.000000000 +0200
@@ -6,7 +6,7 @@
 #include <memory>
 #include <sys/types.h>
 #include <torrent/torrent.h>
-#include <torrent/utils/scheduler.h>
+#include <torrent/system/scheduler.h>
 
 namespace ui {
   class Root;
@@ -107,8 +107,8 @@
   mode_t              m_umask;
   std::string         m_workingDirectory;
 
-  torrent::utils::SchedulerEntry m_task_shutdown;
-  torrent::utils::SchedulerEntry m_task_shutdown_clear_requests;
+  torrent::system::SchedulerEntry m_task_shutdown;
+  torrent::system::SchedulerEntry m_task_shutdown_clear_requests;
 
   int                 m_clear_requests_count{};
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.19/src/core/dht_manager.h 
new/rtorrent-0.16.20/src/core/dht_manager.h
--- old/rtorrent-0.16.19/src/core/dht_manager.h 2026-08-02 11:03:01.000000000 
+0200
+++ new/rtorrent-0.16.20/src/core/dht_manager.h 2026-08-06 10:14:12.000000000 
+0200
@@ -2,7 +2,7 @@
 #define RTORRENT_CORE_DHT_MANAGER_H
 
 #include <torrent/object.h>
-#include <torrent/utils/scheduler.h>
+#include <torrent/system/scheduler.h>
 
 namespace core {
 
@@ -42,8 +42,8 @@
   uint64_t            m_dhtPrevBytesUp;
   uint64_t            m_dhtPrevBytesDown;
 
-  torrent::utils::SchedulerEntry m_update_timeout;
-  torrent::utils::SchedulerEntry m_stop_timeout;
+  torrent::system::SchedulerEntry m_update_timeout;
+  torrent::system::SchedulerEntry m_stop_timeout;
 
   bool                m_warned{};
   bool                m_set_by_user{};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.19/src/core/download_factory.h 
new/rtorrent-0.16.20/src/core/download_factory.h
--- old/rtorrent-0.16.19/src/core/download_factory.h    2026-08-02 
11:03:01.000000000 +0200
+++ new/rtorrent-0.16.20/src/core/download_factory.h    2026-08-06 
10:14:12.000000000 +0200
@@ -9,7 +9,7 @@
 #include <iosfwd>
 
 #include <torrent/object.h>
-#include <torrent/utils/scheduler.h>
+#include <torrent/system/scheduler.h>
 
 #include "http_queue.h"
 
@@ -79,9 +79,9 @@
   command_list_type         m_commands;
   torrent::Object::map_type m_variables;
 
-  slot_void                      m_slot_finished;
-  torrent::utils::SchedulerEntry m_task_load;
-  torrent::utils::SchedulerEntry m_task_commit;
+  slot_void                       m_slot_finished;
+  torrent::system::SchedulerEntry m_task_load;
+  torrent::system::SchedulerEntry m_task_commit;
 };
 
 bool is_network_uri(const std::string& uri);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.19/src/core/view.h 
new/rtorrent-0.16.20/src/core/view.h
--- old/rtorrent-0.16.19/src/core/view.h        2026-08-02 11:03:01.000000000 
+0200
+++ new/rtorrent-0.16.20/src/core/view.h        2026-08-06 10:14:12.000000000 
+0200
@@ -18,7 +18,7 @@
 #include <string>
 #include <vector>
 #include <torrent/object.h>
-#include <torrent/utils/scheduler.h>
+#include <torrent/system/scheduler.h>
 
 #include "globals.h"
 
@@ -153,8 +153,8 @@
 
   std::chrono::microseconds m_last_changed{};
 
-  signal_void                    m_signal_changed;
-  torrent::utils::SchedulerEntry m_delay_changed;
+  signal_void                     m_signal_changed;
+  torrent::system::SchedulerEntry m_delay_changed;
 };
 
 } // namespace core
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.19/src/display/manager.h 
new/rtorrent-0.16.20/src/display/manager.h
--- old/rtorrent-0.16.19/src/display/manager.h  2026-08-02 11:03:01.000000000 
+0200
+++ new/rtorrent-0.16.20/src/display/manager.h  2026-08-06 10:14:12.000000000 
+0200
@@ -1,7 +1,7 @@
 #ifndef RTORRENT_DISPLAY_MANAGER_H
 #define RTORRENT_DISPLAY_MANAGER_H
 
-#include <torrent/utils/scheduler.h>
+#include <torrent/system/scheduler.h>
 
 #include "display/frame.h"
 
@@ -31,9 +31,9 @@
   bool                m_force_redraw{false};
   Frame               m_root_frame;
 
-  std::chrono::microseconds         m_time_last_update{};
-  torrent::utils::ExternalScheduler m_scheduler;
-  torrent::utils::SchedulerEntry    m_task_update;
+  std::chrono::microseconds          m_time_last_update{};
+  torrent::system::ExternalScheduler m_scheduler;
+  torrent::system::SchedulerEntry    m_task_update;
 };
 
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.19/src/display/window.h 
new/rtorrent-0.16.20/src/display/window.h
--- old/rtorrent-0.16.19/src/display/window.h   2026-08-02 11:03:01.000000000 
+0200
+++ new/rtorrent-0.16.20/src/display/window.h   2026-08-06 10:14:12.000000000 
+0200
@@ -2,7 +2,7 @@
 #define RTORRENT_WINDOW_BASE_H
 
 #include <functional>
-#include <torrent/utils/scheduler.h>
+#include <torrent/system/scheduler.h>
 #include <torrent/system/thread.h>
 
 #include "canvas.h"
@@ -99,7 +99,7 @@
   extent_type         m_max_width;
   extent_type         m_max_height;
 
-  torrent::utils::SchedulerEntry m_task_update;
+  torrent::system::SchedulerEntry m_task_update;
 };
 
 // Return a range with a distance of no more than __distance and
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.19/src/display/window_http_queue.h 
new/rtorrent-0.16.20/src/display/window_http_queue.h
--- old/rtorrent-0.16.19/src/display/window_http_queue.h        2026-08-02 
11:03:01.000000000 +0200
+++ new/rtorrent-0.16.20/src/display/window_http_queue.h        2026-08-06 
10:14:12.000000000 +0200
@@ -47,7 +47,7 @@
   signal_curl_get::iterator m_conn_insert;
   signal_curl_get::iterator m_conn_erase;
 
-  torrent::utils::SchedulerEntry m_task_deactivate;
+  torrent::system::SchedulerEntry m_task_deactivate;
 };
 
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.19/src/display/window_log.h 
new/rtorrent-0.16.20/src/display/window_log.h
--- old/rtorrent-0.16.19/src/display/window_log.h       2026-08-02 
11:03:01.000000000 +0200
+++ new/rtorrent-0.16.20/src/display/window_log.h       2026-08-06 
10:14:12.000000000 +0200
@@ -1,8 +1,8 @@
 #ifndef RTORRENT_DISPLAY_WINDOW_LOG_H
 #define RTORRENT_DISPLAY_WINDOW_LOG_H
 
+#include <torrent/system/scheduler.h>
 #include <torrent/utils/log_buffer.h>
-#include <torrent/utils/scheduler.h>
 
 #include "window.h"
 
@@ -22,10 +22,12 @@
 private:
   inline iterator     find_older();
 
-  torrent::log_buffer*           m_log;
-  torrent::utils::SchedulerEntry m_task_update;
+  torrent::log_buffer*            m_log;
+  torrent::system::SchedulerEntry m_task_update;
 
-  align_cacheline std::atomic<bool> m_log_updating{};
+  align_cacheline
+
+  std::atomic<bool>   m_log_updating{};
 };
 
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.19/src/main.cc 
new/rtorrent-0.16.20/src/main.cc
--- old/rtorrent-0.16.19/src/main.cc    2026-08-02 11:03:01.000000000 +0200
+++ new/rtorrent-0.16.20/src/main.cc    2026-08-06 10:14:12.000000000 +0200
@@ -392,13 +392,12 @@
 
       CMD_REDIRECT("bind",                  "network.bind_address.set");
       CMD_REDIRECT("ip",                    "network.local_address.set");
-      CMD_REDIRECT("port_range",            "network.port_range.set");
 
       // TODO: Check if dht is on by default.
       CMD_REDIRECT("dht",                   "dht.mode.set");
 
-      CMD_REDIRECT("port_random",           "network.port_random.set");
-      CMD_REDIRECT("proxy_address",         "network.proxy_address.set");
+      CMD_REDIRECT("port_random",           "network.listen.port.random.set");
+      CMD_REDIRECT("proxy_address",         "network.proxy.http.set");
 
       CMD_REDIRECT("key_layout",            "keys.layout.set");
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.19/src/rpc/command_scheduler_item.h 
new/rtorrent-0.16.20/src/rpc/command_scheduler_item.h
--- old/rtorrent-0.16.19/src/rpc/command_scheduler_item.h       2026-08-02 
11:03:01.000000000 +0200
+++ new/rtorrent-0.16.20/src/rpc/command_scheduler_item.h       2026-08-06 
10:14:12.000000000 +0200
@@ -5,7 +5,7 @@
 
 #include <functional>
 #include <torrent/object.h>
-#include <torrent/utils/scheduler.h>
+#include <torrent/system/scheduler.h>
 
 namespace rpc {
 
@@ -43,7 +43,7 @@
   uint32_t                  m_interval{};
   std::chrono::microseconds m_time_scheduled;
 
-  torrent::utils::SchedulerEntry m_task;
+  torrent::system::SchedulerEntry m_task;
 
   // Flags for various things.
 };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.19/src/rpc/exec_file.cc 
new/rtorrent-0.16.20/src/rpc/exec_file.cc
--- old/rtorrent-0.16.19/src/rpc/exec_file.cc   2026-08-02 11:03:01.000000000 
+0200
+++ new/rtorrent-0.16.20/src/rpc/exec_file.cc   2026-08-06 10:14:12.000000000 
+0200
@@ -1,23 +1,22 @@
 #include "config.h"
 
-#include <cassert>
-#include <cerrno>
-#include <cstring>
-#include <fcntl.h>
-#include <spawn.h>
-#include <string>
+#include "rpc/exec_file.h"
+
+// #include <cassert>
+// #include <cerrno>
+// #include <cstring>
+// #include <fcntl.h>
+// #include <spawn.h>
+// #include <string>
 #include <unistd.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <torrent/net/fd.h>
+// #include <sys/types.h>
+#include <sys/uio.h>
+// #include <torrent/net/fd.h>
 #include <torrent/system/thread.h>
+#include <torrent/system/spawn_process.h>
 #include <torrent/system/types.h>
 
-#include "exec_file.h"
-#include "parse.h"
-
-// Standard POSIX environment pointer
-extern char** environ;
+#include "rpc/parse.h"
 
 namespace rpc {
 
@@ -25,159 +24,56 @@
 
 int
 ExecFile::execute(const char* file, char* const* argv, int flags) {
-  assert(!((flags & flag_capture) && (flags & flag_background)));
+  torrent::system::SpawnProcess spawn_process;
 
-  // Write the executed command and its parameters to the log fd.
-  [[maybe_unused]] int result;
+  spawn_process.set_log_fd(m_log_fd);
+  spawn_process.set_background(flags & flag_background);
+  spawn_process.set_capture_output(flags & flag_capture);
 
   if (m_log_fd != -1) {
-    for (char* const* itr = argv; *itr != NULL; itr++) {
-      if (itr == argv)
-        result = write(m_log_fd, "\n---\n", sizeof("\n---\n"));
-      else
-        result = write(m_log_fd, " ", 1);
+    std::vector<struct iovec> iovecs;
+    iovecs.reserve(32);
+    iovecs.push_back({const_cast<char*>("\n---\n"), 5});
+
+    for (auto* itr = argv; *itr != nullptr; itr++) {
+      if (itr != argv)
+        iovecs.push_back({const_cast<char*>(" "), 1});
 
-      result = write(m_log_fd, *itr, std::strlen(*itr));
+      iovecs.push_back({*itr, std::strlen(*itr)});
     }
 
-    result = write(m_log_fd, "\n---\n", sizeof("\n---\n"));
-  }
-
-  posix_spawn_file_actions_t actions{};
-
-  if (posix_spawn_file_actions_init(&actions) != 0)
-    throw torrent::internal_error("ExecFile::execute(...) 
posix_spawn_file_actions_init failed.");
-
-  posix_spawnattr_t attr;
-  posix_spawnattr_init(&attr);
-
-  // Try to avoid leaking open fds to the spawned process. Prefer 
POSIX_SPAWN_CLOEXEC_DEFAULT
-  // (macOS-only) or posix_spawn_file_actions_addclosefrom_np (glibc >= 2.34, 
FreeBSD >= 13.1).
-  //
-  // Other platforms like musl libc, OpenBSD and NetBSD must rely on explicit 
O_CLOEXEC.
-
-  // Handle standard input redirection (/dev/null), 
posix_spawn_file_actions_addopen handles opening
-  // and dup2 natively
-  if (posix_spawn_file_actions_addopen(&actions, 0, "/dev/null", O_RDWR, 0) != 
0) {
-    // Fallback if open fails inside action setup
-    posix_spawn_file_actions_addclose(&actions, 0);
-  }
-
-  int pipe_0 = -1;
-  int pipe_1 = -1;
-
-  // Handle standard output redirection
-  if (flags & flag_capture) {
-    torrent::fd_open_pipe(pipe_0, pipe_1);
-
-    posix_spawn_file_actions_adddup2(&actions, pipe_1, 1);
-
-    // Ensure the write end of the pipe is closed in the child after 
duplicating.
-    posix_spawn_file_actions_addclose(&actions, pipe_0);
-    posix_spawn_file_actions_addclose(&actions, pipe_1);
+    iovecs.push_back({const_cast<char*>("\n---\n"), 5});
 
-  } else if (m_log_fd != -1) {
-    posix_spawn_file_actions_adddup2(&actions, m_log_fd, 1);
-
-  } else {
-    posix_spawn_file_actions_addopen(&actions, 1, "/dev/null", O_RDWR, 0);
-  }
-
-  if (m_log_fd != -1) {
-    posix_spawn_file_actions_adddup2(&actions, m_log_fd, 2);
-  } else {
-    posix_spawn_file_actions_addopen(&actions, 2, "/dev/null", O_RDWR, 0);
-  }
-
-  short spawn_flags = 0;
-
-#if defined(POSIX_SPAWN_CLOEXEC_DEFAULT)
-  spawn_flags |= POSIX_SPAWN_CLOEXEC_DEFAULT;
-#elif defined(HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP)
-  posix_spawn_file_actions_addclosefrom_np(&actions, 3);
-#endif
-
-  if (flags & flag_background) {
-#ifdef POSIX_SPAWN_SETSID
-    spawn_flags |= POSIX_SPAWN_SETSID;
-#else
-    spawn_flags |= POSIX_SPAWN_SETPGROUP;
-    posix_spawnattr_setpgroup(&attr, 0);
-#endif
+    [[maybe_unused]] int result = ::writev(m_log_fd, iovecs.data(), 
iovecs.size());
   }
 
-  posix_spawnattr_setflags(&attr, spawn_flags);
-
-  pid_t child_pid{};
-  int   spawn_status = posix_spawnp(&child_pid, file, &actions, &attr, argv, 
environ);
-
-  posix_spawn_file_actions_destroy(&actions);
-  posix_spawnattr_destroy(&attr);
+  int spawn_status = spawn_process.execute(file, argv);
 
   if (spawn_status != 0) {
-    if (pipe_0 != -1)
-      torrent::fd_close(pipe_0);
-
-    if (pipe_1 != -1)
-      torrent::fd_close(pipe_1);
-
-    throw torrent::input_error("ExecFile::execute() posix_spawn failed: " + 
torrent::system::errno_enum_str(spawn_status));
-  }
-
-  if (flags & flag_capture) {
-    m_capture = std::string();
-    torrent::fd_close(pipe_1);
-
-    char buffer[4096];
-    ssize_t length;
-
-    do {
-      length = read(pipe_0, buffer, sizeof(buffer));
-
-      if (length > 0)
-        m_capture += std::string(buffer, length);
-
-    } while (length > 0);
+    if (m_log_fd != -1) {
+      auto prefix    = "\n--- posix_spawn failed: ";
+      auto errno_str = torrent::system::errno_enum_str(spawn_status) + " 
---\n";
 
-    torrent::fd_close(pipe_0);
+      struct iovec iovecs[2] = {
+        {const_cast<char*>(prefix), std::strlen(prefix)},
+        {const_cast<char*>(errno_str.c_str()), errno_str.size()},
+      };
 
-    if (m_log_fd != -1) {
-      result = write(m_log_fd, "Captured output:\n", sizeof("Captured 
output:\n"));
-      result = write(m_log_fd, m_capture.data(), m_capture.length());
+      [[maybe_unused]] int result = ::writev(m_log_fd, iovecs, 2);
     }
+
+    throw torrent::input_error("ExecFile::execute() posix_spawn failed: " + 
torrent::system::errno_enum_str(spawn_status));
   }
 
   if (flags & flag_background) {
-    if (m_log_fd != -1)
-      result = write(m_log_fd, "\n--- Running in Background ---\n", 
sizeof("\n--- Running in Background ---\n"));
-
+    m_waitpid_queue.close_pid(spawn_process.child_pid());
     return 0;
   }
 
-  int status;
-
-  while (::waitpid(child_pid, &status, 0) == -1) {
-    switch (errno) {
-    case EINTR:
-      continue;
-    case ECHILD:
-      throw torrent::internal_error("ExecFile::execute(...) waitpid failed 
with ECHILD, child process not found.");
-    case EINVAL:
-      throw torrent::internal_error("ExecFile::execute(...) waitpid failed 
with EINVAL.");
-    default:
-      throw torrent::internal_error("ExecFile::execute(...) waitpid failed 
with unexpected error: " + std::string(std::strerror(errno)));
-    }
-  };
-
-  // Check return value?
-  if (m_log_fd != -1) {
-    if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
-      result = write(m_log_fd, "\n--- Success ---\n", sizeof("\n--- Success 
---\n"));
-    else
-      result = write(m_log_fd, "\n--- Error ---\n", sizeof("\n--- Error 
---\n"));
-  }
+  if (flags & flag_capture)
+    m_capture = spawn_process.capture_child_output();
 
-  return status;
+  return spawn_process.wait_for_child();
 }
 
 torrent::Object
@@ -237,4 +133,4 @@
   return torrent::Object((int64_t)status);
 }
 
-}
+} // namespace rpc
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.19/src/rpc/exec_file.h 
new/rtorrent-0.16.20/src/rpc/exec_file.h
--- old/rtorrent-0.16.19/src/rpc/exec_file.h    2026-08-02 11:03:01.000000000 
+0200
+++ new/rtorrent-0.16.20/src/rpc/exec_file.h    2026-08-06 10:14:12.000000000 
+0200
@@ -3,6 +3,8 @@
 
 #include <torrent/object.h>
 
+#include "utils/waitpid_queue.h"
+
 namespace rpc {
 
 class ExecFile {
@@ -24,6 +26,8 @@
 private:
   int                 m_log_fd{-1};
   std::string         m_capture;
+
+  utils::WaitpidQueue m_waitpid_queue;
 };
 
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.19/src/utils/waitpid_queue.cc 
new/rtorrent-0.16.20/src/utils/waitpid_queue.cc
--- old/rtorrent-0.16.19/src/utils/waitpid_queue.cc     1970-01-01 
01:00:00.000000000 +0100
+++ new/rtorrent-0.16.20/src/utils/waitpid_queue.cc     2026-08-06 
10:14:12.000000000 +0200
@@ -0,0 +1,107 @@
+#include "config.h"
+
+#include "utils/waitpid_queue.h"
+
+#include <sys/wait.h>
+#include <torrent/exceptions.h>
+
+namespace utils {
+
+WaitpidQueue::WaitpidQueue() {
+  m_worker = std::async(std::launch::async, [this]() {
+      auto wait_time  = 50ms;
+
+      while (true) {
+        if (!m_queue.empty()) {
+          auto start_time = std::chrono::steady_clock::now();
+
+          while (std::chrono::steady_clock::now() - start_time < wait_time) {
+            if (m_should_shutdown.load(std::memory_order_acquire))
+              return;
+
+            std::this_thread::sleep_for(50ms);
+
+            if (m_wakeup_worker.load(std::memory_order_acquire))
+              break;
+          }
+
+        } else {
+          m_wakeup_worker.wait(false, std::memory_order_acquire);
+        }
+
+        // Adds a small delay to allow new processes to finish if they're 
quickly spawned and
+        // terminated.
+        std::this_thread::sleep_for(50ms);
+
+        std::set<pid_t> queue;
+
+        {
+          std::lock_guard<std::mutex> guard(m_mutex);
+
+          if (m_should_shutdown)
+            return;
+
+          if (m_queue.empty())
+            throw torrent::internal_error("WaitpidQueue worker thread woke up 
but queue is empty.");
+
+          queue = m_queue;
+
+          m_wakeup_worker.store(false, std::memory_order_release);
+        }
+
+        wait_time = std::min(10 * 1000ms, wait_time * 2);
+
+        for (auto pid : queue) {
+          if (::waitpid(pid, nullptr, WNOHANG) == 0)
+            continue;
+
+          {
+            std::lock_guard<std::mutex> guard(m_mutex);
+
+            if (m_queue.erase(pid) != 1)
+              throw torrent::internal_error("WaitpidQueue worker thread could 
not find pid in queue.");
+          }
+
+          wait_time = std::max(50ms, wait_time / 2);
+
+          m_remaining.fetch_sub(1, std::memory_order_release);
+          m_remaining.notify_all();
+        }
+      }
+    });
+}
+
+// We don't wait for the worker thread to finish as waitpid isn't needed to be 
called on shutdown.
+WaitpidQueue::~WaitpidQueue() {
+  {
+    std::lock_guard<std::mutex> guard(m_mutex);
+    m_should_shutdown = true;
+  }
+
+  m_wakeup_worker.store(true, std::memory_order_release);
+  m_wakeup_worker.notify_all();
+}
+
+void
+WaitpidQueue::close_pid(pid_t pid) {
+  if (pid < 0)
+    throw torrent::internal_error("WaitpidQueue::close_pid() called with 
invalid pid.");
+
+  m_remaining.fetch_add(1, std::memory_order_acquire);
+
+  {
+    std::lock_guard<std::mutex> guard(m_mutex);
+    m_queue.insert(pid);
+  }
+
+  m_wakeup_worker.store(true, std::memory_order_release);
+  m_wakeup_worker.notify_all();
+}
+
+void
+WaitpidQueue::wait_for(uint32_t max_remaining) {
+  while (m_remaining.load(std::memory_order_acquire) > max_remaining)
+    m_remaining.wait(max_remaining, std::memory_order_acquire);
+}
+
+} // namespace torrent::utils
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.19/src/utils/waitpid_queue.h 
new/rtorrent-0.16.20/src/utils/waitpid_queue.h
--- old/rtorrent-0.16.19/src/utils/waitpid_queue.h      1970-01-01 
01:00:00.000000000 +0100
+++ new/rtorrent-0.16.20/src/utils/waitpid_queue.h      2026-08-06 
10:14:12.000000000 +0200
@@ -0,0 +1,46 @@
+#ifndef RTORRENT_UTILS_WAITPID_QUEUE_H
+#define RTORRENT_UTILS_WAITPID_QUEUE_H
+
+#include <future>
+#include <set>
+#include <torrent/system/common.h>
+
+namespace utils {
+
+class WaitpidQueue {
+public:
+  WaitpidQueue();
+  ~WaitpidQueue();
+
+  uint32_t            size() const;
+
+  void                close_pid(int pid);
+
+  void                wait_for(uint32_t max_remaining);
+
+  // TODO: Add a signal handler to tell the worker thread to wake up. Use a 
counter to batch wakeups.
+
+private:
+  WaitpidQueue(const WaitpidQueue&) = delete;
+  WaitpidQueue& operator=(const WaitpidQueue&) = delete;
+
+  std::future<void>   m_worker;
+
+  align_cacheline
+
+  std::mutex          m_mutex;
+  std::set<pid_t>     m_queue;
+
+  align_cacheline
+
+  std::atomic<bool>     m_wakeup_worker{};
+  std::atomic<bool>     m_should_shutdown{};
+
+  std::atomic<uint32_t> m_remaining{};
+};
+
+inline uint32_t WaitpidQueue::size() const { return 
m_remaining.load(std::memory_order_acquire); }
+
+} // namespace utils
+
+#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.19/src/utils/watch_ready_queue.h 
new/rtorrent-0.16.20/src/utils/watch_ready_queue.h
--- old/rtorrent-0.16.19/src/utils/watch_ready_queue.h  2026-08-02 
11:03:02.000000000 +0200
+++ new/rtorrent-0.16.20/src/utils/watch_ready_queue.h  2026-08-06 
10:14:12.000000000 +0200
@@ -9,7 +9,7 @@
 #include <utility>
 #include <vector>
 
-#include <torrent/utils/scheduler.h>
+#include <torrent/system/scheduler.h>
 
 namespace utils {
 
@@ -49,10 +49,12 @@
   void               update_status(Entry* entry);
   void               schedule();
 
-  std::map<std::string, Entry>   m_entries;
-  std::vector<Entry*>            m_entry_queue;
-  torrent::utils::SchedulerEntry m_task_process;
-  bool                           m_active{true};
+  std::map<std::string, Entry> m_entries;
+  std::vector<Entry*>          m_entry_queue;
+
+  bool                         m_active{true};
+
+  torrent::system::SchedulerEntry m_task_process;
 };
 
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.19/test/helpers/test_main_thread.cc 
new/rtorrent-0.16.20/test/helpers/test_main_thread.cc
--- old/rtorrent-0.16.19/test/helpers/test_main_thread.cc       2026-08-02 
11:03:02.000000000 +0200
+++ new/rtorrent-0.16.20/test/helpers/test_main_thread.cc       2026-08-06 
10:14:12.000000000 +0200
@@ -8,7 +8,6 @@
 #include "torrent/exceptions.h"
 #include "torrent/net/resolver.h"
 #include "torrent/utils/log.h"
-#include "torrent/utils/scheduler.h"
 
 std::unique_ptr<TestMainThread>
 TestMainThread::create() {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.19/test/src/test_command_local.cc 
new/rtorrent-0.16.20/test/src/test_command_local.cc
--- old/rtorrent-0.16.19/test/src/test_command_local.cc 2026-08-02 
11:03:02.000000000 +0200
+++ new/rtorrent-0.16.20/test/src/test_command_local.cc 2026-08-06 
10:14:12.000000000 +0200
@@ -45,8 +45,8 @@
 
     CPPUNIT_ASSERT(rpc::commands.has(name + ".size"));
     CPPUNIT_ASSERT(rpc::commands.has(name + ".max_size"));
+    CPPUNIT_ASSERT(rpc::commands.has(name + ".min_alloc"));
 
-    CPPUNIT_ASSERT_EQUAL(has_allocation, rpc::commands.has(name + 
".min_alloc"));
     CPPUNIT_ASSERT_EQUAL(has_allocation, rpc::commands.has(name + 
".max_alloc"));
     CPPUNIT_ASSERT_EQUAL(has_allocation, rpc::commands.has(name + 
".min_alloc.set"));
     CPPUNIT_ASSERT_EQUAL(has_allocation, rpc::commands.has(name + 
".max_alloc.set"));

Reply via email to