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-07-01 16:38:30
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/rtorrent (Old)
 and      /work/SRC/openSUSE:Factory/.rtorrent.new.11887 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "rtorrent"

Wed Jul  1 16:38:30 2026 rev:34 rq:1362739 version:0.16.15

Changes:
--------
--- /work/SRC/openSUSE:Factory/rtorrent/rtorrent.changes        2026-06-15 
19:45:47.653323772 +0200
+++ /work/SRC/openSUSE:Factory/.rtorrent.new.11887/rtorrent.changes     
2026-07-01 16:39:10.406356070 +0200
@@ -1,0 +2,15 @@
+Tue Jun 30 21:07:56 UTC 2026 - Jan Engelhardt <[email protected]>
+
+- Update to release 0.16.15
+  * Deprecated commands: network.open_sockets,
+    network.max_open_sockets, network.max_open_sockets.set,
+    network.http.max_total_connections.set,
+    network.max_open_files.set
+  * Global network socket commands (e.g.,
+    network.max_open_sockets) are now deprecated. Socket
+    allocation is managed granularly via Socket Categories:
+    generic, http, internal, rpc, and files.
+    (e.g. new commands: system.sockets.<category>.size, .max_size,
+    .min_alloc/.max_alloc)
+
+-------------------------------------------------------------------

Old:
----
  rtorrent-0.16.14.tar.gz

New:
----
  rtorrent-0.16.15.tar.gz

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

Other differences:
------------------
++++++ rtorrent.spec ++++++
--- /var/tmp/diff_new_pack.cqdYWD/_old  2026-07-01 16:39:11.154382106 +0200
+++ /var/tmp/diff_new_pack.cqdYWD/_new  2026-07-01 16:39:11.158382245 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           rtorrent
-Version:        0.16.14
+Version:        0.16.15
 Release:        0
 Summary:        Console-based BitTorrent client
 License:        SUSE-GPL-2.0+-with-openssl-exception

++++++ _scmsync.obsinfo ++++++
--- /var/tmp/diff_new_pack.cqdYWD/_old  2026-07-01 16:39:11.202383777 +0200
+++ /var/tmp/diff_new_pack.cqdYWD/_new  2026-07-01 16:39:11.206383916 +0200
@@ -1,5 +1,5 @@
-mtime: 1781442982
-commit: ed7ff080c03459460d03b561a84bc3c9983f0d6c836b908206e3978fcc8d8562
+mtime: 1782854052
+commit: 6e53d80fc4ed98c92abed75aab664a0b23cf717c6e65d31daeff000d98782cd3
 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-06-30 23:14:12.000000000 +0200
@@ -0,0 +1 @@
+.osc

++++++ rtorrent-0.16.14.tar.gz -> rtorrent-0.16.15.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.14/configure 
new/rtorrent-0.16.15/configure
--- old/rtorrent-0.16.14/configure      2026-06-14 10:19:35.000000000 +0200
+++ new/rtorrent-0.16.15/configure      2026-06-22 11:17:06.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.14.
+# Generated by GNU Autoconf 2.72 for rtorrent 0.16.15.
 #
 # Report bugs to <[email protected]>.
 #
@@ -614,8 +614,8 @@
 # Identity of this package.
 PACKAGE_NAME='rtorrent'
 PACKAGE_TARNAME='rtorrent'
-PACKAGE_VERSION='0.16.14'
-PACKAGE_STRING='rtorrent 0.16.14'
+PACKAGE_VERSION='0.16.15'
+PACKAGE_STRING='rtorrent 0.16.15'
 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.14 to adapt to many kinds of systems.
+'configure' configures rtorrent 0.16.15 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.14:";;
+     short | recursive ) echo "Configuration of rtorrent 0.16.15:";;
    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.14
+rtorrent configure 0.16.15
 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.14, which was
+It was created by rtorrent $as_me 0.16.15, 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.14'
+ VERSION='0.16.15'
 
 
 printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h
@@ -18708,7 +18708,7 @@
 fi
 
 
-printf "%s\n" "#define API_VERSION 22" >>confdefs.h
+printf "%s\n" "#define API_VERSION 23" >>confdefs.h
 
 
 
@@ -21491,19 +21491,19 @@
 fi
 
 pkg_failed=no
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libtorrent >= 
0.16.14" >&5
-printf %s "checking for libtorrent >= 0.16.14... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libtorrent >= 
0.16.15" >&5
+printf %s "checking for libtorrent >= 0.16.15... " >&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.14\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "libtorrent >= 0.16.14") 2>&5
+    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists 
--print-errors \"libtorrent >= 0.16.15\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libtorrent >= 0.16.15") 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.14" 
2>/dev/null`
+  pkg_cv_DEPENDENCIES_CFLAGS=`$PKG_CONFIG --cflags "libtorrent >= 0.16.15" 
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.14\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "libtorrent >= 0.16.14") 2>&5
+    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists 
--print-errors \"libtorrent >= 0.16.15\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libtorrent >= 0.16.15") 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.14" 
2>/dev/null`
+  pkg_cv_DEPENDENCIES_LIBS=`$PKG_CONFIG --libs "libtorrent >= 0.16.15" 
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.14" 2>&1`
+                DEPENDENCIES_PKG_ERRORS=`$PKG_CONFIG --short-errors 
--print-errors --cflags --libs "libtorrent >= 0.16.15" 2>&1`
         else
