Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package libtorrent for openSUSE:Factory checked in at 2025-12-03 14:13:35 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/libtorrent (Old) and /work/SRC/openSUSE:Factory/.libtorrent.new.14147 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libtorrent" Wed Dec 3 14:13:35 2025 rev:26 rq:1320950 version:0.16.5 Changes: -------- --- /work/SRC/openSUSE:Factory/libtorrent/libtorrent.changes 2025-11-25 16:58:58.509407230 +0100 +++ /work/SRC/openSUSE:Factory/.libtorrent.new.14147/libtorrent.changes 2025-12-03 14:15:03.284964974 +0100 @@ -1,0 +2,7 @@ +Wed Dec 3 08:54:32 UTC 2025 - Jan Engelhardt <[email protected]> + +- Update to release 0.16.5 + * Fixes 100% CPU usage bug in *BSD kqueue event handler and UDNS + resolver. + +------------------------------------------------------------------- Old: ---- libtorrent-0.16.4.tar.gz New: ---- libtorrent-0.16.5.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libtorrent.spec ++++++ --- /var/tmp/diff_new_pack.AFdaoL/_old 2025-12-03 14:15:05.433055620 +0100 +++ /var/tmp/diff_new_pack.AFdaoL/_new 2025-12-03 14:15:05.453056464 +0100 @@ -16,9 +16,9 @@ # -%define lname libtorrent34 +%define lname libtorrent35 Name: libtorrent -Version: 0.16.4 +Version: 0.16.5 Release: 0 Summary: A BitTorrent library written in C++ License: SUSE-GPL-2.0+-with-openssl-exception ++++++ _scmsync.obsinfo ++++++ --- /var/tmp/diff_new_pack.AFdaoL/_old 2025-12-03 14:15:05.737068449 +0100 +++ /var/tmp/diff_new_pack.AFdaoL/_new 2025-12-03 14:15:05.773069968 +0100 @@ -1,5 +1,5 @@ -mtime: 1764077112 -commit: d3164130ef3fe344555fa0844bd25687f91b69ccd3b4ad054e3487e4becd159e +mtime: 1764752201 +commit: 994a38c7ddd491b1ef7906eedf9419b7f1e842e940708f20791fa05da5a20a0d url: https://src.opensuse.org/jengelh/libtorrent 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 2025-12-03 09:56:51.000000000 +0100 @@ -0,0 +1 @@ +.osc ++++++ libtorrent-0.16.4.tar.gz -> libtorrent-0.16.5.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtorrent-0.16.4/configure new/libtorrent-0.16.5/configure --- old/libtorrent-0.16.4/configure 2025-11-25 11:12:27.000000000 +0100 +++ new/libtorrent-0.16.5/configure 2025-12-02 18:15:57.000000000 +0100 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.72 for libtorrent 0.16.4. +# Generated by GNU Autoconf 2.72 for libtorrent 0.16.5. # # Report bugs to <[email protected]>. # @@ -614,8 +614,8 @@ # Identity of this package. PACKAGE_NAME='libtorrent' PACKAGE_TARNAME='libtorrent' -PACKAGE_VERSION='0.16.4' -PACKAGE_STRING='libtorrent 0.16.4' +PACKAGE_VERSION='0.16.5' +PACKAGE_STRING='libtorrent 0.16.5' PACKAGE_BUGREPORT='[email protected]' PACKAGE_URL='' @@ -1416,7 +1416,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 libtorrent 0.16.4 to adapt to many kinds of systems. +'configure' configures libtorrent 0.16.5 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1487,7 +1487,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of libtorrent 0.16.4:";; + short | recursive ) echo "Configuration of libtorrent 0.16.5:";; esac cat <<\_ACEOF @@ -1649,7 +1649,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -libtorrent configure 0.16.4 +libtorrent configure 0.16.5 generated by GNU Autoconf 2.72 Copyright (C) 2023 Free Software Foundation, Inc. @@ -2367,7 +2367,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by libtorrent $as_me 0.16.4, which was +It was created by libtorrent $as_me 0.16.5, which was generated by GNU Autoconf 2.72. Invocation command line was $ $0$ac_configure_args_raw @@ -4060,7 +4060,7 @@ # Define the identity of the package. PACKAGE='libtorrent' - VERSION='0.16.4' + VERSION='0.16.5' printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h @@ -13704,13 +13704,13 @@ -printf "%s\n" "#define PEER_NAME \"-lt1004-\"" >>confdefs.h +printf "%s\n" "#define PEER_NAME \"-lt1005-\"" >>confdefs.h -printf "%s\n" "#define PEER_VERSION \"lt\\x10\\x04\"" >>confdefs.h +printf "%s\n" "#define PEER_VERSION \"lt\\x10\\x05\"" >>confdefs.h -LIBTORRENT_CURRENT=34 +LIBTORRENT_CURRENT=35 LIBTORRENT_REVISION=0 LIBTORRENT_AGE=0 @@ -23877,7 +23877,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by libtorrent $as_me 0.16.4, which was +This file was extended by libtorrent $as_me 0.16.5, which was generated by GNU Autoconf 2.72. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -23945,7 +23945,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -libtorrent config.status 0.16.4 +libtorrent config.status 0.16.5 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/libtorrent-0.16.4/configure.ac new/libtorrent-0.16.5/configure.ac --- old/libtorrent-0.16.4/configure.ac 2025-11-25 11:12:15.000000000 +0100 +++ new/libtorrent-0.16.5/configure.ac 2025-12-02 18:15:46.000000000 +0100 @@ -1,4 +1,4 @@ -AC_INIT([[libtorrent]],[[0.16.4]],[[[email protected]]]) +AC_INIT([[libtorrent]],[[0.16.5]],[[[email protected]]]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_MACRO_DIRS([scripts]) @@ -6,10 +6,10 @@ LT_INIT([[disable-static]]) -AC_DEFINE([[PEER_NAME]], [["-lt1004-"]], [[Identifier that is part of the default peer id.]]) -AC_DEFINE([[PEER_VERSION]], [["lt\x10\x04"]], [[4 byte client and version identifier for DHT.]]) +AC_DEFINE([[PEER_NAME]], [["-lt1005-"]], [[Identifier that is part of the default peer id.]]) +AC_DEFINE([[PEER_VERSION]], [["lt\x10\x05"]], [[4 byte client and version identifier for DHT.]]) -LIBTORRENT_CURRENT=34 +LIBTORRENT_CURRENT=35 LIBTORRENT_REVISION=0 LIBTORRENT_AGE=0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtorrent-0.16.4/src/net/udns_resolver.cc new/libtorrent-0.16.5/src/net/udns_resolver.cc --- old/libtorrent-0.16.4/src/net/udns_resolver.cc 2025-11-25 11:12:15.000000000 +0100 +++ new/libtorrent-0.16.5/src/net/udns_resolver.cc 2025-12-02 18:15:46.000000000 +0100 @@ -20,6 +20,36 @@ namespace torrent { +struct UdnsQuery { + // TODO: We already use deleted. + ~UdnsQuery() { parent = nullptr; } + + void* requester{}; + std::string hostname; + int family{}; + + UdnsResolver::resolver_callback callback; + + // TODO: Verify canceled and deleted atomicity. + + UdnsResolver* parent{}; + bool canceled{}; + bool deleted{}; + ::dns_query* a4_query{}; + ::dns_query* a6_query{}; + + sin_shared_ptr result_sin; + sin6_shared_ptr result_sin6; + int error_sin{0}; + int error_sin6{0}; +}; + +class UdnsResolverInternal { +public: + static void a4_callback_wrapper(::dns_ctx *ctx, ::dns_rr_a4 *result, void *data); + static void a6_callback_wrapper(::dns_ctx *ctx, ::dns_rr_a6 *result, void *data); +}; + bool UdnsResolver::m_initialized = false; static int @@ -98,7 +128,7 @@ UdnsResolver::resolve(void* requester, const std::string& hostname, int family, resolver_callback&& callback) { assert(std::this_thread::get_id() == m_thread->thread_id()); - auto query = std::make_unique<Query>(); + auto query = std::make_unique<UdnsQuery>(); query->requester = requester; query->hostname = hostname; @@ -110,7 +140,7 @@ return; if (family == AF_INET || family == AF_UNSPEC) { - query->a4_query = ::dns_submit_a4(m_ctx, hostname.c_str(), 0, a4_callback_wrapper, query.get()); + query->a4_query = ::dns_submit_a4(m_ctx, hostname.c_str(), 0, UdnsResolverInternal::a4_callback_wrapper, query.get()); if (query->a4_query == nullptr) { LT_LOG("malformed A query : requester:%p name:%s", requester, hostname.c_str()); @@ -124,17 +154,18 @@ // query internally so we can call the callback later with a failure code. query->error_sin = EAI_NONAME; - process_timeouts(); - - auto lock = std::scoped_lock(m_mutex); - m_malformed_queries.emplace(requester, std::move(query)); + { + auto lock = std::lock_guard(m_mutex); + m_malformed_queries_unsafe.emplace(requester, std::move(query)); + } + process_timeouts(); return; } } if (family == AF_INET6 || family == AF_UNSPEC) { - query->a6_query = ::dns_submit_a6(m_ctx, hostname.c_str(), 0, a6_callback_wrapper, query.get()); + query->a6_query = ::dns_submit_a6(m_ctx, hostname.c_str(), 0, UdnsResolverInternal::a6_callback_wrapper, query.get()); // It should be impossible for dns_submit_a6 to fail if dns_submit_a4 // succeeded, but just in case, make it a hard failure. @@ -151,25 +182,28 @@ query->error_sin = EAI_NONAME; - process_timeouts(); - - auto lock = std::scoped_lock(m_mutex); - m_malformed_queries.emplace(requester, std::move(query)); + { + auto lock = std::lock_guard(m_mutex); + m_malformed_queries_unsafe.emplace(requester, std::move(query)); + } + process_timeouts(); return; } } LT_LOG("resolving : requester:%p name:%s family:%d", requester, hostname.c_str(), family); - process_timeouts(); + { + auto lock = std::lock_guard(m_mutex); + m_queries_unsafe.emplace(requester, std::move(query)); + } - auto lock = std::scoped_lock(m_mutex); - m_queries.emplace(requester, std::move(query)); + process_timeouts(); } bool -UdnsResolver::try_resolve_numeric(std::unique_ptr<Query>& query) { +UdnsResolver::try_resolve_numeric(std::unique_ptr<UdnsQuery>& query) { assert(std::this_thread::get_id() == m_thread->thread_id()); addrinfo hints{}; @@ -204,30 +238,34 @@ if (query->family != AF_UNSPEC && query->family != result->ai_family) throw internal_error("getaddrinfo returned address with unexpected family"); - auto requester = query->requester; - - auto lock = std::scoped_lock(m_mutex); - auto itr = m_queries.emplace(requester, std::move(query)); + { + auto lock = std::lock_guard(m_mutex); + process_final_result_unsafe(std::move(query)); + } - process_result(itr); return true; } void UdnsResolver::cancel(void* requester) { - auto lock = std::scoped_lock(m_mutex); + auto lock = std::lock_guard(m_mutex); - auto range = m_queries.equal_range(requester); - unsigned int query_count = std::distance(range.first, range.second); + auto cancel_fn = [](std::pair<query_map::iterator, query_map::iterator> range) { + unsigned int count = 0; - for (auto itr = range.first; itr != range.second; ++itr) - itr->second->canceled = true; + for (auto itr = range.first; itr != range.second; ++itr) { + if (itr->second->canceled) + continue; - range = m_malformed_queries.equal_range(requester); - unsigned int malformed_count = std::distance(range.first, range.second); + itr->second->canceled = true; + ++count; + } + + return count; + }; - for (auto itr = range.first; itr != range.second; ++itr) - itr->second->canceled = true; + unsigned int query_count = cancel_fn(m_queries_unsafe.equal_range(requester)); + unsigned int malformed_count = cancel_fn(m_malformed_queries_unsafe.equal_range(requester)); LT_LOG("canceled : requester:%p queries:%d malformed:%d", requester, query_count, malformed_count); } @@ -236,8 +274,9 @@ UdnsResolver::flush() { assert(std::this_thread::get_id() == m_thread->thread_id()); - auto lock = std::scoped_lock(m_mutex); - auto malformed_queries = std::move(m_malformed_queries); + // Keep lock to ensure cancel() calls do not return until after flushing is complete. + auto lock = std::lock_guard(m_mutex); + auto malformed_queries = std::move(m_malformed_queries_unsafe); for (auto& query : malformed_queries) { if (query.second->canceled) @@ -266,59 +305,27 @@ void UdnsResolver::event_error() { - // TODO: Handle error. - process_timeouts(); -} - -std::unique_ptr<UdnsResolver::Query> -UdnsResolver::erase_query(query_map::iterator itr) { - if (itr == m_queries.end()) - throw internal_error("UdnsResolver::erase_query called with invalid iterator"); - - auto query = std::move(itr->second); - m_queries.erase(itr); - - query->deleted = true; - return query; + throw internal_error("UdnsResolver::event_error() called"); } - UdnsResolver::query_map::iterator -UdnsResolver::find_query(Query* query) { - auto range = m_queries.equal_range(query->requester); +UdnsResolver::find_query_or_fail_unsafe(UdnsQuery* query) { + auto range = m_queries_unsafe.equal_range(query->requester); for (auto itr = range.first; itr != range.second; ++itr) { if (itr->second.get() == query) return itr; } - return m_queries.end(); -} - -UdnsResolver::query_map::iterator -UdnsResolver::find_malformed_query(Query* query) { - auto range = m_malformed_queries.equal_range(query->requester); - - for (auto itr = range.first; itr != range.second; ++itr) { - if (itr->second.get() == query) - return itr; - } - - return m_malformed_queries.end(); + throw internal_error("UdnsResolver::find_query_or_fail_unsafe() called with invalid query"); } +// Do not call recursively. void UdnsResolver::process_timeouts() { assert(std::this_thread::get_id() == m_thread->thread_id()); - if (m_processing_timeouts) - return; - - m_processing_timeouts = true; int timeout = ::dns_timeouts(m_ctx, -1, 0); - m_processing_timeouts = false; - - // TODO: We shouldn't remove from error events. if (timeout == -1) { this_thread::poll()->remove_read(this); @@ -342,21 +349,18 @@ } void -UdnsResolver::a4_callback_wrapper(struct ::dns_ctx *ctx, ::dns_rr_a4 *result, void *data) { - auto query = static_cast<UdnsResolver::Query*>(data); - auto lock = std::scoped_lock(query->parent->m_mutex); +UdnsResolverInternal::a4_callback_wrapper(::dns_ctx *ctx, ::dns_rr_a4 *result, void *data) { + auto query = static_cast<UdnsQuery*>(data); + auto lock = std::lock_guard(query->parent->m_mutex); if (query->deleted) { LT_LOG("A records received, but query was deleted : requester:%p name:%s", query->requester, query->hostname.c_str()); throw internal_error("UdnsResolver::a4_callback_wrapper called with deleted query"); } - auto itr = query->parent->find_query(static_cast<UdnsResolver::Query*>(data)); - - if (itr == query->parent->m_queries.end()) - throw internal_error("UdnsResolver::a4_callback_wrapper called with invalid query"); + auto itr = query->parent->find_query_or_fail_unsafe(query); - // TODO: Verify... + // TODO: Do we need to release a4_query? query->a4_query = nullptr; if (result == nullptr || result->dnsa4_nrr == 0) { @@ -365,33 +369,28 @@ LT_LOG("no A records received : requester:%p name:%s error:'%s'", query->requester, query->hostname.c_str(), gai_strerror(query->error_sin)); - process_result(itr); - return; - } - - query->result_sin = sin_make(); - query->result_sin->sin_addr = result->dnsa4_addr[0]; + } else { + query->result_sin = sin_make(); + query->result_sin->sin_addr = result->dnsa4_addr[0]; - LT_LOG("A records received : requester:%p name:%s nrr:%d", - query->requester, query->hostname.c_str(), result->dnsa4_nrr); + LT_LOG("A records received : requester:%p name:%s nrr:%d", + query->requester, query->hostname.c_str(), result->dnsa4_nrr); + } - process_result(itr); + UdnsResolver::process_partial_result_unsafe(itr); } void -UdnsResolver::a6_callback_wrapper(struct ::dns_ctx *ctx, ::dns_rr_a6 *result, void *data) { - auto query = static_cast<UdnsResolver::Query*>(data); - auto lock = std::scoped_lock(query->parent->m_mutex); +UdnsResolverInternal::a6_callback_wrapper(::dns_ctx *ctx, ::dns_rr_a6 *result, void *data) { + auto query = static_cast<UdnsQuery*>(data); + auto lock = std::lock_guard(query->parent->m_mutex); if (query->deleted) { LT_LOG("AAAA records received, but query was deleted : requester:%p name:%s", query->requester, query->hostname.c_str()); throw internal_error("UdnsResolver::a6_callback_wrapper called with deleted query"); } - auto itr = query->parent->find_query(query); - - if (itr == query->parent->m_queries.end()) - throw internal_error("UdnsResolver::a6_callback_wrapper called with invalid query"); + auto itr = query->parent->find_query_or_fail_unsafe(query); query->a6_query = nullptr; @@ -401,30 +400,34 @@ LT_LOG("no AAAA records received, calling back with error : requester:%p name:%s error:'%s'", query->requester, query->hostname.c_str(), gai_strerror(query->error_sin6)); - process_result(itr); - return; - } - - query->result_sin6 = sin6_make(); - query->result_sin6->sin6_addr = result->dnsa6_addr[0]; + } else { + query->result_sin6 = sin6_make(); + query->result_sin6->sin6_addr = result->dnsa6_addr[0]; - LT_LOG("AAAA records received : requester:%p name:%s nrr:%d", - query->requester, query->hostname.c_str(), result->dnsa6_nrr); + LT_LOG("AAAA records received : requester:%p name:%s nrr:%d", + query->requester, query->hostname.c_str(), result->dnsa6_nrr); + } - process_result(itr); + UdnsResolver::process_partial_result_unsafe(itr); } void -UdnsResolver::process_result(query_map::iterator itr) { - itr->second->parent->process_timeouts(); - +UdnsResolver::process_partial_result_unsafe(query_map::iterator itr) { if (itr->second->a4_query != nullptr || itr->second->a6_query != nullptr) { LT_LOG("processing results, waiting for other queries : requester:%p name:%s", itr->second->requester, itr->second->hostname.c_str()); return; } - auto query = itr->second->parent->erase_query(itr); + auto query = std::move(itr->second); + + query->deleted = true; + query->parent->m_queries_unsafe.erase(itr); + process_final_result_unsafe(std::move(query)); +} + +void +UdnsResolver::process_final_result_unsafe(std::unique_ptr<UdnsQuery>&& query) { if (query->canceled) { LT_LOG("processing results, canceled : requester:%p name:%s", query->requester, query->hostname.c_str()); return; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtorrent-0.16.4/src/net/udns_resolver.h new/libtorrent-0.16.5/src/net/udns_resolver.h --- old/libtorrent-0.16.4/src/net/udns_resolver.h 2025-11-25 11:12:15.000000000 +0100 +++ new/libtorrent-0.16.5/src/net/udns_resolver.h 2025-12-02 18:15:46.000000000 +0100 @@ -10,35 +10,17 @@ #include "torrent/utils/scheduler.h" struct dns_ctx; -struct dns_query; -struct dns_rr_a4; -struct dns_rr_a6; namespace torrent { +struct UdnsQuery; +class UdnsResolverInternal; + class UdnsResolver : public Event { public: using resolver_callback = std::function<void(sin_shared_ptr, sin6_shared_ptr, int)>; - struct Query { - void* requester{}; - std::string hostname; - int family{}; - resolver_callback callback; - - UdnsResolver* parent{}; - bool canceled{}; - bool deleted{}; - ::dns_query* a4_query{}; - ::dns_query* a6_query{}; - - sin_shared_ptr result_sin; - sin6_shared_ptr result_sin6; - int error_sin{0}; - int error_sin6{0}; - }; - - using query_map = std::multimap<void*, std::unique_ptr<Query>>; + using query_map = std::multimap<void*, std::unique_ptr<UdnsQuery>>; UdnsResolver(); ~UdnsResolver() override; @@ -63,30 +45,30 @@ void event_error() override; protected: - std::unique_ptr<Query> erase_query(query_map::iterator itr); - query_map::iterator find_query(Query* query); - query_map::iterator find_malformed_query(Query* query); + friend class UdnsResolverInternal; + + std::unique_ptr<UdnsQuery> erase_query(query_map::iterator itr); + + query_map::iterator find_query_or_fail_unsafe(UdnsQuery* query); - bool try_resolve_numeric(std::unique_ptr<Query>& query); + bool try_resolve_numeric(std::unique_ptr<UdnsQuery>& query); void process_canceled(); void process_timeouts(); - static void a4_callback_wrapper(struct ::dns_ctx *ctx, ::dns_rr_a4 *result, void *data); - static void a6_callback_wrapper(struct ::dns_ctx *ctx, ::dns_rr_a6 *result, void *data); - static void process_result(query_map::iterator itr); + static void process_partial_result_unsafe(query_map::iterator itr); + static void process_final_result_unsafe(std::unique_ptr<UdnsQuery>&& query); static bool m_initialized; utils::Thread* m_thread{}; ::dns_ctx* m_ctx{}; - bool m_processing_timeouts{}; utils::SchedulerEntry m_task_timeout; std::mutex m_mutex; - query_map m_queries; - query_map m_malformed_queries; + query_map m_queries_unsafe; + query_map m_malformed_queries_unsafe; }; } // namespace torrent diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtorrent-0.16.4/src/torrent/net/fd.cc new/libtorrent-0.16.5/src/torrent/net/fd.cc --- old/libtorrent-0.16.4/src/torrent/net/fd.cc 2025-11-25 11:12:16.000000000 +0100 +++ new/libtorrent-0.16.5/src/torrent/net/fd.cc 2025-12-02 18:15:46.000000000 +0100 @@ -174,6 +174,7 @@ return -1; } + LT_LOG_FD("fd_accept() succeeded"); return connection_fd; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtorrent-0.16.4/src/torrent/net/poll_kqueue.cc new/libtorrent-0.16.5/src/torrent/net/poll_kqueue.cc --- old/libtorrent-0.16.4/src/torrent/net/poll_kqueue.cc 2025-11-25 11:12:16.000000000 +0100 +++ new/libtorrent-0.16.5/src/torrent/net/poll_kqueue.cc 2025-12-02 18:15:46.000000000 +0100 @@ -19,6 +19,9 @@ // TODO: Optimize table memory size, and add a reference to Event for direct lookup. +#define LT_LOG(log_fmt, ...) \ + lt_log_print(LOG_CONNECTION_FD, "kqueue: " log_fmt, __VA_ARGS__); + #define LT_LOG_EVENT(log_fmt, ...) \ lt_log_print(LOG_CONNECTION_FD, "kqueue->%i : %s : " log_fmt, event->file_descriptor(), event->type_name(), __VA_ARGS__); @@ -40,6 +43,7 @@ inline uint32_t event_mask_any(int fd); inline void set_event_mask(Event* e, uint32_t m); + void flush(); void modify(torrent::Event* event, unsigned short op, short mask); int m_fd; @@ -93,16 +97,25 @@ } void +PollInternal::flush() { + if (m_changed_events == 0) + return; + + LT_LOG("flushing events : changed:%u", m_changed_events); + + if (::kevent(m_fd, m_changes.get(), m_changed_events, nullptr, 0, nullptr) == -1) + throw internal_error("PollInternal::flush() error: " + std::string(std::strerror(errno))); + + m_changed_events = 0; +} + +void PollInternal::modify(Event* event, unsigned short op, short mask) { LT_LOG_EVENT("modify event : op:%hx mask:%hx changed:%u", op, mask, m_changed_events); // Flush the changed filters to the kernel if the buffer is full. - if (m_changed_events == m_max_events) { - if (::kevent(m_fd, m_changes.get(), m_changed_events, nullptr, 0, nullptr) == -1) - throw internal_error("PollInternal::modify() error: " + std::string(std::strerror(errno))); - - m_changed_events = 0; - } + if (m_changed_events == m_max_events) + flush(); struct kevent* itr = m_changes.get() + (m_changed_events++); @@ -197,7 +210,7 @@ auto ev_itr = m_internal->m_table.begin() + itr->ident; if (ev_itr->second == nullptr) { - LT_LOG_DEBUG_IDENT("event is null, skipping : flags:%hx filter:%hx", itr->flags, itr->filter); + LT_LOG_DEBUG_IDENT("event is null, skipping : flags:%hx fflag:%hx filter:%hx", itr->flags, itr->fflags, itr->filter); continue; } @@ -259,21 +272,7 @@ m_internal->m_table[event->file_descriptor()] = PollInternal::Table::value_type(); - // No need to touch m_events as we unset the read/write/error flags in m_internal->m_events using - // remove_read/write/error. - auto last_itr = std::remove_if(m_internal->m_changes.get(), - m_internal->m_changes.get() + m_internal->m_changed_events, - [event](const struct kevent& ke) { return ke.udata == event; }); - - m_internal->m_changed_events = last_itr - m_internal->m_changes.get(); - - // Clear the event list just in case we open a new socket with the - // same fd while in the middle of calling Poll::perform. - // - // Removed. - // - // Shouldn't be needed as we unset the read/write/error flags in m_internal->m_events using - // remove_read/write/error. + m_internal->flush(); } bool diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtorrent-0.16.4/src/torrent/utils/log.cc new/libtorrent-0.16.5/src/torrent/utils/log.cc --- old/libtorrent-0.16.4/src/torrent/utils/log.cc 2025-11-25 11:12:16.000000000 +0100 +++ new/libtorrent-0.16.5/src/torrent/utils/log.cc 2025-12-02 18:15:46.000000000 +0100 @@ -308,6 +308,8 @@ // Remove from all groups, then modify all outputs. } +// TODO: Add lock for file writes. + static void log_file_write(const std::shared_ptr<std::ofstream>& outfile, const char* data, size_t length, int group) { // Add group name, data, etc as flags. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtorrent-0.16.4/src/tracker/tracker_list.cc new/libtorrent-0.16.5/src/tracker/tracker_list.cc --- old/libtorrent-0.16.4/src/tracker/tracker_list.cc 2025-11-25 11:12:16.000000000 +0100 +++ new/libtorrent-0.16.5/src/tracker/tracker_list.cc 2025-12-02 18:15:47.000000000 +0100 @@ -269,7 +269,7 @@ // TODO: Use proper flags for insert options. void TrackerList::insert_url(unsigned int group, const std::string& url, bool extra_tracker) { - TrackerWorker* worker; + TrackerWorker* worker{}; int flags = tracker::TrackerState::flag_enabled; @@ -277,6 +277,7 @@ flags |= tracker::TrackerState::flag_extra_tracker; TrackerInfo tracker_info; + tracker_info.info_hash = m_info->hash(); tracker_info.obfuscated_hash = m_info->hash_obfuscated(); tracker_info.local_id = m_info->local_id(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtorrent-0.16.4/src/tracker/tracker_list.h new/libtorrent-0.16.5/src/tracker/tracker_list.h --- old/libtorrent-0.16.4/src/tracker/tracker_list.h 2025-11-25 11:12:16.000000000 +0100 +++ new/libtorrent-0.16.5/src/tracker/tracker_list.h 2025-12-02 18:15:47.000000000 +0100 @@ -123,7 +123,7 @@ TrackerList& operator=(const TrackerList&) = delete; DownloadInfo* m_info{}; - int m_state; + int m_state{}; // TODO: Key should be part of download static info. uint32_t m_key{0}; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtorrent-0.16.4/src/tracker/tracker_worker.h new/libtorrent-0.16.5/src/tracker/tracker_worker.h --- old/libtorrent-0.16.4/src/tracker/tracker_worker.h 2025-11-25 11:12:16.000000000 +0100 +++ new/libtorrent-0.16.5/src/tracker/tracker_worker.h 2025-12-02 18:15:47.000000000 +0100 @@ -103,7 +103,7 @@ TrackerInfo m_info; - tracker::TrackerState m_state; + tracker::TrackerState m_state{}; std::string m_tracker_id; uint32_t m_group{0}; };
