diff --git a/libtorrent/src/assert.cpp b/libtorrent/src/assert.cpp index aa048e444..26307a95b 100644 --- a/libtorrent/src/assert.cpp +++ b/libtorrent/src/assert.cpp @@ -30,6 +30,12 @@ POSSIBILITY OF SUCH DAMAGE. */ +#ifdef TORRENT_DEBUG + +#ifdef __APPLE__ +#include +#endif + #ifdef __GNUC__ #include @@ -40,10 +46,27 @@ POSSIBILITY OF SUCH DAMAGE. std::string demangle(char const* name) { // in case this string comes + // this is needed on linux char const* start = strchr(name, '('); - if (start != 0) ++start; - else start = name; + if (start != 0) + { + ++start; + } + else + { + // this is needed on macos x + start = strstr(name, "0x"); + if (start != 0) + { + start = strchr(start, ' '); + if (start != 0) ++start; + else start = name; + } + else start = name; + } + char const* end = strchr(start, '+'); + if (end) while (*(end-1) == ' ') --end; std::string in; if (end == 0) in.assign(start); @@ -60,13 +83,32 @@ std::string demangle(char const* name) #endif -#ifdef TORRENT_DEBUG - #include #include #include -#if defined __linux__ && defined __GNUC__ + +// execinfo.h is available in the MacOS X 10.5 SDK. +#if (defined __linux__ || (defined __APPLE__ && MAC_OS_X_VERSION_MIN_REQUIRED >= 1050)) #include + +void print_backtrace(char const* label) +{ + void* stack[50]; + int size = backtrace(stack, 50); + char** symbols = backtrace_symbols(stack, size); + + fprintf(stderr, "%s\n", label); + for (int i = 1; i < size; ++i) + { + fprintf(stderr, "%d: %s\n", i, demangle(symbols[i]).c_str()); + } + + free(symbols); +} +#else + +void print_backtrace(char const* label) {} + #endif void assert_fail(char const* expr, int line, char const* file, char const* function) @@ -78,21 +120,10 @@ void assert_fail(char const* expr, int line, char const* file, char const* funct "file: '%s'\n" "line: %d\n" "function: %s\n" - "expression: %s\n" - "stack:\n", file, line, function, expr); + "expression: %s\n", file, line, function, expr); -#if defined __linux__ && defined __GNUC__ - void* stack[50]; - int size = backtrace(stack, 50); - char** symbols = backtrace_symbols(stack, size); + print_backtrace("stack:"); - for (int i = 0; i < size; ++i) - { - fprintf(stderr, "%d: %s\n", i, demangle(symbols[i]).c_str()); - } - - free(symbols); -#endif // send SIGINT to the current process // to break into the debugger raise(SIGINT); diff --git a/libtorrent/src/http_connection.cpp b/libtorrent/src/http_connection.cpp index b8251de95..8f9104548 100644 --- a/libtorrent/src/http_connection.cpp +++ b/libtorrent/src/http_connection.cpp @@ -249,6 +249,7 @@ void http_connection::close() { error_code ec; m_timer.cancel(ec); + m_resolver.cancel(); m_limiter_timer.cancel(ec); m_sock.close(ec); m_hostname.clear(); diff --git a/libtorrent/src/kademlia/dht_tracker.cpp b/libtorrent/src/kademlia/dht_tracker.cpp index 0cd2a9220..485471555 100644 --- a/libtorrent/src/kademlia/dht_tracker.cpp +++ b/libtorrent/src/kademlia/dht_tracker.cpp @@ -304,20 +304,20 @@ namespace libtorrent { namespace dht first = false; pc << "\n\n ***** starting log at " << time_now_string() << " *****\n\n" << "minute:active nodes:passive nodes" - ":ping replies sent:ping queries recvd:ping" - ":ping replies sent:ping queries recvd:ping" + ":ping replies sent:ping queries recvd" + ":ping replies bytes sent:ping queries bytes recvd" + ":find_node replies sent:find_node queries recv" ":find_node replies bytes sent:find_node queries bytes recv" - ":find_node replies bytes sent:find_node queries bytes recv" - ":get_peers replies sent:get_peers queries recvd:get_peers" + ":get_peers replies sent:get_peers queries recvd" ":get_peers replies bytes sent:get_peers queries bytes recv" - ":announce_peer replies sent:announce_peer queries recvd:announce_peer" + ":announce_peer replies sent:announce_peer queries recvd" ":announce_peer replies bytes sent:announce_peer queries bytes recv" - ":error replies sent:error queries recvd:error" + ":error replies sent:error queries recvd" ":error replies bytes sent:error queries bytes recv" ":num torrents:num peers:announces per min" ":failed announces per min:total msgs per min" ":ut msgs per min:lt msgs per min:mp msgs per min" - ":gr msgs per min:bytes in per sec:bytes out per sec" + ":gr msgs per min:mo msgs per min:bytes in per sec:bytes out per sec" ":queries out bytes per sec\n\n"; } diff --git a/libtorrent/src/natpmp.cpp b/libtorrent/src/natpmp.cpp index 67c4ae3c5..753d2c7df 100644 --- a/libtorrent/src/natpmp.cpp +++ b/libtorrent/src/natpmp.cpp @@ -58,6 +58,7 @@ natpmp::natpmp(io_service& ios, address const& listen_interface, portmap_callbac , m_refresh_timer(ios) , m_next_refresh(-1) , m_disabled(false) + , m_abort(false) { #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) m_log.open("natpmp.log", std::ios::in | std::ios::out | std::ios::trunc); @@ -287,13 +288,18 @@ void natpmp::send_map_request(int i) error_code ec; m_socket.send_to(asio::buffer(buf, 12), m_nat_endpoint, 0, ec); - // linear back-off instead of exponential if (m_abort) { + // when we're shutting down, ignore the + // responses and just remove all mappings + // immediately + m_currently_mapping = -1; + m.action = mapping_t::action_none; try_next_mapping(i); } else { + // linear back-off instead of exponential ++m_retry_count; m_send_timer.expires_from_now(milliseconds(250 * m_retry_count), ec); m_send_timer.async_wait(bind(&natpmp::resend_request, self(), i, _1)); diff --git a/libtorrent/src/torrent.cpp b/libtorrent/src/torrent.cpp index 311cd20d8..4ee05d59d 100755 --- a/libtorrent/src/torrent.cpp +++ b/libtorrent/src/torrent.cpp @@ -2223,6 +2223,8 @@ namespace libtorrent (*m_ses.m_logger) << time_now_string() << " completed resolve proxy hostname for: " << url << "\n"; #endif + if (m_abort) return; + if (e || host == tcp::resolver::iterator()) { if (m_ses.m_alerts.should_post()) @@ -2282,6 +2284,8 @@ namespace libtorrent (*m_ses.m_logger) << time_now_string() << " completed resolve: " << url << "\n"; #endif + if (m_abort) return; + std::set::iterator i = m_resolving_web_seeds.find(url); if (i != m_resolving_web_seeds.end()) m_resolving_web_seeds.erase(i); @@ -2425,6 +2429,8 @@ namespace libtorrent m_resolving_country = false; + if (m_abort) return; + // must be ordered in increasing order static const country_entry country_map[] = { diff --git a/libtorrent/src/udp_socket.cpp b/libtorrent/src/udp_socket.cpp index 8ffbe2ed8..c501be20b 100644 --- a/libtorrent/src/udp_socket.cpp +++ b/libtorrent/src/udp_socket.cpp @@ -45,7 +45,9 @@ udp_socket::udp_socket(asio::io_service& ios, udp_socket::callback_t const& c void udp_socket::send(udp::endpoint const& ep, char const* p, int len, error_code& ec) { CHECK_MAGIC; - TORRENT_ASSERT(m_ipv4_sock.is_open()); + // if the sockets are closed, the udp_socket is closing too + if (!m_ipv4_sock.is_open() && !m_ipv6_sock.is_open()) return; + if (m_tunnel_packets) { // send udp packets through SOCKS5 server @@ -74,8 +76,8 @@ void udp_socket::on_read(udp::socket* s, error_code const& e, std::size_t bytes_ // "this" may be destructed in the callback // that's why we need to unlock callback_t tmp = m_callback; - l.unlock(); m_callback.clear(); + l.unlock(); } return; } @@ -105,7 +107,17 @@ void udp_socket::on_read(udp::socket* s, error_code const& e, std::size_t bytes_ && e != asio::error::connection_refused && e != asio::error::connection_aborted && e != asio::error::message_size) + { + if (m_outstanding == 0) + { + // "this" may be destructed in the callback + // that's why we need to unlock + callback_t tmp = m_callback; + m_callback.clear(); + l.unlock(); + } return; + } if (s == &m_ipv4_sock) s->async_receive_from(asio::buffer(m_v4_buf, sizeof(m_v4_buf)) @@ -239,6 +251,7 @@ void udp_socket::close() m_ipv4_sock.close(ec); m_ipv6_sock.close(ec); m_socks5_sock.close(ec); + m_resolver.cancel(); if (m_connection_ticket >= 0) { m_cc.done(m_connection_ticket);