diff --git a/Jamfile b/Jamfile index a51a9d65b..37c82cdb9 100644 --- a/Jamfile +++ b/Jamfile @@ -519,12 +519,12 @@ variant test_release : release variant test_debug : debug : on full shared - on on multi on + on multi on ; variant test_barebones : debug : off off off off shared off off - on on multi on + on multi on ; variant test_arm : debug : off off off off diff --git a/appveyor.yml b/appveyor.yml index bb3ec7b7d..436a3887f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -88,7 +88,7 @@ build_script: # simulations - cd %ROOT_DIRECTORY%\simulation - if defined sim ( - b2.exe --hash openssl-version=pre1.1 warnings-as-errors=on -j2 %compiler% address-model=%model% picker-debugging=on invariant-checks=full variant=%variant% deprecated-functions=off %linkflags% %include% link=shared crypto=built-in testing.execute=off + b2.exe --hash openssl-version=pre1.1 warnings-as-errors=on -j2 %compiler% address-model=%model% debug-iterators=off picker-debugging=on invariant-checks=full test_debug %linkflags% %include% boost-link=default link=static crypto=built-in define=BOOST_ASIO_DISABLE_IOCP testing.execute=off ) test_script: @@ -107,7 +107,9 @@ test_script: # specifiers when debug iterators are enabled. Specifically, constructors that # allocate memory are still marked as noexcept. That results in program # termination +# the IOCP backend in asio appears to have an issue where it hangs under +# certain unexpected terminations (through exceptions) - cd %ROOT_DIRECTORY%\simulation - if defined sim ( - b2.exe --hash openssl-version=pre1.1 warnings-as-errors=on -j2 %compiler% address-model=%model% debug-iterators=off picker-debugging=on invariant-checks=full test_debug %linkflags% %include% boost-link=default link=static crypto=built-in + b2.exe --hash openssl-version=pre1.1 warnings-as-errors=on -j2 %compiler% address-model=%model% debug-iterators=off picker-debugging=on invariant-checks=full test_debug %linkflags% %include% boost-link=default link=static crypto=built-in define=BOOST_ASIO_DISABLE_IOCP ) diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp index 88f33985f..6b5a036a1 100644 --- a/include/libtorrent/aux_/session_impl.hpp +++ b/include/libtorrent/aux_/session_impl.hpp @@ -1261,7 +1261,7 @@ namespace aux { #ifndef TORRENT_DISABLE_LOGGING bool should_log() const override; - void session_log(char const* fmt, ...) const override TORRENT_FORMAT(2,3); + void session_log(char const* fmt, ...) const noexcept override TORRENT_FORMAT(2,3); #endif #ifndef TORRENT_DISABLE_EXTENSIONS @@ -1314,7 +1314,7 @@ namespace aux { , error_code const& ec, const std::string& str , seconds32 retry_interval) override; bool should_log() const override; - void debug_log(const char* fmt, ...) const override TORRENT_FORMAT(2,3); + void debug_log(const char* fmt, ...) const noexcept override TORRENT_FORMAT(2,3); session_interface& m_ses; private: // explicitly disallow assignment, to silence msvc warning diff --git a/include/libtorrent/disk_io_thread.hpp b/include/libtorrent/disk_io_thread.hpp index 798d5f974..c9711dbb3 100644 --- a/include/libtorrent/disk_io_thread.hpp +++ b/include/libtorrent/disk_io_thread.hpp @@ -286,7 +286,9 @@ namespace aux { , buffer_allocator_interface { disk_io_thread(io_service& ios, counters& cnt); +#if TORRENT_USE_ASSERTS ~disk_io_thread(); +#endif void set_settings(settings_pack const* sett); diff --git a/include/libtorrent/packet_pool.hpp b/include/libtorrent/packet_pool.hpp index aab9c6f87..4900db441 100644 --- a/include/libtorrent/packet_pool.hpp +++ b/include/libtorrent/packet_pool.hpp @@ -160,6 +160,16 @@ namespace libtorrent { // can handle common cases of packet size by 3 pools struct TORRENT_EXTRA_EXPORT packet_pool : private single_threaded { + // there's a bug in GCC where allocating these in + // member initializer expressions won't propagate exceptions. + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80683 + packet_pool() + : m_syn_slab(TORRENT_UTP_HEADER) + , m_mtu_floor_slab(mtu_floor_size) + , m_mtu_ceiling_slab(mtu_ceiling_size) + {} + packet_pool(packet_pool&&) = default; + packet_ptr acquire(int const allocate) { TORRENT_ASSERT(is_single_thread()); @@ -202,9 +212,9 @@ namespace libtorrent { } static int const mtu_floor_size = TORRENT_INET_MIN_MTU - TORRENT_IPV4_HEADER - TORRENT_UDP_HEADER; static int const mtu_ceiling_size = TORRENT_ETHERNET_MTU - TORRENT_IPV4_HEADER - TORRENT_UDP_HEADER; - packet_slab m_syn_slab{ TORRENT_UTP_HEADER }; - packet_slab m_mtu_floor_slab{ mtu_floor_size }; - packet_slab m_mtu_ceiling_slab{ mtu_ceiling_size }; + packet_slab m_syn_slab; + packet_slab m_mtu_floor_slab; + packet_slab m_mtu_ceiling_slab; }; } diff --git a/include/libtorrent/peer_connection.hpp b/include/libtorrent/peer_connection.hpp index c4dc8f829..4b154d7b6 100644 --- a/include/libtorrent/peer_connection.hpp +++ b/include/libtorrent/peer_connection.hpp @@ -526,9 +526,9 @@ namespace aux { #ifndef TORRENT_DISABLE_LOGGING bool should_log(peer_log_alert::direction_t direction) const override; void peer_log(peer_log_alert::direction_t direction - , char const* event, char const* fmt, ...) const override TORRENT_FORMAT(4,5); + , char const* event, char const* fmt, ...) const noexcept override TORRENT_FORMAT(4,5); void peer_log(peer_log_alert::direction_t direction - , char const* event) const; + , char const* event) const noexcept; time_point m_connect_time; time_point m_bitfield_time; diff --git a/include/libtorrent/peer_connection_interface.hpp b/include/libtorrent/peer_connection_interface.hpp index 03b692194..45b61681b 100644 --- a/include/libtorrent/peer_connection_interface.hpp +++ b/include/libtorrent/peer_connection_interface.hpp @@ -65,7 +65,7 @@ namespace libtorrent { #ifndef TORRENT_DISABLE_LOGGING virtual bool should_log(peer_log_alert::direction_t direction) const = 0; virtual void peer_log(peer_log_alert::direction_t direction - , char const* event, char const* fmt = "", ...) const TORRENT_FORMAT(4,5) = 0; + , char const* event, char const* fmt = "", ...) const noexcept TORRENT_FORMAT(4,5) = 0; #endif protected: ~peer_connection_interface() {} diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index eecb546f8..9af5ebc16 100644 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -1023,7 +1023,7 @@ namespace libtorrent { // LOGGING #ifndef TORRENT_DISABLE_LOGGING bool should_log() const override; - void debug_log(const char* fmt, ...) const override TORRENT_FORMAT(2,3); + void debug_log(const char* fmt, ...) const noexcept override TORRENT_FORMAT(2,3); void log_to_all_peers(char const* message); time_point m_dht_start_time; diff --git a/include/libtorrent/tracker_manager.hpp b/include/libtorrent/tracker_manager.hpp index 353eecf67..2f353bf24 100644 --- a/include/libtorrent/tracker_manager.hpp +++ b/include/libtorrent/tracker_manager.hpp @@ -249,7 +249,7 @@ namespace libtorrent { #ifndef TORRENT_DISABLE_LOGGING virtual bool should_log() const = 0; - virtual void debug_log(const char* fmt, ...) const TORRENT_FORMAT(2,3) = 0; + virtual void debug_log(const char* fmt, ...) const noexcept TORRENT_FORMAT(2,3) = 0; #endif }; diff --git a/simulation/Jamfile b/simulation/Jamfile index 96c4eba99..135dbfb25 100644 --- a/simulation/Jamfile +++ b/simulation/Jamfile @@ -51,8 +51,6 @@ alias libtorrent-sims : [ run test_fast_extensions.cpp ] [ run test_file_pool.cpp ] [ run test_save_resume.cpp ] + [ run test_error_handling.cpp ] ; -run test_error_handling.cpp ; -explicit test_error_handling ; - diff --git a/simulation/test_error_handling.cpp b/simulation/test_error_handling.cpp index a5661b87c..1538479f4 100644 --- a/simulation/test_error_handling.cpp +++ b/simulation/test_error_handling.cpp @@ -51,6 +51,10 @@ POSSIBILITY OF SUCH DAMAGE. using namespace sim; +#if defined _MSC_VER && _ITERATOR_DEBUG_LEVEL > 0 +// https://developercommunity.visualstudio.com/content/problem/140200/c-stl-stdvector-constructor-declared-with-noexcept.html +#error "msvc's standard library does not support bad_alloc with debug iterators. This test only works with debug iterators disabled on msvc. _ITERATOR_DEBUG_LEVEL=0" +#endif std::string make_ep_string(char const* address, bool const is_v6 , char const* port) @@ -105,7 +109,7 @@ void run_test(HandleAlerts const& on_alert, Test const& test) // only monitor alerts for session 0 (the downloader) print_alerts(*ses[0], [=](lt::session& ses, lt::alert const* a) { - if (auto ta = alert_cast(a)) + if (auto ta = alert_cast(a)) { ta->handle.connect_peer(lt::tcp::endpoint(peer1, 6881)); } @@ -149,6 +153,22 @@ void* operator new(std::size_t sz) { char stack[10000]; print_backtrace(stack, sizeof(stack), 40, nullptr); +#ifdef _MSC_VER + // this is a bit unfortunate. Some MSVC standard containers really don't move + // with noexcept, by actually allocating memory (i.e. it's not just a matter + // of accidentally missing noexcept specifiers). The heterogeneous queue used + // by the alert manager requires alerts to be noexcept move constructable and + // move assignable, which they claim to be, even though on MSVC some of them + // aren't. Things will improve in C++17 and it doesn't seem worth the trouble + // to make the heterogeneous queue support throwing moves, nor to replace all + // standard types with variants that can move noexcept. + if (std::strstr(stack, " libtorrent::entry::operator= ") != nullptr + || std::strstr(stack, " libtorrent::aux::noexcept_movable 0) break; } + + // if this fails, we need to raise the limit in the loop above + TEST_CHECK(g_alloc_counter > 0); + + // we don't want any part of the actual test framework to suffer from failed + // allocations, so bump the counter + g_alloc_counter = 1000000; } diff --git a/src/block_cache.cpp b/src/block_cache.cpp index 82e72ac89..4b7eeb4ee 100644 --- a/src/block_cache.cpp +++ b/src/block_cache.cpp @@ -329,7 +329,6 @@ cached_piece_entry::~cached_piece_entry() { for (int i = 0; i < blocks_in_piece; ++i) { - TORRENT_ASSERT(blocks[i].buf == nullptr); TORRENT_ASSERT(!blocks[i].pending); TORRENT_ASSERT(blocks[i].refcount == 0); TORRENT_ASSERT(blocks[i].hashing_count == 0); diff --git a/src/disk_io_thread.cpp b/src/disk_io_thread.cpp index f3346df4c..27d62fa05 100644 --- a/src/disk_io_thread.cpp +++ b/src/disk_io_thread.cpp @@ -227,6 +227,9 @@ constexpr disk_job_flags_t disk_interface::cache_hit; TORRENT_ASSERT(storage); if (m_free_slots.empty()) { + // make sure there's always space in here to add another free slot. + // stopping a torrent should never fail because it needs to allocate memory + m_free_slots.reserve(m_torrents.size() + 1); storage_index_t const idx = m_torrents.end_index(); m_torrents.emplace_back(std::move(storage)); m_torrents.back()->set_storage_index(idx); @@ -251,21 +254,15 @@ constexpr disk_job_flags_t disk_interface::cache_hit; } } +#if TORRENT_USE_ASSERTS disk_io_thread::~disk_io_thread() { DLOG("destructing disk_io_thread\n"); -#if TORRENT_USE_ASSERTS - // by now, all pieces should have been evicted - auto pieces = m_disk_cache.all_pieces(); - TORRENT_ASSERT(pieces.first == pieces.second); -#endif - TORRENT_ASSERT(m_magic == 0x1337); -#if TORRENT_USE_ASSERTS m_magic = 0xdead; -#endif } +#endif void disk_io_thread::abort(bool const wait) { diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index e1c7f98cd..de8f87840 100644 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -182,6 +182,11 @@ namespace libtorrent { , print_endpoint(local_ep).c_str()); } #endif + + // this counter should not be incremeneted until we know constructing this + // peer object can't fail anymore + if (m_connecting && t) t->inc_num_connecting(m_peer_info); + #if TORRENT_USE_ASSERTS piece_failed = false; m_in_constructor = false; @@ -372,8 +377,6 @@ namespace libtorrent { // if this is an incoming connection, we're done here if (!m_connecting) return; - if (m_connecting && t) t->inc_num_connecting(m_peer_info); - #ifndef TORRENT_DISABLE_LOGGING if (should_log(peer_log_alert::outgoing)) { @@ -529,14 +532,14 @@ namespace libtorrent { } void peer_connection::peer_log(peer_log_alert::direction_t direction - , char const* event) const + , char const* event) const noexcept { peer_log(direction, event, ""); } TORRENT_FORMAT(4,5) void peer_connection::peer_log(peer_log_alert::direction_t direction - , char const* event, char const* fmt, ...) const + , char const* event, char const* fmt, ...) const noexcept try { TORRENT_ASSERT(is_single_thread()); @@ -555,6 +558,7 @@ namespace libtorrent { va_end(v); } + catch (std::exception const&) {} #endif #ifndef TORRENT_DISABLE_EXTENSIONS @@ -797,8 +801,6 @@ namespace libtorrent { // INVARIANT_CHECK; TORRENT_ASSERT(!m_in_constructor); - TORRENT_ASSERT(m_disconnecting); - TORRENT_ASSERT(m_disconnect_started); TORRENT_ASSERT(!m_destructed); #if TORRENT_USE_ASSERTS m_destructed = true; @@ -836,7 +838,6 @@ namespace libtorrent { TORRENT_ASSERT(t || !m_connecting); // we should really have dealt with this already - TORRENT_ASSERT(!m_connecting); if (m_connecting) { m_counters.inc_stats_counter(counters::num_peers_half_open, -1); @@ -853,11 +854,6 @@ namespace libtorrent { #endif TORRENT_ASSERT(m_request_queue.empty()); TORRENT_ASSERT(m_download_queue.empty()); - -#if TORRENT_USE_ASSERTS - if (m_peer_info) - TORRENT_ASSERT(m_peer_info->connection == nullptr); -#endif } bool peer_connection::on_parole() const @@ -4385,7 +4381,7 @@ namespace libtorrent { m_queued_time_critical = 0; #if TORRENT_USE_INVARIANT_CHECKS - check_invariant(); + try { check_invariant(); } catch (std::exception const&) {} #endif t->remove_peer(self()); @@ -6326,10 +6322,6 @@ namespace libtorrent { TORRENT_ASSERT(m_request_queue.empty()); TORRENT_ASSERT(m_disconnect_started); } - else if (!m_in_constructor) - { - TORRENT_ASSERT(m_ses.has_peer(this)); - } TORRENT_ASSERT(m_outstanding_bytes >= 0); if (t && t->valid_metadata() && !m_disconnecting) diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 9b12537e3..fa57fb505 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -882,12 +882,13 @@ namespace aux { session_log(" aborting all connections (%d)", int(m_connections.size())); #endif // abort all connections - // keep in mind that connections that are not associated with a torrent - // will remove its entry from m_connections immediately, which means we - // can't iterate over it here - auto conns = m_connections; - for (auto const& p : conns) + for (connection_map::iterator i = m_connections.begin(); + i != m_connections.end();) + { + peer_connection* p = (*i).get(); + ++i; p->disconnect(errors::stopping_torrent, operation_t::bittorrent); + } // close the listen sockets for (auto const& l : m_listen_sockets) @@ -4533,7 +4534,7 @@ namespace { } TORRENT_FORMAT(2,3) - void session_impl::session_log(char const* fmt, ...) const + void session_impl::session_log(char const* fmt, ...) const noexcept try { if (!m_alerts.should_post()) return; @@ -4542,6 +4543,7 @@ namespace { m_alerts.emplace_alert(fmt, v); va_end(v); } + catch (std::exception const&) {} #endif void session_impl::get_torrent_status(std::vector* ret @@ -7147,7 +7149,7 @@ namespace { return m_ses.alerts().should_post(); } - void tracker_logger::debug_log(const char* fmt, ...) const + void tracker_logger::debug_log(const char* fmt, ...) const noexcept try { if (!m_ses.alerts().should_post()) return; @@ -7156,5 +7158,6 @@ namespace { m_ses.alerts().emplace_alert(fmt, v); va_end(v); } + catch (std::exception const&) {} #endif // TORRENT_DISABLE_LOGGING }} diff --git a/src/torrent.cpp b/src/torrent.cpp index a9505d927..d56e2de77 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -4361,8 +4361,23 @@ namespace libtorrent { // the torrent object from there if (m_storage) { - m_ses.disk_thread().async_stop_torrent(m_storage - , std::bind(&torrent::on_torrent_aborted, shared_from_this())); + try { + m_ses.disk_thread().async_stop_torrent(m_storage + , std::bind(&torrent::on_torrent_aborted, shared_from_this())); + } + catch (std::exception const& e) + { + TORRENT_UNUSED(e); + m_storage.reset(); +#ifndef TORRENT_DISABLE_LOGGING + debug_log("Failed to flush disk cache: %s", e.what()); +#endif + // clients may rely on this alert to be posted, so it's probably a + // good idea to post it here, even though we failed + // TODO: 3 should this alert have an error code in it? + if (alerts().should_post()) + alerts().emplace_alert(get_handle()); + } } else { @@ -4401,6 +4416,10 @@ namespace libtorrent { // have been destructed if (m_peer_list) m_peer_list->clear(); m_connections.clear(); + m_peers_to_disconnect.clear(); + m_num_uploads = 0; + m_num_connecting = 0; + m_num_connecting_seeds = 0; } void torrent::set_super_seeding(bool on) @@ -6877,22 +6896,7 @@ namespace libtorrent { peers_erased(st.erased); m_peers_to_disconnect.reserve(m_connections.size() + 1); - - TORRENT_ASSERT(sorted_find(m_connections, p) == m_connections.end()); - TORRENT_ASSERT(m_iterating_connections == 0); - sorted_insert(m_connections, p); - update_want_peers(); - update_want_tick(); - - if (p->peer_info_struct() && p->peer_info_struct()->seed) - { - TORRENT_ASSERT(m_num_seeds < 0xffff); - ++m_num_seeds; - } - -#ifndef TORRENT_DISABLE_LOGGING - debug_log("incoming peer (%d)", num_peers()); -#endif + m_connections.reserve(m_connections.size() + 1); #if TORRENT_USE_ASSERTS error_code ec; @@ -6956,13 +6960,33 @@ namespace libtorrent { if (m_share_mode) recalc_share_mode(); + // once we add the peer to our m_connections list, we can't throw an + // exception. That will end up violating an invariant between the session, + // torrent and peers + TORRENT_ASSERT(sorted_find(m_connections, p) == m_connections.end()); + TORRENT_ASSERT(m_iterating_connections == 0); + sorted_insert(m_connections, p); + update_want_peers(); + update_want_tick(); + + if (p->peer_info_struct() && p->peer_info_struct()->seed) + { + TORRENT_ASSERT(m_num_seeds < 0xffff); + ++m_num_seeds; + } + #ifndef TORRENT_DISABLE_LOGGING - if (should_log()) + debug_log("incoming peer (%d)", num_peers()); +#endif + +#ifndef TORRENT_DISABLE_LOGGING + if (should_log()) try { debug_log("ATTACHED CONNECTION \"%s\" connections: %d limit: %d" , print_endpoint(p->remote()).c_str(), num_peers() , m_max_connections); } + catch (std::exception const&) {} #endif return true; @@ -7775,7 +7799,7 @@ namespace libtorrent { TORRENT_ASSERT(is_single_thread()); // this fires during disconnecting peers -// if (is_paused()) TORRENT_ASSERT(num_peers() == 0 || m_graceful_pause_mode); + if (is_paused()) TORRENT_ASSERT(num_peers() == 0 || m_graceful_pause_mode); int seeds = 0; int num_uploads = 0; @@ -7784,10 +7808,6 @@ namespace libtorrent { std::map num_requests; for (peer_connection const* peer : *this) { -#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS - // make sure this peer is not a dangling pointer - TORRENT_ASSERT(m_ses.has_peer(peer)); -#endif peer_connection const& p = *peer; if (p.is_connecting()) ++num_connecting; @@ -7813,16 +7833,19 @@ namespace libtorrent { if (associated_torrent != this && associated_torrent != nullptr) TORRENT_ASSERT_FAIL(); } - TORRENT_ASSERT(num_uploads == int(m_num_uploads)); - TORRENT_ASSERT(seeds == int(m_num_seeds)); - TORRENT_ASSERT(num_connecting == int(m_num_connecting)); - TORRENT_ASSERT(num_connecting_seeds == int(m_num_connecting_seeds)); - TORRENT_ASSERT(int(m_num_uploads) <= num_peers()); - TORRENT_ASSERT(int(m_num_seeds) <= num_peers()); - TORRENT_ASSERT(int(m_num_connecting) <= num_peers()); - TORRENT_ASSERT(int(m_num_connecting_seeds) <= num_peers()); - TORRENT_ASSERT(int(m_num_connecting) + int(m_num_seeds) >= int(m_num_connecting_seeds)); - TORRENT_ASSERT(int(m_num_connecting) + int(m_num_seeds) - int(m_num_connecting_seeds) <= num_peers()); + TORRENT_ASSERT_VAL(num_uploads == int(m_num_uploads), int(m_num_uploads) - num_uploads); + TORRENT_ASSERT_VAL(seeds == int(m_num_seeds), int(m_num_seeds) - seeds); + TORRENT_ASSERT_VAL(num_connecting == int(m_num_connecting), int(m_num_connecting) - num_connecting); + TORRENT_ASSERT_VAL(num_connecting_seeds == int(m_num_connecting_seeds) + , int(m_num_connecting_seeds) - num_connecting_seeds); + TORRENT_ASSERT_VAL(int(m_num_uploads) <= num_peers(), m_num_uploads - num_peers()); + TORRENT_ASSERT_VAL(int(m_num_seeds) <= num_peers(), m_num_seeds - num_peers()); + TORRENT_ASSERT_VAL(int(m_num_connecting) <= num_peers(), int(m_num_connecting) - num_peers()); + TORRENT_ASSERT_VAL(int(m_num_connecting_seeds) <= num_peers(), int(m_num_connecting_seeds) - num_peers()); + TORRENT_ASSERT_VAL(int(m_num_connecting) + int(m_num_seeds) >= int(m_num_connecting_seeds) + , int(m_num_connecting_seeds) - (int(m_num_connecting) + int(m_num_seeds))); + TORRENT_ASSERT_VAL(int(m_num_connecting) + int(m_num_seeds) - int(m_num_connecting_seeds) <= num_peers() + , num_peers() - (int(m_num_connecting) + int(m_num_seeds) - int(m_num_connecting_seeds))); if (has_picker()) { @@ -10979,7 +11002,7 @@ namespace { } TORRENT_FORMAT(2,3) - void torrent::debug_log(char const* fmt, ...) const + void torrent::debug_log(char const* fmt, ...) const noexcept try { if (!alerts().should_post()) return; @@ -10989,6 +11012,7 @@ namespace { const_cast(this)->get_handle(), fmt, v); va_end(v); } + catch (std::exception const&) {} #endif } diff --git a/test/test_peer_list.cpp b/test/test_peer_list.cpp index 210b874aa..322a23bed 100644 --- a/test/test_peer_list.cpp +++ b/test/test_peer_list.cpp @@ -70,11 +70,11 @@ struct mock_peer_connection virtual ~mock_peer_connection() = default; #if !defined TORRENT_DISABLE_LOGGING - bool should_log(peer_log_alert::direction_t) const override + bool should_log(peer_log_alert::direction_t) const noexcept override { return true; } void peer_log(peer_log_alert::direction_t dir, char const* event - , char const* fmt, ...) const override + , char const* fmt, ...) const noexcept override { va_list v; va_start(v, fmt);