-                DEPENDENCIES_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags 
--libs "libtorrent >= 0.16.14" 2>&1`
+                DEPENDENCIES_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags 
--libs "libtorrent >= 0.16.15" 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.14) were not 
met:
+        as_fn_error $? "Package requirements (libtorrent >= 0.16.15) were not 
met:
 
 $DEPENDENCIES_PKG_ERRORS
 
@@ -23494,7 +23494,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.14, which was
+This file was extended by rtorrent $as_me 0.16.15, which was
 generated by GNU Autoconf 2.72.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -23562,7 +23562,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config='$ac_cs_config_escaped'
 ac_cs_version="\\
-rtorrent config.status 0.16.14
+rtorrent config.status 0.16.15
 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.14/configure.ac 
new/rtorrent-0.16.15/configure.ac
--- old/rtorrent-0.16.14/configure.ac   2026-06-14 10:04:12.000000000 +0200
+++ new/rtorrent-0.16.15/configure.ac   2026-06-22 11:01:51.000000000 +0200
@@ -1,6 +1,6 @@
 m4_pattern_allow([PKG_CHECK_EXISTS])
 
-AC_INIT([rtorrent],[0.16.14],[[email protected]])
+AC_INIT([rtorrent],[0.16.15],[[email protected]])
 
 AC_CONFIG_HEADERS([config.h])
 AC_CONFIG_MACRO_DIRS([scripts])
@@ -14,7 +14,7 @@
 
 PKG_PROG_PKG_CONFIG
 
-AC_DEFINE([API_VERSION], [22], [api version])
+AC_DEFINE([API_VERSION], [23], [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.14])
+PKG_CHECK_MODULES([DEPENDENCIES], [libtorrent >= 0.16.15])
 
 AC_LANG_PUSH(C++)
 TORRENT_WITH_XMLRPC_C
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.14/src/command_download.cc 
new/rtorrent-0.16.15/src/command_download.cc
--- old/rtorrent-0.16.14/src/command_download.cc        2026-06-14 
10:04:12.000000000 +0200
+++ new/rtorrent-0.16.15/src/command_download.cc        2026-06-22 
11:01:51.000000000 +0200
@@ -780,15 +780,15 @@
   CMD2_DL_TIMESTAMP("d.timestamp.started",      "rtorrent", 
"timestamp.started");
   CMD2_DL_TIMESTAMP("d.timestamp.finished",     "rtorrent", 
"timestamp.finished");
 
-  CMD2_DL       ("d.connection_current",     
std::bind(&torrent::option_as_string, torrent::OPTION_CONNECTION_TYPE, 
CMD2_ON_DL(connection_type)));
-  CMD2_DL_STRING("d.connection_current.set", 
std::bind(&apply_d_connection_type, std::placeholders::_1, 
std::placeholders::_2));
+  CMD2_DL         ("d.connection_current",     [](auto* d, auto)     { return 
torrent::option_to_c_str_or_throw(torrent::OPTION_CONNECTION_TYPE, 
d->download()->connection_type()); });
+  CMD2_DL_STRING_V("d.connection_current.set", [](auto* d, auto arg) { 
apply_d_connection_type(d, arg); });
 
   CMD2_DL_VAR_STRING("d.connection_leech",      "rtorrent", 
"connection_leech");
   CMD2_DL_VAR_STRING("d.connection_seed",       "rtorrent", "connection_seed");
 
-  CMD2_DL       ("d.up.choke_heuristics",       
std::bind(&torrent::option_as_string, torrent::OPTION_CHOKE_HEURISTICS, 
CMD2_ON_DL(upload_choke_heuristic)));
+  CMD2_DL       ("d.up.choke_heuristics",       [](auto* d, auto)     { return 
torrent::option_to_c_str_or_throw(torrent::OPTION_CHOKE_HEURISTICS, 
d->download()->upload_choke_heuristic()); });
   CMD2_DL_STRING("d.up.choke_heuristics.set",   
std::bind(&apply_d_choke_heuristics, std::placeholders::_1, 
std::placeholders::_2, false));
-  CMD2_DL       ("d.down.choke_heuristics",     
std::bind(&torrent::option_as_string, torrent::OPTION_CHOKE_HEURISTICS, 
CMD2_ON_DL(download_choke_heuristic)));
+  CMD2_DL       ("d.down.choke_heuristics",     [](auto* d, auto)     { return 
torrent::option_to_c_str_or_throw(torrent::OPTION_CHOKE_HEURISTICS, 
d->download()->download_choke_heuristic()); });
   CMD2_DL_STRING("d.down.choke_heuristics.set", 
std::bind(&apply_d_choke_heuristics, std::placeholders::_1, 
std::placeholders::_2, true));
 
   CMD2_DL_VAR_STRING("d.up.choke_heuristics.leech", "rtorrent", 
"choke_heuristics.up.leech");
@@ -843,7 +843,7 @@
   CMD2_DL         ("d.bytes_done",     CMD2_ON_DL(bytes_done));
   CMD2_DL         ("d.ratio",          std::bind(&retrieve_d_ratio, 
std::placeholders::_1));
   CMD2_DL         ("d.chunks_hashed",  CMD2_ON_DL(chunks_hashed));
-  CMD2_DL         ("d.free_diskspace", CMD2_ON_FL(free_diskspace));
+  CMD2_DL         ("d.free_diskspace", [](auto* download, auto) { return 
download->file_list()->free_diskspace_no_cache(); });
 
   CMD2_DL         ("d.size_files",     CMD2_ON_FL(size_files));
   CMD2_DL         ("d.size_bytes",     CMD2_ON_FL(size_bytes));
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.14/src/command_events.cc 
new/rtorrent-0.16.15/src/command_events.cc
--- old/rtorrent-0.16.14/src/command_events.cc  2026-06-14 10:04:12.000000000 
+0200
+++ new/rtorrent-0.16.15/src/command_events.cc  2026-06-22 11:01:51.000000000 
+0200
@@ -168,12 +168,14 @@
 apply_close_low_diskspace(int64_t arg, uint32_t skip_priority) {
   bool closed = false;
 
+  torrent::FileList::cache_list cache;
+
   for (auto download : *control->core()->download_list()) {
     if (!download->is_downloading())
       continue;
     if (download->priority() >= skip_priority)
       continue;
-    if (download->file_list()->free_diskspace() >= (uint64_t)arg)
+    if (download->file_list()->free_diskspace(cache) >= (uint64_t)arg)
       continue;
 
     control->core()->download_list()->close(download);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.14/src/command_groups.cc 
new/rtorrent-0.16.15/src/command_groups.cc
--- old/rtorrent-0.16.14/src/command_groups.cc  2026-06-14 10:04:12.000000000 
+0200
+++ new/rtorrent-0.16.15/src/command_groups.cc  2026-06-22 11:01:51.000000000 
+0200
@@ -337,54 +337,51 @@
 
 void
 initialize_command_groups() {
-  CMD2_ANY         ("choke_group.list",                
std::bind(&apply_cg_list));
-  CMD2_ANY_STRING  ("choke_group.insert",              
std::bind(&apply_cg_insert, std::placeholders::_2));
+  CMD_ANY         ("choke_group.list",                
std::bind(&apply_cg_list));
+  CMD_ANY_STRING  ("choke_group.insert",              
std::bind(&apply_cg_insert, std::placeholders::_2));
 
 #if USE_CHOKE_GROUP
-  CMD2_ANY         ("choke_group.size",                
std::bind(&torrent::ResourceManager::group_size, torrent::resource_manager()));
-  CMD2_ANY_STRING  ("choke_group.index_of",            
std::bind(&torrent::ResourceManager::group_index_of, 
torrent::resource_manager(), std::placeholders::_2));
+  CMD_ANY         ("choke_group.size",                
std::bind(&torrent::ResourceManager::group_size, torrent::resource_manager()));
+  CMD_ANY_STRING  ("choke_group.index_of",            
std::bind(&torrent::ResourceManager::group_index_of, 
torrent::resource_manager(), std::placeholders::_2));
 #else
   apply_cg_insert("default");
 
-  CMD2_ANY         ("choke_group.size",                
std::bind(&std::vector<torrent::choke_group*>::size, cg_list_hack));
-  CMD2_ANY_STRING  ("choke_group.index_of",            
std::bind(&apply_cg_index_of, std::placeholders::_2));
+  CMD_ANY         ("choke_group.size",                
std::bind(&std::vector<torrent::choke_group*>::size, cg_list_hack));
+  CMD_ANY_STRING  ("choke_group.index_of",            
std::bind(&apply_cg_index_of, std::placeholders::_2));
 #endif
 
   // Commands specific for a group. Supports as the first argument the
   // name, the index or a negative index.
-  CMD2_ANY         ("choke_group.general.size",        
std::bind(&torrent::choke_group::size, CG_GROUP_AT()));
+  CMD_ANY         ("choke_group.general.size",        
std::bind(&torrent::choke_group::size, CG_GROUP_AT()));
 
-  CMD2_ANY         ("choke_group.tracker.mode",        
std::bind(&torrent::option_as_string, torrent::OPTION_TRACKER_MODE,
-                                                                 
std::bind(&torrent::choke_group::tracker_mode, CG_GROUP_AT())));
-  CMD2_ANY_LIST    ("choke_group.tracker.mode.set",    
std::bind(&apply_cg_tracker_mode_set, std::placeholders::_2));
-
-  CMD2_ANY         ("choke_group.all.up.update_balance",   
std::bind(&apply_cg_all_update_balance, true));
-  CMD2_ANY         ("choke_group.all.down.update_balance", 
std::bind(&apply_cg_all_update_balance, false));
-
-  CMD2_ANY         ("choke_group.up.rate",             
std::bind(&torrent::choke_group::up_rate, CG_GROUP_AT()));
-  CMD2_ANY         ("choke_group.down.rate",           
std::bind(&torrent::choke_group::down_rate, CG_GROUP_AT()));
-
-  CMD2_ANY         ("choke_group.up.max.unlimited",    
std::bind(&torrent::choke_queue::is_unlimited, 
CHOKE_GROUP(&torrent::choke_group::up_queue)));
-  CMD2_ANY         ("choke_group.up.max",              
std::bind(&torrent::choke_queue::max_unchoked_signed, 
CHOKE_GROUP(&torrent::choke_group::up_queue)));
-  CMD2_ANY_LIST    ("choke_group.up.max.set",          
std::bind(&apply_cg_max_set, std::placeholders::_2, true));
-
-  CMD2_ANY         ("choke_group.up.total",            
std::bind(&torrent::choke_queue::size_total, 
CHOKE_GROUP(&torrent::choke_group::up_queue)));
-  CMD2_ANY         ("choke_group.up.queued",           
std::bind(&torrent::choke_queue::size_queued, 
CHOKE_GROUP(&torrent::choke_group::up_queue)));
-  CMD2_ANY         ("choke_group.up.unchoked",         
std::bind(&torrent::choke_queue::size_unchoked, 
CHOKE_GROUP(&torrent::choke_group::up_queue)));
-  CMD2_ANY         ("choke_group.up.heuristics",       
std::bind(&torrent::option_as_string, torrent::OPTION_CHOKE_HEURISTICS,
-                                                                 
std::bind(&torrent::choke_queue::heuristics, 
CHOKE_GROUP(&torrent::choke_group::up_queue))));
-  CMD2_ANY_LIST    ("choke_group.up.heuristics.set",   
std::bind(&apply_cg_heuristics_set, std::placeholders::_2, true));
-
-  CMD2_ANY         ("choke_group.down.max.unlimited",  
std::bind(&torrent::choke_queue::is_unlimited, 
CHOKE_GROUP(&torrent::choke_group::down_queue)));
-  CMD2_ANY         ("choke_group.down.max",            
std::bind(&torrent::choke_queue::max_unchoked_signed, 
CHOKE_GROUP(&torrent::choke_group::down_queue)));
-  CMD2_ANY_LIST    ("choke_group.down.max.set",        
std::bind(&apply_cg_max_set, std::placeholders::_2, false));
-
-  CMD2_ANY         ("choke_group.down.total",          
std::bind(&torrent::choke_queue::size_total, 
CHOKE_GROUP(&torrent::choke_group::down_queue)));
-  CMD2_ANY         ("choke_group.down.queued",         
std::bind(&torrent::choke_queue::size_queued, 
CHOKE_GROUP(&torrent::choke_group::down_queue)));
-  CMD2_ANY         ("choke_group.down.unchoked",       
std::bind(&torrent::choke_queue::size_unchoked, 
CHOKE_GROUP(&torrent::choke_group::down_queue)));
-  CMD2_ANY         ("choke_group.down.heuristics",     
std::bind(&torrent::option_as_string, torrent::OPTION_CHOKE_HEURISTICS,
-                                                                 
std::bind(&torrent::choke_queue::heuristics, 
CHOKE_GROUP(&torrent::choke_group::down_queue))));
-  CMD2_ANY_LIST    ("choke_group.down.heuristics.set", 
std::bind(&apply_cg_heuristics_set, std::placeholders::_2, false));
+  CMD_ANY         ("choke_group.tracker.mode",        [](auto, auto arg) { 
return torrent::option_to_str_or_throw(torrent::OPTION_TRACKER_MODE, 
cg_get_group(arg)->tracker_mode()); });
+  CMD_ANY_LIST    ("choke_group.tracker.mode.set",    [](auto, auto arg) { 
return apply_cg_tracker_mode_set(arg); });
+
+  CMD_ANY         ("choke_group.all.up.update_balance",   
std::bind(&apply_cg_all_update_balance, true));
+  CMD_ANY         ("choke_group.all.down.update_balance", 
std::bind(&apply_cg_all_update_balance, false));
+
+  CMD_ANY         ("choke_group.up.rate",             
std::bind(&torrent::choke_group::up_rate, CG_GROUP_AT()));
+  CMD_ANY         ("choke_group.down.rate",           
std::bind(&torrent::choke_group::down_rate, CG_GROUP_AT()));
+
+  CMD_ANY         ("choke_group.up.max.unlimited",    
std::bind(&torrent::choke_queue::is_unlimited, 
CHOKE_GROUP(&torrent::choke_group::up_queue)));
+  CMD_ANY         ("choke_group.up.max",              
std::bind(&torrent::choke_queue::max_unchoked_signed, 
CHOKE_GROUP(&torrent::choke_group::up_queue)));
+  CMD_ANY_LIST    ("choke_group.up.max.set",          
std::bind(&apply_cg_max_set, std::placeholders::_2, true));
+
+  CMD_ANY         ("choke_group.up.total",            
std::bind(&torrent::choke_queue::size_total, 
CHOKE_GROUP(&torrent::choke_group::up_queue)));
+  CMD_ANY         ("choke_group.up.queued",           
std::bind(&torrent::choke_queue::size_queued, 
CHOKE_GROUP(&torrent::choke_group::up_queue)));
+  CMD_ANY         ("choke_group.up.unchoked",         
std::bind(&torrent::choke_queue::size_unchoked, 
CHOKE_GROUP(&torrent::choke_group::up_queue)));
+  CMD_ANY         ("choke_group.up.heuristics",       [](auto, auto arg) { 
return torrent::option_to_str_or_throw(torrent::OPTION_CHOKE_HEURISTICS, 
cg_get_group(arg)->up_queue()->heuristics()); });
+  CMD_ANY_LIST    ("choke_group.up.heuristics.set",   [](auto, auto arg) { 
return apply_cg_heuristics_set(arg, true); });
+
+  CMD_ANY         ("choke_group.down.max.unlimited",  
std::bind(&torrent::choke_queue::is_unlimited, 
CHOKE_GROUP(&torrent::choke_group::down_queue)));
+  CMD_ANY         ("choke_group.down.max",            
std::bind(&torrent::choke_queue::max_unchoked_signed, 
CHOKE_GROUP(&torrent::choke_group::down_queue)));
+  CMD_ANY_LIST    ("choke_group.down.max.set",        
std::bind(&apply_cg_max_set, std::placeholders::_2, false));
+
+  CMD_ANY         ("choke_group.down.total",          
std::bind(&torrent::choke_queue::size_total, 
CHOKE_GROUP(&torrent::choke_group::down_queue)));
+  CMD_ANY         ("choke_group.down.queued",         
std::bind(&torrent::choke_queue::size_queued, 
CHOKE_GROUP(&torrent::choke_group::down_queue)));
+  CMD_ANY         ("choke_group.down.unchoked",       
std::bind(&torrent::choke_queue::size_unchoked, 
CHOKE_GROUP(&torrent::choke_group::down_queue)));
+  CMD_ANY         ("choke_group.down.heuristics",     [](auto, auto arg) { 
return torrent::option_to_str_or_throw(torrent::OPTION_CHOKE_HEURISTICS, 
cg_get_group(arg)->down_queue()->heuristics()); });
+  CMD_ANY_LIST    ("choke_group.down.heuristics.set", [](auto, auto arg) { 
return apply_cg_heuristics_set(arg, false); });
 
   rpc::rpc.mark_safe("choke_group.list");
   rpc::rpc.mark_safe("choke_group.size");
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.14/src/command_helpers.h 
new/rtorrent-0.16.15/src/command_helpers.h
--- old/rtorrent-0.16.14/src/command_helpers.h  2026-06-14 10:04:12.000000000 
+0200
+++ new/rtorrent-0.16.15/src/command_helpers.h  2026-06-22 11:01:51.000000000 
+0200
@@ -8,6 +8,25 @@
 void initialize_commands();
 
 //
+// Aliases with CMD_* for the below
+//
+
+#define CMD_ANY(key, slot)                CMD2_ANY(key, slot)
+#define CMD_ANY_P(key, slot)              CMD2_ANY_P(key, slot)
+#define CMD_REDIRECT(key, slot)           CMD2_REDIRECT(key, slot)
+#define CMD_REDIRECT_NO_EXPORT(key, slot) CMD2_REDIRECT_NO_EXPORT(key, slot)
+#define CMD_ANY_STRING(key, slot)         CMD2_ANY_STRING(key, slot)
+#define CMD_ANY_STRING_V(key, slot)       CMD2_ANY_STRING_V(key, slot)
+#define CMD_ANY_LIST(key, slot)           CMD2_ANY_LIST(key, slot)
+#define CMD_VAR_VALUE(key, value)         CMD2_VAR_VALUE(key, value)
+#define CMD_VAR_BOOL(key, value)          CMD2_VAR_BOOL(key, value)
+#define CMD_VAR_STRING(key, value)        CMD2_VAR_STRING(key, value)
+#define CMD_VAR_C_STRING(key, value)      CMD2_VAR_C_STRING(key, value)
+#define CMD_VAR_LIST(key)                 CMD2_VAR_LIST(key)
+#define CMD_ANY_V(key, slot)              CMD2_ANY_V(key, slot)
+#define CMD_ANY_VALUE_V(key, slot)        CMD2_ANY_VALUE_V(key, slot)
+
+//
 // New std::function based command_base helper functions:
 //
 
@@ -115,7 +134,6 @@
 #define CMD2_REDIRECT_TRACKER(from_key, to_key) \
   rpc::commands.create_redirect(from_key, to_key, 
rpc::CommandMap::flag_public_rpc | rpc::CommandMap::flag_tracker_target | 
rpc::CommandMap::flag_dont_delete);
 
-
 //
 // Conversion of return types:
 //
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.14/src/command_ip.cc 
new/rtorrent-0.16.15/src/command_ip.cc
--- old/rtorrent-0.16.14/src/command_ip.cc      2026-06-14 10:04:12.000000000 
+0200
+++ new/rtorrent-0.16.15/src/command_ip.cc      2026-06-22 11:01:51.000000000 
+0200
@@ -353,7 +353,7 @@
     inet_ntop(AF_INET, &net_start, start_str, INET_ADDRSTRLEN);
     inet_ntop(AF_INET, &net_end, end_str, INET_ADDRSTRLEN);
 
-    snprintf(buffer, 64, "%s-%s %s", start_str, end_str, 
torrent::option_as_string(torrent::OPTION_IP_FILTER, value));
+    snprintf(buffer, 64, "%s-%s %s", start_str, end_str, 
torrent::option_to_c_str_or_throw(torrent::OPTION_IP_FILTER, value));
 
     result.push_back((std::string)buffer);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.14/src/command_local.cc 
new/rtorrent-0.16.15/src/command_local.cc
--- old/rtorrent-0.16.14/src/command_local.cc   2026-06-14 10:04:12.000000000 
+0200
+++ new/rtorrent-0.16.15/src/command_local.cc   2026-06-22 11:01:51.000000000 
+0200
@@ -12,6 +12,7 @@
 #include <torrent/data/file_manager.h>
 #include <torrent/data/chunk_utils.h>
 #include <torrent/runtime/runtime.h>
+#include <torrent/runtime/socket_manager.h>
 #include <torrent/utils/chrono.h>
 #include <torrent/utils/option_strings.h>
 
@@ -191,139 +192,155 @@
   torrent::FileManager*  fileManager = torrent::file_manager();
 
   if (rpc::call_command_value("method.use_deprecated") == 1) {
-    CMD2_ANY_LIST    ("file.append",    std::bind(&cmd_file_append, 
std::placeholders::_2));
+    CMD_ANY_LIST    ("file.append",    std::bind(&cmd_file_append, 
std::placeholders::_2));
   }
 
-  CMD2_ANY         ("system.hostname", std::bind(&system_hostname));
-  CMD2_ANY         ("system.pid",      std::bind(&getpid));
+  CMD_ANY         ("system.hostname", std::bind(&system_hostname));
+  CMD_ANY         ("system.pid",      std::bind(&getpid));
 
-  CMD2_VAR_C_STRING("system.api_version",           (int64_t)API_VERSION);
-  CMD2_VAR_C_STRING("system.client_version",        PACKAGE_VERSION);
-  CMD2_VAR_C_STRING("system.library_version",       
torrent::runtime::version());
-
-  CMD2_VAR_VALUE   ("system.file.allocate",         0);
-  CMD2_VAR_VALUE   ("system.file.max_size",         (int64_t)512 << 30);
-  CMD2_VAR_VALUE   ("system.file.split_size",       -1);
-  CMD2_VAR_STRING  ("system.file.split_suffix",     ".part");
+  CMD_VAR_C_STRING("system.api_version",           (int64_t)API_VERSION);
+  CMD_VAR_C_STRING("system.client_version",        PACKAGE_VERSION);
+  CMD_VAR_C_STRING("system.library_version",       
torrent::runtime::version());
+
+  CMD_VAR_VALUE   ("system.file.allocate",         0);
+  CMD_VAR_VALUE   ("system.file.max_size",         (int64_t)512 << 30);
+  CMD_VAR_VALUE   ("system.file.split_size",       -1);
+  CMD_VAR_STRING  ("system.file.split_suffix",     ".part");
 
-  CMD2_ANY         ("system.file_status_cache.size",   
std::bind(&utils::FileStatusCache::size,
+  CMD_ANY         ("system.file_status_cache.size",   
std::bind(&utils::FileStatusCache::size,
                                                                  
(utils::FileStatusCache::base_type*)control->core()->file_status_cache()));
-  CMD2_ANY_V       ("system.file_status_cache.prune",  
std::bind(&utils::FileStatusCache::prune, 
control->core()->file_status_cache()));
+  CMD_ANY_V       ("system.file_status_cache.prune",  
std::bind(&utils::FileStatusCache::prune, 
control->core()->file_status_cache()));
 
-  CMD2_VAR_BOOL    ("file.prioritize_toc",          0);
-  CMD2_VAR_LIST    ("file.prioritize_toc.first");
-  CMD2_VAR_LIST    ("file.prioritize_toc.last");
-
-  CMD2_ANY         ("system.files.advise_random",             
std::bind(&FM_t::advise_random, fileManager));
-  CMD2_ANY_VALUE_V ("system.files.advise_random.set",         
std::bind(&FM_t::set_advise_random, fileManager, std::placeholders::_2));
-  CMD2_ANY         ("system.files.advise_random.hashing",     
std::bind(&FM_t::advise_random_hashing, fileManager));
-  CMD2_ANY_VALUE_V ("system.files.advise_random.hashing.set", 
std::bind(&FM_t::set_advise_random_hashing, fileManager, 
std::placeholders::_2));
-  CMD2_ANY         ("system.files.session.fdatasync",         [](auto, auto)   
     { return session_thread::manager()->use_fsyncdisk(); });
-  CMD2_ANY_VALUE_V ("system.files.session.fdatasync.set",     [](auto, auto& 
value) { return session_thread::manager()->set_use_fsyncdisk(value); });
-
-  CMD2_ANY         ("system.files.opened_counter",     
std::bind(&FM_t::files_opened_counter, fileManager));
-  CMD2_ANY         ("system.files.closed_counter",     
std::bind(&FM_t::files_closed_counter, fileManager));
-  CMD2_ANY         ("system.files.failed_counter",     
std::bind(&FM_t::files_failed_counter, fileManager));
+  CMD_VAR_BOOL    ("file.prioritize_toc",          0);
+  CMD_VAR_LIST    ("file.prioritize_toc.first");
+  CMD_VAR_LIST    ("file.prioritize_toc.last");
 
-  CMD2_ANY_STRING  ("system.env",                      std::bind(&system_env, 
std::placeholders::_2));
+  CMD_ANY         ("system.files.advise_random",             
std::bind(&FM_t::advise_random, fileManager));
+  CMD_ANY_VALUE_V ("system.files.advise_random.set",         
std::bind(&FM_t::set_advise_random, fileManager, std::placeholders::_2));
+  CMD_ANY         ("system.files.advise_random.hashing",     
std::bind(&FM_t::advise_random_hashing, fileManager));
+  CMD_ANY_VALUE_V ("system.files.advise_random.hashing.set", 
std::bind(&FM_t::set_advise_random_hashing, fileManager, 
std::placeholders::_2));
+  CMD_ANY         ("system.files.session.fdatasync",         [](auto, auto)    
    { return session_thread::manager()->use_fsyncdisk(); });
+  CMD_ANY_VALUE_V ("system.files.session.fdatasync.set",     [](auto, auto& 
value) { return session_thread::manager()->set_use_fsyncdisk(value); });
 
-  CMD2_ANY         ("system.time",                     []([[maybe_unused]] 
auto t, [[maybe_unused]] auto o) -> torrent::Object {
-      return torrent::this_thread::cached_seconds().count();
-    });
-  CMD2_ANY         ("system.time_seconds",             []([[maybe_unused]] 
auto t, [[maybe_unused]] auto o) -> torrent::Object {
-      return 
torrent::utils::cast_seconds(torrent::utils::time_since_epoch()).count();
-    });
-  CMD2_ANY         ("system.time_usec",                []([[maybe_unused]] 
auto t, [[maybe_unused]] auto o) -> torrent::Object {
-      return torrent::utils::time_since_epoch().count();
-    });
+  CMD_ANY         ("system.files.opened_counter",     
std::bind(&FM_t::files_opened_counter, fileManager));
+  CMD_ANY         ("system.files.closed_counter",     
std::bind(&FM_t::files_closed_counter, fileManager));
+  CMD_ANY         ("system.files.failed_counter",     
std::bind(&FM_t::files_failed_counter, fileManager));
+
+  CMD_ANY_STRING  ("system.env",                      [](auto, auto& str)   { 
return system_env(str); });
+
+  CMD_ANY         ("system.time",                     [](auto, auto)        { 
return torrent::this_thread::cached_seconds().count(); });
+  CMD_ANY         ("system.time_seconds",             [](auto, auto)        { 
return 
torrent::utils::cast_seconds(torrent::utils::time_since_epoch()).count(); });
+  CMD_ANY         ("system.time_usec",                [](auto, auto)        { 
return torrent::utils::time_since_epoch().count(); });
+
+  CMD_ANY_VALUE_V ("system.umask.set",                [](auto, auto& value) { 
return ::umask(value); });
+
+  CMD_VAR_BOOL    ("system.daemon",                   false);
+
+  CMD_ANY_V       ("system.shutdown.normal",          [](auto, auto)        { 
control->receive_normal_shutdown(); });
+  CMD_ANY_V       ("system.shutdown.quick",           [](auto, auto)        { 
control->receive_quick_shutdown(); });
+
+  CMD_REDIRECT_NO_EXPORT("system.shutdown", "system.shutdown.normal");
 
-  CMD2_ANY_VALUE_V ("system.umask.set",                std::bind(&umask, 
std::placeholders::_2));
+  CMD_ANY         ("system.cwd",                      [](auto, auto)        { 
return system_get_cwd(); });
+  CMD_ANY_STRING  ("system.cwd.set",                  [](auto, auto& str)   { 
return system_set_cwd(str); });
 
-  CMD2_VAR_BOOL    ("system.daemon",                   false);
+  CMD_ANY         ("system.sockets.size",             [](auto, auto)        { 
return torrent::runtime::socket_manager()->size(); });
+  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(); });
 
-  CMD2_ANY_V       ("system.shutdown.normal",          
std::bind(&Control::receive_normal_shutdown, control));
-  CMD2_ANY_V       ("system.shutdown.quick",           
std::bind(&Control::receive_quick_shutdown, control));
-  CMD2_REDIRECT_NO_EXPORT("system.shutdown", "system.shutdown.normal");
-
-  CMD2_ANY         ("system.cwd",                      
std::bind(&system_get_cwd));
-  CMD2_ANY_STRING  ("system.cwd.set",                  
std::bind(&system_set_cwd, std::placeholders::_2));
-
-  CMD2_ANY         ("pieces.sync.always_safe",         
std::bind(&CM_t::safe_sync, chunkManager));
-  CMD2_ANY_VALUE_V ("pieces.sync.always_safe.set",     
std::bind(&CM_t::set_safe_sync, chunkManager, std::placeholders::_2));
-  CMD2_ANY         ("pieces.sync.safe_free_diskspace", 
std::bind(&CM_t::safe_free_diskspace, chunkManager));
-  CMD2_ANY         ("pieces.sync.timeout",             
std::bind(&CM_t::timeout_sync, chunkManager));
-  CMD2_ANY_VALUE_V ("pieces.sync.timeout.set",         
std::bind(&CM_t::set_timeout_sync, chunkManager, std::placeholders::_2));
-  CMD2_ANY         ("pieces.sync.timeout_safe",        
std::bind(&CM_t::timeout_safe_sync, chunkManager));
-  CMD2_ANY_VALUE_V ("pieces.sync.timeout_safe.set",    
std::bind(&CM_t::set_timeout_safe_sync, chunkManager, std::placeholders::_2));
-  CMD2_ANY         ("pieces.sync.queue_size",          
std::bind(&CM_t::sync_queue_size, chunkManager));
-
-  CMD2_ANY         ("pieces.preload.type",             
std::bind(&CM_t::preload_type, chunkManager));
-  CMD2_ANY_VALUE_V ("pieces.preload.type.set",         
std::bind(&CM_t::set_preload_type, chunkManager, std::placeholders::_2));
-  CMD2_ANY         ("pieces.preload.min_size",         
std::bind(&CM_t::preload_min_size, chunkManager));
-  CMD2_ANY_VALUE_V ("pieces.preload.min_size.set",     
std::bind(&CM_t::set_preload_min_size, chunkManager, std::placeholders::_2));
-  CMD2_ANY         ("pieces.preload.min_rate",         
std::bind(&CM_t::preload_required_rate, chunkManager));
-  CMD2_ANY_VALUE_V ("pieces.preload.min_rate.set",     
std::bind(&CM_t::set_preload_required_rate, chunkManager, 
std::placeholders::_2));
-
-  CMD2_ANY         ("pieces.memory.current",           
std::bind(&CM_t::memory_usage, chunkManager));
-  CMD2_ANY         ("pieces.memory.sync_queue",        
std::bind(&CM_t::sync_queue_memory_usage, chunkManager));
-  CMD2_ANY         ("pieces.memory.block_count",       
std::bind(&CM_t::memory_block_count, chunkManager));
-  CMD2_ANY         ("pieces.memory.max",               
std::bind(&CM_t::max_memory_usage, chunkManager));
-  CMD2_ANY_VALUE_V ("pieces.memory.max.set",           
std::bind(&CM_t::set_max_memory_usage, chunkManager, std::placeholders::_2));
-  CMD2_ANY         ("pieces.stats_preloaded",          
std::bind(&CM_t::stats_preloaded, chunkManager));
-  CMD2_ANY         ("pieces.stats_not_preloaded",      
std::bind(&CM_t::stats_not_preloaded, chunkManager));
-
-  CMD2_ANY         ("pieces.stats.total_size",         
std::bind(&apply_pieces_stats_total_size));
-
-  CMD2_ANY         ("pieces.hash.queue_size",          
std::bind(&torrent::main_thread::hash_queue_size));
-  CMD2_VAR_BOOL    ("pieces.hash.on_completion",       true);
-
-  CMD2_VAR_STRING  ("directory.default",               "./");
-
-  CMD2_VAR_STRING  ("session.name",                    "");
-  CMD2_ANY         ("session.path",                    [](auto, auto)        { 
return session_thread::manager()->path(); });
-  CMD2_ANY_STRING_V("session.path.set",                [](auto, auto& str)   { 
return session_thread::manager()->set_path(str); });
-  CMD2_ANY         ("session.use_lock",                [](auto, auto)        { 
return session_thread::manager()->use_lock(); });
-  CMD2_ANY_VALUE_V ("session.use_lock.set",            [](auto, auto& value) { 
return session_thread::manager()->set_use_lock(value); });
-  CMD2_VAR_BOOL    ("session.on_completion",           true);
+  for (uint32_t i = 0; i < torrent::runtime::SocketManager::category_count; 
++i) {
+    auto category      = 
static_cast<torrent::runtime::socket_manager_category_t>(i);
+    auto category_name = "system.sockets." + 
torrent::option_to_str_or_throw(torrent::OPTION_SOCKET_CATEGORY, i);
 
-  CMD2_ANY_V       ("session.save",                    [dList](auto, auto)   { 
return dList->session_save(); });
+    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); });
+    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); 
});
 
-  CMD2_ANY         ("magnet.path",                     [](auto, auto)        { 
return control->core()->magnet_path(); });
-  CMD2_ANY_STRING_V("magnet.path.set",                 [](auto, auto& str)   { 
return control->core()->set_magnet_path(str); });
+    if (i == 0)
+      continue;
+
+    CMD_ANY_VALUE_V(category_name + ".min_alloc.set", [category](auto, auto& 
value) { 
torrent::runtime::socket_manager()->set_category_min_allocation(category, 
value); });
+    CMD_ANY_VALUE_V(category_name + ".max_alloc.set", [category](auto, auto& 
value) { 
torrent::runtime::socket_manager()->set_category_max_allocation(category, 
value); });
+  }
+
+  CMD_ANY         ("pieces.sync.always_safe",         
std::bind(&CM_t::safe_sync, chunkManager));
+  CMD_ANY_VALUE_V ("pieces.sync.always_safe.set",     
std::bind(&CM_t::set_safe_sync, chunkManager, std::placeholders::_2));
+  CMD_ANY         ("pieces.sync.safe_free_diskspace", 
std::bind(&CM_t::safe_free_diskspace, chunkManager));
+  CMD_ANY         ("pieces.sync.timeout",             
std::bind(&CM_t::timeout_sync, chunkManager));
+  CMD_ANY_VALUE_V ("pieces.sync.timeout.set",         
std::bind(&CM_t::set_timeout_sync, chunkManager, std::placeholders::_2));
+  CMD_ANY         ("pieces.sync.timeout_safe",        
std::bind(&CM_t::timeout_safe_sync, chunkManager));
+  CMD_ANY_VALUE_V ("pieces.sync.timeout_safe.set",    
std::bind(&CM_t::set_timeout_safe_sync, chunkManager, std::placeholders::_2));
+  CMD_ANY         ("pieces.sync.queue_size",          
std::bind(&CM_t::sync_queue_size, chunkManager));
+
+  CMD_ANY         ("pieces.preload.type",             
std::bind(&CM_t::preload_type, chunkManager));
+  CMD_ANY_VALUE_V ("pieces.preload.type.set",         
std::bind(&CM_t::set_preload_type, chunkManager, std::placeholders::_2));
+  CMD_ANY         ("pieces.preload.min_size",         
std::bind(&CM_t::preload_min_size, chunkManager));
+  CMD_ANY_VALUE_V ("pieces.preload.min_size.set",     
std::bind(&CM_t::set_preload_min_size, chunkManager, std::placeholders::_2));
+  CMD_ANY         ("pieces.preload.min_rate",         
std::bind(&CM_t::preload_required_rate, chunkManager));
+  CMD_ANY_VALUE_V ("pieces.preload.min_rate.set",     
std::bind(&CM_t::set_preload_required_rate, chunkManager, 
std::placeholders::_2));
+
+  CMD_ANY         ("pieces.memory.current",           
std::bind(&CM_t::memory_usage, chunkManager));
+  CMD_ANY         ("pieces.memory.sync_queue",        
std::bind(&CM_t::sync_queue_memory_usage, chunkManager));
+  CMD_ANY         ("pieces.memory.block_count",       
std::bind(&CM_t::memory_block_count, chunkManager));
+  CMD_ANY         ("pieces.memory.max",               
std::bind(&CM_t::max_memory_usage, chunkManager));
+  CMD_ANY_VALUE_V ("pieces.memory.max.set",           
std::bind(&CM_t::set_max_memory_usage, chunkManager, std::placeholders::_2));
+  CMD_ANY         ("pieces.stats_preloaded",          
std::bind(&CM_t::stats_preloaded, chunkManager));
+  CMD_ANY         ("pieces.stats_not_preloaded",      
std::bind(&CM_t::stats_not_preloaded, chunkManager));
+
+  CMD_ANY         ("pieces.stats.total_size",         
std::bind(&apply_pieces_stats_total_size));
+
+  CMD_ANY         ("pieces.hash.queue_size",          
std::bind(&torrent::main_thread::hash_queue_size));
+  CMD_VAR_BOOL    ("pieces.hash.on_completion",       true);
+
+  CMD_VAR_STRING  ("directory.default",               "./");
+
+  CMD_VAR_STRING  ("session.name",                    "");
+  CMD_ANY         ("session.path",                    [](auto, auto)        { 
return session_thread::manager()->path(); });
+  CMD_ANY_STRING_V("session.path.set",                [](auto, auto& str)   { 
return session_thread::manager()->set_path(str); });
+  CMD_ANY         ("session.use_lock",                [](auto, auto)        { 
return session_thread::manager()->use_lock(); });
+  CMD_ANY_VALUE_V ("session.use_lock.set",            [](auto, auto& value) { 
return session_thread::manager()->set_use_lock(value); });
+  CMD_VAR_BOOL    ("session.on_completion",           true);
+
+  CMD_ANY_V       ("session.save",                    [dList](auto, auto)   { 
return dList->session_save(); });
+
+  CMD_ANY         ("magnet.path",                     [](auto, auto)        { 
return control->core()->magnet_path(); });
+  CMD_ANY_STRING_V("magnet.path.set",                 [](auto, auto& str)   { 
return control->core()->set_magnet_path(str); });
 
 #ifdef HAVE_LUA
   rpc::LuaEngine* lua_engine = control->lua_engine();
 
-  CMD2_ANY         ("lua.execute",                    
std::bind(&rpc::execute_lua, lua_engine, std::placeholders::_1, 
std::placeholders::_2, 0));
-  CMD2_ANY         ("lua.execute.str",                
std::bind(&rpc::execute_lua, lua_engine, std::placeholders::_1, 
std::placeholders::_2, rpc::LuaEngine::flag_string));
+  CMD_ANY         ("lua.execute",                    
std::bind(&rpc::execute_lua, lua_engine, std::placeholders::_1, 
std::placeholders::_2, 0));
+  CMD_ANY         ("lua.execute.str",                
std::bind(&rpc::execute_lua, lua_engine, std::placeholders::_1, 
std::placeholders::_2, rpc::LuaEngine::flag_string));
 #endif
 
-#define CMD2_EXECUTE(key, flags)                                        \
-  CMD2_ANY(key, std::bind(&rpc::ExecFile::execute_object, &rpc::execFile, 
std::placeholders::_2, flags));
+#define CMD_EXECUTE(key, flags)                                        \
+  CMD_ANY(key, std::bind(&rpc::ExecFile::execute_object, &rpc::execFile, 
std::placeholders::_2, flags));
 
-  CMD2_EXECUTE     ("execute",                 
rpc::ExecFile::flag_expand_tilde | rpc::ExecFile::flag_throw);
-  CMD2_EXECUTE     ("execute.throw",           
rpc::ExecFile::flag_expand_tilde | rpc::ExecFile::flag_throw);
-  CMD2_EXECUTE     ("execute.throw.bg",        
rpc::ExecFile::flag_expand_tilde | rpc::ExecFile::flag_throw | 
rpc::ExecFile::flag_background);
-  CMD2_EXECUTE     ("execute.nothrow",         
rpc::ExecFile::flag_expand_tilde);
-  CMD2_EXECUTE     ("execute.nothrow.bg",      
rpc::ExecFile::flag_expand_tilde | rpc::ExecFile::flag_background);
-  CMD2_EXECUTE     ("execute.raw",             rpc::ExecFile::flag_throw);
-  CMD2_EXECUTE     ("execute.raw.bg",          rpc::ExecFile::flag_throw | 
rpc::ExecFile::flag_background);
-  CMD2_EXECUTE     ("execute.raw_nothrow",     0);
-  CMD2_EXECUTE     ("execute.raw_nothrow.bg",  rpc::ExecFile::flag_background);
-  CMD2_EXECUTE     ("execute.capture",         rpc::ExecFile::flag_throw | 
rpc::ExecFile::flag_expand_tilde | rpc::ExecFile::flag_capture);
-  CMD2_EXECUTE     ("execute.capture_nothrow", 
rpc::ExecFile::flag_expand_tilde | rpc::ExecFile::flag_capture);
+  CMD_EXECUTE     ("execute",                 rpc::ExecFile::flag_expand_tilde 
| rpc::ExecFile::flag_throw);
+  CMD_EXECUTE     ("execute.throw",           rpc::ExecFile::flag_expand_tilde 
| rpc::ExecFile::flag_throw);
+  CMD_EXECUTE     ("execute.throw.bg",        rpc::ExecFile::flag_expand_tilde 
| rpc::ExecFile::flag_throw | rpc::ExecFile::flag_background);
+  CMD_EXECUTE     ("execute.nothrow",         
rpc::ExecFile::flag_expand_tilde);
+  CMD_EXECUTE     ("execute.nothrow.bg",      rpc::ExecFile::flag_expand_tilde 
| rpc::ExecFile::flag_background);
+  CMD_EXECUTE     ("execute.raw",             rpc::ExecFile::flag_throw);
+  CMD_EXECUTE     ("execute.raw.bg",          rpc::ExecFile::flag_throw | 
rpc::ExecFile::flag_background);
+  CMD_EXECUTE     ("execute.raw_nothrow",     0);
+  CMD_EXECUTE     ("execute.raw_nothrow.bg",  rpc::ExecFile::flag_background);
+  CMD_EXECUTE     ("execute.capture",         rpc::ExecFile::flag_throw | 
rpc::ExecFile::flag_expand_tilde | rpc::ExecFile::flag_capture);
+  CMD_EXECUTE     ("execute.capture_nothrow", rpc::ExecFile::flag_expand_tilde 
| rpc::ExecFile::flag_capture);
 
   // TODO: Convert to new command types:
   *rpc::command_base::argument(0) = "placeholder.0";
   *rpc::command_base::argument(1) = "placeholder.1";
   *rpc::command_base::argument(2) = "placeholder.2";
   *rpc::command_base::argument(3) = "placeholder.3";
-  CMD2_ANY_P("argument.0", std::bind(&rpc::command_base::argument_ref, 0));
-  CMD2_ANY_P("argument.1", std::bind(&rpc::command_base::argument_ref, 1));
-  CMD2_ANY_P("argument.2", std::bind(&rpc::command_base::argument_ref, 2));
-  CMD2_ANY_P("argument.3", std::bind(&rpc::command_base::argument_ref, 3));
+  CMD_ANY_P("argument.0", std::bind(&rpc::command_base::argument_ref, 0));
+  CMD_ANY_P("argument.1", std::bind(&rpc::command_base::argument_ref, 1));
+  CMD_ANY_P("argument.2", std::bind(&rpc::command_base::argument_ref, 2));
+  CMD_ANY_P("argument.3", std::bind(&rpc::command_base::argument_ref, 3));
 
-  CMD2_ANY_LIST  ("group.insert", std::bind(&group_insert, 
std::placeholders::_2));
+  CMD_ANY_LIST  ("group.insert", std::bind(&group_insert, 
std::placeholders::_2));
 
   rpc::rpc.mark_safe("system.api_version");
   rpc::rpc.mark_safe("system.client_version");
@@ -332,6 +349,18 @@
   rpc::rpc.mark_safe("system.file.split_size");
   rpc::rpc.mark_safe("system.file.split_suffix");
 
+  rpc::rpc.mark_safe("system.sockets.size");
+  rpc::rpc.mark_safe("system.sockets.max_size");
+
+  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);
+
+    rpc::rpc.mark_safe(category_name + ".size");
+    rpc::rpc.mark_safe(category_name + ".max_size");
+    rpc::rpc.mark_safe(category_name + ".min_alloc");
+    rpc::rpc.mark_safe(category_name + ".max_alloc");
+  }
+
   rpc::rpc.mark_safe("directory.default");
   rpc::rpc.mark_safe("session.path");
   rpc::rpc.mark_safe("session.use_lock");
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.14/src/command_network.cc 
new/rtorrent-0.16.15/src/command_network.cc
--- old/rtorrent-0.16.14/src/command_network.cc 2026-06-14 10:04:12.000000000 
+0200
+++ new/rtorrent-0.16.15/src/command_network.cc 2026-06-22 11:01:51.000000000 
+0200
@@ -251,7 +251,6 @@
   CMD2_ANY         ("network.http.max_host_connections",      
[http_stack](auto, auto)        { return http_stack->max_host_connections(); });
   CMD2_ANY_VALUE_V ("network.http.max_host_connections.set",  
[http_stack](auto, auto& value) { return 
http_stack->set_max_host_connections(value); });
   CMD2_ANY         ("network.http.max_total_connections",     
[http_stack](auto, auto)        { return http_stack->max_total_connections(); 
});
-  CMD2_ANY_VALUE_V ("network.http.max_total_connections.set", 
[http_stack](auto, auto& value) { return 
http_stack->set_max_total_connections(value); });
   CMD2_ANY         ("network.http.proxy_address",             
[http_stack](auto, auto)        { return http_stack->http_proxy(); });
   CMD2_ANY_STRING_V("network.http.proxy_address.set",         
[http_stack](auto, auto& str)   { return http_stack->set_http_proxy(str); });
   CMD2_ANY         ("network.http.ssl_verify_host",           
[http_stack](auto, auto)        { return http_stack->ssl_verify_host(); });
@@ -263,7 +262,7 @@
   CMD2_ANY_VALUE_V ("network.send_buffer.size.set",       [nw_config](auto, 
auto& value) { return nw_config->set_send_buffer_size(value); });
   CMD2_ANY         ("network.receive_buffer.size",        [nw_config](auto, 
auto)        { return nw_config->receive_buffer_size(); });
   CMD2_ANY_VALUE_V ("network.receive_buffer.size.set",    [nw_config](auto, 
auto& value) { return nw_config->set_receive_buffer_size(value); });
-  CMD2_ANY_STRING  ("network.tos.set",                    [](auto, auto& str)  
               { return apply_tos(str); });
+  CMD2_ANY_STRING  ("network.tos.set",                    [](auto, auto& str)  
          { return apply_tos(str); });
 
   CMD2_ANY         ("network.bind_address",               [nw_config](auto, 
auto)        { return nw_config->bind_address_best_match_str(); });
   CMD2_ANY_STRING_V("network.bind_address.set",           [nw_config](auto, 
auto& str)   { return nw_config->set_bind_address_str(str); });
@@ -284,11 +283,7 @@
 
   CMD2_ANY         ("network.open_files",            [file_manager](auto, 
auto)        { return file_manager->open_files(); });
   CMD2_ANY         ("network.max_open_files",        [file_manager](auto, 
auto)        { return file_manager->max_open_files(); });
-  CMD2_ANY_VALUE_V ("network.max_open_files.set",    [file_manager](auto, 
auto& value) { return file_manager->set_max_open_files(value); });
   CMD2_ANY         ("network.total_handshakes",      [](auto, auto)            
        { return torrent::runtime::total_handshakes(); });
-  CMD2_ANY         ("network.open_sockets",          [](auto, auto)            
        { return torrent::runtime::socket_manager()->size(); });
-  CMD2_ANY         ("network.max_open_sockets",      [](auto, auto)            
        { return torrent::runtime::socket_manager()->max_size(); });
-  CMD2_ANY_VALUE_V ("network.max_open_sockets.set",  [](auto, auto& value)     
        { return 
torrent::runtime::socket_manager()->set_max_size_and_adjust(value); });
 
   CMD2_ANY_STRING  ("network.scgi.open_port",        std::bind(&apply_scgi, 
std::placeholders::_2, 1));
   CMD2_ANY_STRING  ("network.scgi.open_local",       std::bind(&apply_scgi, 
std::placeholders::_2, 2));
@@ -329,10 +324,9 @@
   rpc::rpc.mark_safe("network.http.max_host_connections");
   rpc::rpc.mark_safe("network.http.max_total_connections");
 
+  rpc::rpc.mark_safe("network.total_handshakes");
   rpc::rpc.mark_safe("network.open_files");
   rpc::rpc.mark_safe("network.max_open_files");
-  rpc::rpc.mark_safe("network.max_open_sockets");
-  rpc::rpc.mark_safe("network.total_handshakes");
 
   rpc::rpc.mark_safe("network.send_buffer.size");
   rpc::rpc.mark_safe("network.receive_buffer.size");
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.14/src/command_ui.cc 
new/rtorrent-0.16.15/src/command_ui.cc
--- old/rtorrent-0.16.14/src/command_ui.cc      2026-06-14 10:04:12.000000000 
+0200
+++ new/rtorrent-0.16.15/src/command_ui.cc      2026-06-22 11:01:51.000000000 
+0200
@@ -472,11 +472,14 @@
 // if (cond1) { branch1 } else if (cond2) { branch2 } else { branch3 }
 // <cond1>,<branch1>,<cond2>,<branch2>,<branch3>
 torrent::Object
-apply_if(rpc::target_type target, const torrent::Object& rawArgs, int flags) {
-  const torrent::Object::list_type& args = rawArgs.as_list();
-  torrent::Object::list_const_iterator itr = args.begin();
+apply_if(rpc::target_type target, const torrent::Object& raw_args, int flags) {
+  auto& args = raw_args.as_list();
+  auto  itr  = args.begin();
 
-  while (itr != args.end() && itr != --args.end()) {
+  if (args.empty())
+    throw torrent::input_error("Empty argument list to " + std::string((flags 
& 0x1) ? "branch" : "if") + ".");
+
+  {
     torrent::Object tmp;
     const torrent::Object* conditional;
 
@@ -500,40 +503,44 @@
       result = false;
       break;
     default:
-      throw torrent::input_error("Type not supported by 'if'.");
+      throw torrent::input_error("Type not supported by " + std::string((flags 
& 0x1) ? "branch" : "if") + ".");
     };
 
     itr++;
 
-    if (result)
-      break;
-
-    itr++;
+    if (!result && itr != args.end())
+      itr++;
   }
 
   if (itr == args.end())
     return torrent::Object();
 
-  if (flags & 0x1 && itr->is_string()) {
-    return rpc::parse_command(target, itr->as_string().c_str(), 
itr->as_string().c_str() + itr->as_string().size()).first;
+  if (flags & 0x1) {
+    if (itr->is_string())
+      return rpc::parse_command(target, itr->as_string().c_str(), 
itr->as_string().c_str() + itr->as_string().size()).first;
 
-  } else if (flags & 0x1 && itr->is_dict_key()) {
-    return rpc::commands.call_command(itr->as_dict_key().c_str(), 
itr->as_dict_obj(), target);
+    if (itr->is_dict_key())
+      return rpc::commands.call_command(itr->as_dict_key().c_str(), 
itr->as_dict_obj(), target);
 
-  } else if (flags & 0x1 && itr->is_list()) {
-    // Move this into a special function or something. Also, might be
-    // nice to have a parse_command function that takes list
-    // iterator...
-
-    for (const auto& cmdItr : itr->as_list())
-      if (cmdItr.is_string())
-        rpc::parse_command(target, cmdItr.as_string().c_str(), 
cmdItr.as_string().c_str() + cmdItr.as_string().size());
+    if (itr->is_list()) {
+      for (const auto& cmd_itr : itr->as_list()) {
+        if (cmd_itr.is_string())
+          rpc::parse_command(target, cmd_itr.as_string().c_str(), 
cmd_itr.as_string().c_str() + cmd_itr.as_string().size());
 
-    return torrent::Object();
+        else if (cmd_itr.is_dict_key())
+          rpc::commands.call_command(cmd_itr.as_dict_key().c_str(), 
cmd_itr.as_dict_obj(), target);
+
+        else
+          throw torrent::input_error("Invalid command type in branch list.");
+      }
 
-  } else {
-    return *itr;
+      return torrent::Object();
+    }
+
+    throw torrent::input_error("Invalid command type in branch.");
   }
+
+  return *itr;
 }
 
 torrent::Object
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.14/src/control.cc 
new/rtorrent-0.16.15/src/control.cc
--- old/rtorrent-0.16.14/src/control.cc 2026-06-14 10:04:12.000000000 +0200
+++ new/rtorrent-0.16.15/src/control.cc 2026-06-22 11:01:51.000000000 +0200
@@ -76,7 +76,7 @@
   m_ui->init(this);
 
   if(!display::Canvas::daemon())
-    m_inputStdin->insert(torrent::this_thread::poll());
+    m_inputStdin->insert();
 }
 
 void
@@ -86,7 +86,9 @@
   torrent::this_thread::scheduler()->erase(&m_task_shutdown);
 
   if(!display::Canvas::daemon())
-    m_inputStdin->remove(torrent::this_thread::poll());
+    m_inputStdin->remove();
+
+  m_directory_events->close();
 
   if (scgi_thread::thread()->is_active())
     scgi_thread::thread()->stop_thread_wait();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.14/src/input/input_event.cc 
new/rtorrent-0.16.15/src/input/input_event.cc
--- old/rtorrent-0.16.14/src/input/input_event.cc       2026-06-14 
10:04:12.000000000 +0200
+++ new/rtorrent-0.16.15/src/input/input_event.cc       2026-06-22 
11:01:51.000000000 +0200
@@ -2,20 +2,27 @@
 
 #include "input_event.h"
 
+#include <torrent/common.h>
+#include <torrent/system/poll.h>
+
 #include "display/attributes.h"
 
 namespace input {
 
 void
-InputEvent::insert(torrent::system::Poll* p) {
-  p->open(this);
-  p->insert_read(this);
+InputEvent::insert() {
+  torrent::this_thread::poll()->open(this);
+  torrent::this_thread::poll()->insert_read(this);
+  torrent::this_thread::poll()->insert_error(this);
 }
 
 void
-InputEvent::remove(torrent::system::Poll* p) {
-  p->remove_read(this);
-  p->close(this);
+InputEvent::remove() {
+  if (!is_open())
+    return;
+
+  torrent::this_thread::poll()->remove_and_close(this);
+  set_file_descriptor(-1);
 }
 
 void
@@ -32,6 +39,8 @@
 
 void
 InputEvent::event_error() {
+  torrent::this_thread::poll()->remove_and_close(this);
+  set_file_descriptor(-1);
 }
 
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.14/src/input/input_event.h 
new/rtorrent-0.16.15/src/input/input_event.h
--- old/rtorrent-0.16.14/src/input/input_event.h        2026-06-14 
10:04:12.000000000 +0200
+++ new/rtorrent-0.16.15/src/input/input_event.h        2026-06-22 
11:01:51.000000000 +0200
@@ -4,7 +4,6 @@
 #include <functional>
 
 #include <torrent/event.h>
-#include <torrent/system/poll.h>
 
 namespace input {
 
@@ -16,8 +15,8 @@
 
   const char*         type_name() const override { return "input"; }
 
-  void                insert(torrent::system::Poll* p);
-  void                remove(torrent::system::Poll* p);
+  void                insert();
+  void                remove();
 
   void                event_read() override;
   void                event_write() override;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.14/src/main.cc 
new/rtorrent-0.16.15/src/main.cc
--- old/rtorrent-0.16.14/src/main.cc    2026-06-14 10:04:12.000000000 +0200
+++ new/rtorrent-0.16.15/src/main.cc    2026-06-22 11:01:51.000000000 +0200
@@ -112,8 +112,16 @@
     // TODO: Create a fake thread object for initializing other processes and 
enabling logging.
     torrent::initialize_main_thread();
 
+    // Block SIGCHLD until all threads are created, then unblock on 
main-thread, to avoid SIGCHLD
+    // interrupting other threads.
+    //
+    // This means only main-thread can fork and wait for child processes.
+
+    SignalHandler::set_block(SIGALRM);
+    SignalHandler::set_block(SIGPIPE);
+    SignalHandler::set_block(SIGCHLD);
+
     // All signal handlers must restore errno if they return.
-    SignalHandler::set_ignore(SIGPIPE);
     SignalHandler::set_handler(SIGSEGV,  std::bind(&do_panic, SIGSEGV));
     SignalHandler::set_handler(SIGILL,   std::bind(&do_panic, SIGILL));
     SignalHandler::set_handler(SIGFPE,   std::bind(&do_panic, SIGFPE));
@@ -156,6 +164,8 @@
     scgi::ThreadScgi::create_thread();
     session::ThreadSession::create_thread();
 
+    SignalHandler::set_unblock(SIGCHLD);
+
     // Initialize option handlers after libtorrent to ensure
     // torrent::ConnectionManager* are valid etc.
     initialize_commands();
@@ -296,56 +306,71 @@
     // Functions that might not get depracted as they are nice for
     // configuration files, and thus might do with just some
     // cleanup.
-    CMD2_REDIRECT("upload_rate",           
"throttle.global_up.max_rate.set_kb");
-    CMD2_REDIRECT("download_rate",         
"throttle.global_down.max_rate.set_kb");
+    CMD_REDIRECT("upload_rate",           
"throttle.global_up.max_rate.set_kb");
+    CMD_REDIRECT("download_rate",         
"throttle.global_down.max_rate.set_kb");
 
-    CMD2_REDIRECT("ratio.enable",          "group.seeding.ratio.enable");
-    CMD2_REDIRECT("ratio.disable",         "group.seeding.ratio.disable");
-    CMD2_REDIRECT("ratio.min",             "group.seeding.ratio.min");
-    CMD2_REDIRECT("ratio.max",             "group.seeding.ratio.max");
-    CMD2_REDIRECT("ratio.upload",          "group.seeding.ratio.upload");
-    CMD2_REDIRECT("ratio.min.set",         "group.seeding.ratio.min.set");
-    CMD2_REDIRECT("ratio.max.set",         "group.seeding.ratio.max.set");
-    CMD2_REDIRECT("ratio.upload.set",      "group.seeding.ratio.upload.set");
-
-    CMD2_REDIRECT("encryption",            "protocol.encryption.set");
-
-    CMD2_REDIRECT("check_hash",            "pieces.hash.on_completion.set");
-
-    CMD2_REDIRECT("connection_leech",      "protocol.connection.leech.set");
-    CMD2_REDIRECT("connection_seed",       "protocol.connection.seed.set");
-
-    CMD2_REDIRECT("min_peers",             "throttle.min_peers.normal.set");
-    CMD2_REDIRECT("max_peers",             "throttle.max_peers.normal.set");
-    CMD2_REDIRECT("min_peers_seed",        "throttle.min_peers.seed.set");
-    CMD2_REDIRECT("max_peers_seed",        "throttle.max_peers.seed.set");
-
-    CMD2_REDIRECT("min_uploads",           "throttle.min_uploads.set");
-    CMD2_REDIRECT("max_uploads",           "throttle.max_uploads.set");
-    CMD2_REDIRECT("min_downloads",         "throttle.min_downloads.set");
-    CMD2_REDIRECT("max_downloads",         "throttle.max_downloads.set");
-
-    CMD2_REDIRECT("max_uploads_div",       "throttle.max_uploads.div.set");
-    CMD2_REDIRECT("max_uploads_global",    "throttle.max_uploads.global.set");
-    CMD2_REDIRECT("max_downloads_div",     "throttle.max_downloads.div.set");
-    CMD2_REDIRECT("max_downloads_global",  
"throttle.max_downloads.global.set");
-
-    CMD2_REDIRECT("directory",             "directory.default.set");
-    CMD2_REDIRECT("session",               "session.path.set");
-
-    CMD2_REDIRECT("scgi_port",             "network.scgi.open_port");
-    CMD2_REDIRECT("scgi_local",            "network.scgi.open_local");
-
-    CMD2_REDIRECT("to_gm_time",            "convert.gm_time");
-    CMD2_REDIRECT("to_gm_date",            "convert.gm_date");
-    CMD2_REDIRECT("to_time",               "convert.time");
-    CMD2_REDIRECT("to_date",               "convert.date");
-    CMD2_REDIRECT("to_elapsed_time",       "convert.elapsed_time");
-    CMD2_REDIRECT("to_kb",                 "convert.kb");
-    CMD2_REDIRECT("to_mb",                 "convert.mb");
-    CMD2_REDIRECT("to_xb",                 "convert.xb");
-    CMD2_REDIRECT("to_throttle",           "convert.throttle");
+    CMD_REDIRECT("ratio.enable",          "group.seeding.ratio.enable");
+    CMD_REDIRECT("ratio.disable",         "group.seeding.ratio.disable");
+    CMD_REDIRECT("ratio.min",             "group.seeding.ratio.min");
+    CMD_REDIRECT("ratio.max",             "group.seeding.ratio.max");
+    CMD_REDIRECT("ratio.upload",          "group.seeding.ratio.upload");
+    CMD_REDIRECT("ratio.min.set",         "group.seeding.ratio.min.set");
+    CMD_REDIRECT("ratio.max.set",         "group.seeding.ratio.max.set");
+    CMD_REDIRECT("ratio.upload.set",      "group.seeding.ratio.upload.set");
+
+    CMD_REDIRECT("encryption",            "protocol.encryption.set");
+
+    CMD_REDIRECT("check_hash",            "pieces.hash.on_completion.set");
+
+    CMD_REDIRECT("connection_leech",      "protocol.connection.leech.set");
+    CMD_REDIRECT("connection_seed",       "protocol.connection.seed.set");
+
+    CMD_REDIRECT("min_peers",             "throttle.min_peers.normal.set");
+    CMD_REDIRECT("max_peers",             "throttle.max_peers.normal.set");
+    CMD_REDIRECT("min_peers_seed",        "throttle.min_peers.seed.set");
+    CMD_REDIRECT("max_peers_seed",        "throttle.max_peers.seed.set");
+
+    CMD_REDIRECT("min_uploads",           "throttle.min_uploads.set");
+    CMD_REDIRECT("max_uploads",           "throttle.max_uploads.set");
+    CMD_REDIRECT("min_downloads",         "throttle.min_downloads.set");
+    CMD_REDIRECT("max_downloads",         "throttle.max_downloads.set");
+
+    CMD_REDIRECT("max_uploads_div",       "throttle.max_uploads.div.set");
+    CMD_REDIRECT("max_uploads_global",    "throttle.max_uploads.global.set");
+    CMD_REDIRECT("max_downloads_div",     "throttle.max_downloads.div.set");
+    CMD_REDIRECT("max_downloads_global",  "throttle.max_downloads.global.set");
+
+    CMD_REDIRECT("directory",             "directory.default.set");
+    CMD_REDIRECT("session",               "session.path.set");
+
+    CMD_REDIRECT("scgi_port",             "network.scgi.open_port");
+    CMD_REDIRECT("scgi_local",            "network.scgi.open_local");
+
+    CMD_REDIRECT("to_gm_time",            "convert.gm_time");
+    CMD_REDIRECT("to_gm_date",            "convert.gm_date");
+    CMD_REDIRECT("to_time",               "convert.time");
+    CMD_REDIRECT("to_date",               "convert.date");
+    CMD_REDIRECT("to_elapsed_time",       "convert.elapsed_time");
+    CMD_REDIRECT("to_kb",                 "convert.kb");
+    CMD_REDIRECT("to_mb",                 "convert.mb");
+    CMD_REDIRECT("to_xb",                 "convert.xb");
+    CMD_REDIRECT("to_throttle",           "convert.throttle");
+
+    // TODO: Deprecate these at some point a while after 1.1 release.
+
+    CMD_REDIRECT("network.open_sockets",          "system.sockets.size");
+    CMD_REDIRECT("network.max_open_sockets",      "system.sockets.max_size");
+    CMD_REDIRECT("network.max_open_sockets.set",  
"system.sockets.max_size.set");
 
+    rpc::rpc.mark_safe("network.max_open_sockets");
+
+    CMD2_ANY_VALUE_V("network.http.max_total_connections.set", [](auto, auto) {
+        lt_log_print(torrent::LOG_WARN, 
"network.http.max_total_connections.set is deprecated, use 
system.sockets.http.min_alloc.set instead.");
+      });
+
+    CMD2_ANY_VALUE_V("network.max_open_files.set", [](auto, auto) {
+        lt_log_print(torrent::LOG_WARN, "network.max_open_files.set is 
deprecated, use system.sockets.files.min_alloc.set instead.");
+      });
 
     // if (rpc::call_command_value("method.use_intermediate") == 1) {
 
@@ -354,41 +379,41 @@
     // }
 
     if (rpc::call_command_value("method.use_deprecated") == 1) {
-      CMD2_REDIRECT("execute2",         "execute");
-      CMD2_REDIRECT("schedule2",        "schedule");
-      CMD2_REDIRECT("schedule_remove2", "schedule.remove");
+      CMD_REDIRECT("execute2",         "execute");
+      CMD_REDIRECT("schedule2",        "schedule");
+      CMD_REDIRECT("schedule_remove2", "schedule.remove");
 
       // TODO: Remove file.append when cleaning these up.
 
-      CMD2_REDIRECT("bind",                  "network.bind_address.set");
-      CMD2_REDIRECT("ip",                    "network.local_address.set");
-      CMD2_REDIRECT("port_range",            "network.port_range.set");
+      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.
-      CMD2_REDIRECT("dht",                   "dht.mode.set");
+      CMD_REDIRECT("dht",                   "dht.mode.set");
 
-      CMD2_REDIRECT("port_random",           "network.port_random.set");
-      CMD2_REDIRECT("proxy_address",         "network.proxy_address.set");
+      CMD_REDIRECT("port_random",           "network.port_random.set");
+      CMD_REDIRECT("proxy_address",         "network.proxy_address.set");
 
-      CMD2_REDIRECT("key_layout",            "keys.layout.set");
+      CMD_REDIRECT("key_layout",            "keys.layout.set");
 
-      CMD2_REDIRECT("torrent_list_layout",   "ui.torrent_list.layout.set");
+      CMD_REDIRECT("torrent_list_layout",   "ui.torrent_list.layout.set");
 
       CMD2_VAR_STRING("dht.throttle.name",   "deprecated");
       rpc::rpc.mark_safe("dht.throttle.name");
 
-      CMD2_REDIRECT("network.http.max_open",     
"network.http.max_total_connections");
-      CMD2_REDIRECT("network.http.max_open.set", 
"network.http.max_total_connections.set");
+      CMD_REDIRECT("network.http.max_open",     
"network.http.max_total_connections");
+      CMD_REDIRECT("network.http.max_open.set", 
"network.http.max_total_connections.set");
 
       // Users should check their setups to see if they need to modify their 
use of these options.
-      CMD2_REDIRECT("max_memory_usage",      "pieces.memory.max.set");
-      CMD2_REDIRECT("encoding_list",         "encoding.add");
+      CMD_REDIRECT("max_memory_usage",      "pieces.memory.max.set");
+      CMD_REDIRECT("encoding_list",         "encoding.add");
 
-      CMD2_ANY_STRING_V("encoding.add", [](auto, auto) {
+      CMD_ANY_STRING_V("encoding.add", [](auto, auto) {
           lt_log_print(torrent::LOG_WARN, "The 'encoding.add' command is 
deprecated and does nothing.");
         });
 
-      CMD2_ANY_LIST ("throttle.ip", []( auto, auto) {
+      CMD_ANY_LIST("throttle.ip", []( auto, auto) {
           lt_log_print(torrent::LOG_WARN, "The 'throttle.ip' command is 
deprecated and does nothing.");
           return torrent::Object();
         });
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.14/src/rpc/command.h 
new/rtorrent-0.16.15/src/rpc/command.h
--- old/rtorrent-0.16.14/src/rpc/command.h      2026-06-14 10:04:12.000000000 
+0200
+++ new/rtorrent-0.16.15/src/rpc/command.h      2026-06-22 11:01:51.000000000 
+0200
@@ -3,6 +3,7 @@
 
 #include <functional>
 #include <limits>
+#include <new>
 #include <torrent/common.h>
 #include <torrent/object.h>
 #include <torrent/data/file_list_iterator.h>
@@ -28,7 +29,6 @@
   typedef no_type*    cleaned_type;
 };
 
-// Since c++0x isn't out yet...
 template <typename T1, typename T2, typename T3>
 struct rt_triple : private std::pair<T1, T2> {
   typedef std::pair<T1, T2> base_type;
@@ -55,9 +55,6 @@
     base_type(src.first, src.second), third(src.third) {}
 };
 
-// Since it gets used so many places we might as well put it in the
-// rpc namespace.
-//typedef std::pair<int, void*> target_type;
 typedef rt_triple<int, void*, void*> target_type;
 
 class command_base;
@@ -114,10 +111,48 @@
     char buffer[sizeof(torrent::Object) * max_arguments];
   };
 
-  command_base() { new (&_pod<base_function>()) base_function(); }
-  command_base(const command_base& src) { new (&_pod<base_function>()) 
base_function(src._pod<base_function>()); }
+  command_base() : m_copy_helper(nullptr), m_dest_helper(nullptr) {}
 
-  ~command_base() { _pod<base_function>().~base_function(); }
+  command_base(const command_base& src) {
+    m_copy_helper = src.m_copy_helper;
+    m_dest_helper = src.m_dest_helper;
+    if (src.m_copy_helper)
+      src.m_copy_helper(t_pod, src.t_pod);
+  }
+
+  command_base& operator=(const command_base& src) {
+    if (this != &src) {
+      if (m_dest_helper) m_dest_helper(t_pod);
+      m_copy_helper = src.m_copy_helper;
+      m_dest_helper = src.m_dest_helper;
+      if (src.m_copy_helper)
+        src.m_copy_helper(t_pod, src.t_pod);
+    }
+    return *this;
+  }
+
+  command_base(command_base&& src) noexcept {
+    m_copy_helper = src.m_copy_helper;
+    m_dest_helper = src.m_dest_helper;
+    if (src.m_copy_helper)
+      src.m_copy_helper(t_pod, src.t_pod);
+  }
+
+  command_base& operator=(command_base&& src) noexcept {
+    if (this != &src) {
+      if (m_dest_helper) m_dest_helper(t_pod);
+      m_copy_helper = src.m_copy_helper;
+      m_dest_helper = src.m_dest_helper;
+      if (src.m_copy_helper)
+        src.m_copy_helper(t_pod, src.t_pod);
+    }
+    return *this;
+  }
+
+  ~command_base() {
+    if (m_dest_helper)
+      m_dest_helper(t_pod);
+  }
 
   static torrent::Object* argument(unsigned int index) { return 
current_stack.begin() + index; }
   static torrent::Object& argument_ref(unsigned int index) { return 
*(current_stack.begin() + index); }
@@ -132,55 +167,52 @@
   static void             pop_stack(stack_type* stack, torrent::Object* 
last_stack);
 
   template <typename T>
-  void set_function(T s, [[maybe_unused]] int value = 
command_base_is_valid<T>::value) { _pod<T>() = s; }
+  void set_function(T s, [[maybe_unused]] int value = 
command_base_is_valid<T>::value) {
+    static_assert(sizeof(T) <= sizeof(t_pod), "t_pod storage overflow");
+    static_assert(alignof(std::max_align_t) % alignof(T) == 0, "t_pod 
alignment insufficient for type");
+    static_assert(alignof(std::max_align_t) >= alignof(T), "t_pod structural 
capacity mismatch");
+
+    if (m_dest_helper)
+      m_dest_helper(t_pod);
+
+    ::new (t_pod) T(std::move(s));
+
+    m_copy_helper = [](void* dest, const void* src) {
+      ::new (dest) T(*static_cast<const T*>(src));
+    };
+    m_dest_helper = [](void* ptr) {
+      static_cast<T*>(ptr)->~T();
+    };
+  }
 
   template <command_base_call_type T>
   void set_function_2(typename command_base_is_type<T>::type s, 
[[maybe_unused]] int value = command_base_is_valid<typename 
command_base_is_type<T>::type>::value) {
-    _pod<typename command_base_is_type<T>::type>() = s;
+    set_function<typename command_base_is_type<T>::type>(std::move(s));
   }
 
-  // The std::function object in GCC is castable between types with a
-  // pointer to a struct of ctor/dtor/calls for non-POD slots. As such
-  // it should be safe to cast between different std::function
-  // template types, yet what the C++0x standard will say about this I
-  // have no idea atm.
   template <typename tmpl> tmpl& _pod() { return 
reinterpret_cast<tmpl&>(t_pod); }
   template <typename tmpl> const tmpl& _pod() const { return 
reinterpret_cast<const tmpl&>(t_pod); }
 
   template <typename Func, typename T, typename Args>
   static const torrent::Object _call(command_base* cmd, target_type target, 
Args args);
 
-  command_base& operator = (const command_base& src) {
-    _pod<base_function>() = src._pod<base_function>();
-    return *this;
-  }
-
 protected:
-  // For use by functions that need to use placeholders to arguments
-  // within commands. E.d. callable command strings where one of the
-  // arguments within the command needs to be supplied by the caller.
-
-#ifdef HAVE_CXX11
-  union {
-    base_function t_pod;
-    // char t_pod[sizeof(base_function)];
-  };
-#else
-  union {
-    char t_pod[sizeof(base_function)];
-  };
-#endif
+  using copy_fn_t = void (*)(void* dest, const void* src);
+  using dest_fn_t = void (*)(void* ptr);
+
+  alignas(std::max_align_t) char t_pod[sizeof(base_function)];
+
+  copy_fn_t m_copy_helper;
+  dest_fn_t m_dest_helper;
 };
 
 template <typename T1 = void, typename T2 = void>
 struct target_type_id {
-  // Nothing here, so we cause an error.
 };
 
 template <typename T> inline bool
 is_target_compatible(const target_type& target) { return target.first == 
target_type_id<T>::value; }
 
-// Splitting pairs into separate targets.
 inline bool is_target_pair(const target_type& target) { return target.first >= 
command_base::target_download_pair; }
 
 template <typename T> inline T
@@ -203,7 +235,7 @@
 
 #define COMMAND_BASE_TEMPLATE_TYPE(func_type, func_parm)                \
   template <typename T, int proper = target_type_id<T>::proper_type> struct 
func_type { typedef std::function<func_parm> type; }; \
-                                                                        \
+                                                                         \
   template <> struct command_base_is_valid<func_type<target_type>::type>       
         { static const int value = 1; }; \
   template <> struct command_base_is_valid<func_type<core::Download*>::type>   
         { static const int value = 1; }; \
   template <> struct command_base_is_valid<func_type<torrent::Peer*>::type>    
         { static const int value = 1; }; \
@@ -211,8 +243,6 @@
   template <> struct command_base_is_valid<func_type<torrent::File*>::type>    
         { static const int value = 1; }; \
   template <> struct 
command_base_is_valid<func_type<torrent::FileListIterator*>::type> { static 
const int value = 1; };
 
-//  template <typename Q> struct command_base_is_valid<typename 
func_type<Q>::type > { static const int value = 1; };
-
 COMMAND_BASE_TEMPLATE_TYPE(command_function,        torrent::Object (T, const 
torrent::Object&));
 COMMAND_BASE_TEMPLATE_TYPE(command_value_function,  torrent::Object (T, const 
torrent::Object::value_type&));
 COMMAND_BASE_TEMPLATE_TYPE(command_string_function, torrent::Object (T, const 
std::string&));
@@ -220,7 +250,7 @@
 
 #define COMMAND_BASE_TEMPLATE_CALL(func_name, func_type)                \
   template <typename T> const torrent::Object func_name(command_base* 
rawCommand, target_type target, const torrent::Object& args); \
-                                                                        \
+                                                                         \
   template <> struct command_base_is_type<func_name<target_type> >       { 
static const int value = 1; typedef func_type<target_type>::type type; }; \
   template <> struct command_base_is_type<func_name<core::Download*> >   { 
static const int value = 1; typedef func_type<core::Download*>::type type; }; \
   template <> struct command_base_is_type<func_name<torrent::Peer*> >    { 
static const int value = 1; typedef func_type<torrent::Peer*>::type type; }; \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.14/src/rpc/exec_file.cc 
new/rtorrent-0.16.15/src/rpc/exec_file.cc
--- old/rtorrent-0.16.14/src/rpc/exec_file.cc   2026-06-14 10:04:12.000000000 
+0200
+++ new/rtorrent-0.16.15/src/rpc/exec_file.cc   2026-06-22 11:01:51.000000000 
+0200
@@ -3,6 +3,7 @@
 #include <cerrno>
 #include <cstring>
 #include <fcntl.h>
+#include <spawn.h>
 #include <string>
 #include <unistd.h>
 #include <sys/types.h>
@@ -12,6 +13,9 @@
 #include "exec_file.h"
 #include "parse.h"
 
+// Standard POSIX environment pointer
+extern char** environ;
+
 namespace rpc {
 
 // TODO: Access fd through torrent logging?
@@ -34,86 +38,92 @@
     result = write(m_log_fd, "\n---\n", sizeof("\n---\n"));
   }
 
-  int pipeFd[2];
+  int pipe_fd[2];
 
-  if ((flags & flag_capture) && pipe(pipeFd))
+  if ((flags & flag_capture) && pipe(pipe_fd))
     throw torrent::input_error("ExecFile::execute(...) Pipe creation failed.");
 
-  pid_t childPid = fork();
+  auto clean_fn = [pipe_fd, flags]() {
+      if (flags & flag_capture) {
+        ::close(pipe_fd[0]);
+        ::close(pipe_fd[1]);
+      }
+    };
+
+  posix_spawn_file_actions_t actions{};
 
-  if (childPid == -1) {
-    if (flags & flag_capture) {
-      ::close(pipeFd[0]);
-      ::close(pipeFd[1]);
-    }
-    throw torrent::input_error("ExecFile::execute(...) Fork failed.");
+  if (posix_spawn_file_actions_init(&actions) != 0) {
+    clean_fn();
+    throw torrent::internal_error("ExecFile::execute(...) 
posix_spawn_file_actions_init failed.");
   }
 
-  if (childPid == 0) {
-    if (flags & flag_background) {
-      pid_t detached_pid = fork();
+  // 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);
+  }
 
-      if (detached_pid == -1)
-        _exit(-1);
+  // Handle standard output redirection
+  if (flags & flag_capture) {
+    posix_spawn_file_actions_adddup2(&actions, pipe_fd[1], 1);
 
-      if (detached_pid != 0) {
-        if (m_log_fd != -1)
-          result = write(m_log_fd, "\n--- Background task ---\n", 
sizeof("\n--- Background task ---\n"));
+    // Ensure the write end of the pipe is closed in the child after 
duplicating.
+    posix_spawn_file_actions_addclose(&actions, pipe_fd[1]);
+    posix_spawn_file_actions_addclose(&actions, pipe_fd[0]);
 
-        _exit(0);
-      }
+  } else if (m_log_fd != -1) {
+    posix_spawn_file_actions_adddup2(&actions, m_log_fd, 1);
 
-      m_log_fd = -1;
-      flags &= ~flag_capture;
-    }
+  } 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);
+  }
 
-    int devNull = open("/dev/null", O_RDWR);
+  posix_spawnattr_t attr;
+  posix_spawnattr_init(&attr);
 
-    if (devNull != -1)
-      dup2(devNull, 0);
-    else
-      ::close(0);
-
-    if (flags & flag_capture)
-      dup2(pipeFd[1], 1);
-    else if (m_log_fd != -1)
-      dup2(m_log_fd, 1);
-    else if (devNull != -1)
-      dup2(devNull, 1);
-    else
-      ::close(1);
-
-    if (m_log_fd != -1)
-      dup2(m_log_fd, 2);
-    else if (devNull != -1)
-      dup2(devNull, 2);
-    else
-      ::close(2);
-
-    // Close all fd's.
-    for (int i = 3, last = sysconf(_SC_OPEN_MAX); i != last; i++)
-      ::close(i);
+  // If you are using standard close-on-exec (O_CLOEXEC) across rtorrent, 
posix_spawn honors it
+  // automatically. If you want to explicitly enforce a clean slate, modern 
systems support
+  // POSIX_SPAWN_CLOEXEC_DEFAULT.
 
-    result = execvp(file, argv);
+#ifdef POSIX_SPAWN_CLOEXEC_DEFAULT
+  posix_spawnattr_setflags(&attr, POSIX_SPAWN_CLOEXEC_DEFAULT);
+#endif
 
-    _exit(result);
+  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);
+
+  if (spawn_status != 0) {
+    clean_fn();
+    throw torrent::input_error("ExecFile::execute(...) posix_spawn failed: " + 
std::string(std::strerror(spawn_status)));
   }
 
   if (flags & flag_capture) {
     m_capture = std::string();
-    ::close(pipeFd[1]);
+    ::close(pipe_fd[1]);
 
     char buffer[4096];
     ssize_t length;
 
     do {
-      length = read(pipeFd[0], buffer, sizeof(buffer));
+      length = read(pipe_fd[0], buffer, sizeof(buffer));
 
       if (length > 0)
         m_capture += std::string(buffer, length);
+
     } while (length > 0);
 
-    ::close(pipeFd[0]);
+    ::close(pipe_fd[0]);
 
     if (m_log_fd != -1) {
       result = write(m_log_fd, "Captured output:\n", sizeof("Captured 
output:\n"));
@@ -123,7 +133,7 @@
 
   int status;
 
-  while (waitpid(childPid, &status, 0) == -1) {
+  while (waitpid(child_pid, &status, 0) == -1) {
     switch (errno) {
     case EINTR:
       continue;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.14/src/rpc/scgi.cc 
new/rtorrent-0.16.15/src/rpc/scgi.cc
--- old/rtorrent-0.16.14/src/rpc/scgi.cc        2026-06-14 10:04:12.000000000 
+0200
+++ new/rtorrent-0.16.15/src/rpc/scgi.cc        2026-06-22 11:01:51.000000000 
+0200
@@ -48,7 +48,7 @@
 
   open(reinterpret_cast<sockaddr*>(sa), length);
 
-  torrent::runtime::socket_manager()->register_event_or_throw(this, 
torrent::runtime::category_scgi, []() {});
+  torrent::runtime::socket_manager()->register_event_or_throw(this, 
torrent::runtime::category_rpc, []() {});
 }
 
 void
@@ -72,7 +72,7 @@
 
   open(reinterpret_cast<sockaddr*>(sa), offsetof(struct sockaddr_un, sun_path) 
+ filename.size() + 1);
 
-  torrent::runtime::socket_manager()->register_event_or_throw(this, 
torrent::runtime::category_scgi, []() {});
+  torrent::runtime::socket_manager()->register_event_or_throw(this, 
torrent::runtime::category_rpc, []() {});
 
   m_path = filename;
 }
@@ -86,7 +86,7 @@
 
   // fd is already bound and listening; no bind()/listen() needed.
 
-  torrent::runtime::socket_manager()->register_event_or_throw(this, 
torrent::runtime::category_scgi, []() {});
+  torrent::runtime::socket_manager()->register_event_or_throw(this, 
torrent::runtime::category_rpc, []() {});
 }
 
 void
@@ -183,7 +183,7 @@
         task->cancel_open();
       };
 
-    bool result = 
torrent::runtime::socket_manager()->open_event_or_cleanup(m_current->get(), 
torrent::runtime::category_scgi, open_func, cleanup_func);
+    bool result = 
torrent::runtime::socket_manager()->open_event_or_cleanup(m_current->get(), 
torrent::runtime::category_rpc, open_func, cleanup_func);
 
     if (!result)
       break;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.14/src/signal_handler.cc 
new/rtorrent-0.16.15/src/signal_handler.cc
--- old/rtorrent-0.16.14/src/signal_handler.cc  2026-06-14 10:04:12.000000000 
+0200
+++ new/rtorrent-0.16.15/src/signal_handler.cc  2026-06-22 11:01:51.000000000 
+0200
@@ -42,6 +42,7 @@
     throw std::logic_error("SignalHandler::set_handler(...) received an empty 
slot.");
 
   struct sigaction sa;
+
   sigemptyset(&sa.sa_mask);
   sa.sa_flags = SA_RESTART;
   sa.sa_handler = &SignalHandler::caught;
@@ -53,6 +54,34 @@
 }
 
 void
+SignalHandler::set_block(unsigned int signum) {
+  if (signum >= HIGHEST_SIGNAL)
+    throw std::logic_error("SignalHandler::set_block(...) received invalid 
signal value.");
+
+  sigset_t mask;
+
+  sigemptyset(&mask);
+  sigaddset(&mask, signum);
+
+  if (pthread_sigmask(SIG_BLOCK, &mask, NULL) == -1)
+    throw std::logic_error("Could not block signal: " + 
std::string(std::strerror(errno)));
+}
+
+void
+SignalHandler::set_unblock(unsigned int signum) {
+  if (signum >= HIGHEST_SIGNAL)
+    throw std::logic_error("SignalHandler::set_unblock(...) received invalid 
signal value.");
+
+  sigset_t mask;
+
+  sigemptyset(&mask);
+  sigaddset(&mask, signum);
+
+  if (pthread_sigmask(SIG_UNBLOCK, &mask, NULL) == -1)
+    throw std::logic_error("Could not unblock signal: " + 
std::string(std::strerror(errno)));
+}
+
+void
 SignalHandler::set_sigaction_handler(unsigned int signum, handler_slot slot) {
   if (signum >= HIGHEST_SIGNAL)
     throw std::logic_error("SignalHandler::set_handler(...) received invalid 
signal value.");
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rtorrent-0.16.14/src/signal_handler.h 
new/rtorrent-0.16.15/src/signal_handler.h
--- old/rtorrent-0.16.14/src/signal_handler.h   2026-06-14 10:04:12.000000000 
+0200
+++ new/rtorrent-0.16.15/src/signal_handler.h   2026-06-22 11:01:51.000000000 
+0200
@@ -1,37 +1,3 @@
-// rTorrent - BitTorrent client
-// Copyright (C) 2005-2011, Jari Sundell
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-// 
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-// 
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-//
-// In addition, as a special exception, the copyright holders give
-// permission to link the code of portions of this program with the
-// OpenSSL library under certain conditions as described in each
-// individual source file, and distribute linked combinations
-// including the two.
-//
-// You must obey the GNU General Public License in all respects for
-// all of the code used other than OpenSSL.  If you modify file(s)
-// with this exception, you may extend this exception to your version
-// of the file(s), but you are not obligated to do so.  If you do not
-// wish to do so, delete this exception statement from your version.
-// If you delete this exception statement from all source files in the
-// program, then also delete it here.
-//
-// Contact:  Jari Sundell <[email protected]>
-
-
 #ifndef RTORRENT_SIGNAL_HANDLER_H
 #define RTORRENT_SIGNAL_HANDLER_H
 
@@ -56,6 +22,9 @@
   static void         set_ignore(unsigned int signum);
   static void         set_handler(unsigned int signum, slot_void slot);
 
+  static void         set_block(unsigned int signum);
+  static void         set_unblock(unsigned int signum);
+
   static void         set_sigaction_handler(unsigned int signum, handler_slot 
slot);
 
   static const char*  as_string(unsigned int signum);

Reply via email to