From 682ceff21b11df25bbfa851c3c89a0426e3c9830 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Sun, 23 Mar 2014 07:40:43 +0000 Subject: [PATCH] improve messaging of assert caused by precondition violation --- include/libtorrent/assert.hpp | 15 ++++++++--- src/assert.cpp | 20 ++++++++++---- src/file_storage.cpp | 50 +++++++++++++++++------------------ src/session.cpp | 2 +- src/session_impl.cpp | 2 +- src/torrent_handle.cpp | 14 +++++----- 6 files changed, 61 insertions(+), 42 deletions(-) diff --git a/include/libtorrent/assert.hpp b/include/libtorrent/assert.hpp index 55b7478b9..5e0c2ca2e 100644 --- a/include/libtorrent/assert.hpp +++ b/include/libtorrent/assert.hpp @@ -53,23 +53,32 @@ extern char const* libtorrent_assert_log; #endif TORRENT_EXPORT void assert_fail(const char* expr, int line, char const* file - , char const* function, char const* val); + , char const* function, char const* val, int kind = 0); + +#define TORRENT_ASSERT_PRECOND(x) \ + do { if (x) {} else assert_fail(#x, __LINE__, __FILE__, __PRETTY_FUNCTION__, "", 1); } while (false) + +#define TORRENT_ASSERT(x) \ + do { if (x) {} else assert_fail(#x, __LINE__, __FILE__, __PRETTY_FUNCTION__, "", 0); } while (false) -#define TORRENT_ASSERT(x) do { if (x) {} else assert_fail(#x, __LINE__, __FILE__, __PRETTY_FUNCTION__, 0); } while (false) #if TORRENT_USE_IOSTREAM -#define TORRENT_ASSERT_VAL(x, y) do { if (x) {} else { std::stringstream __s__; __s__ << #y ": " << y; assert_fail(#x, __LINE__, __FILE__, __PRETTY_FUNCTION__, __s__.str().c_str()); } } while (false) +#define TORRENT_ASSERT_VAL(x, y) \ + do { if (x) {} else { std::stringstream __s__; __s__ << #y ": " << y; \ + assert_fail(#x, __LINE__, __FILE__, __PRETTY_FUNCTION__, __s__.str().c_str(), 0); } } while (false) #else #define TORRENT_ASSERT_VAL(x, y) TORRENT_ASSERT(x) #endif #else #include +#define TORRENT_ASSERT_PRECOND(x) assert(x) #define TORRENT_ASSERT(x) assert(x) #define TORRENT_ASSERT_VAL(x, y) assert(x) #endif #else // TORRENT_USE_ASSERTS +#define TORRENT_ASSERT_PRECOND(a) do {} while(false) #define TORRENT_ASSERT(a) do {} while(false) #define TORRENT_ASSERT_VAL(a, b) do {} while(false) diff --git a/src/assert.cpp b/src/assert.cpp index 4fdd19eb0..ed12ad367 100644 --- a/src/assert.cpp +++ b/src/assert.cpp @@ -215,7 +215,7 @@ boost::detail::atomic_count assert_counter(0); #endif TORRENT_EXPORT void assert_fail(char const* expr, int line, char const* file - , char const* function, char const* value) + , char const* function, char const* value, int kind) { #if TORRENT_PRODUCTION_ASSERTS // no need to flood the assert log with infinite number of asserts @@ -231,11 +231,20 @@ TORRENT_EXPORT void assert_fail(char const* expr, int line, char const* file stack[0] = '\0'; print_backtrace(stack, sizeof(stack), 0); - fprintf(out, "assertion failed. Please file a bugreport at " + char const* message = "assertion failed. Please file a bugreport at " "http://code.google.com/p/libtorrent/issues\n" "Please include the following information:\n\n" "version: " LIBTORRENT_VERSION "\n" - "%s\n" + LIBTORRENT_REVISION "\n"; + + switch (kind) + { + case 1: + message = "A precondition of a libtorrent function has been violated.\n" + "This indicates a bug in the client application using libtorrent\n"; + } + + fprintf(out, "%s\n" "file: '%s'\n" "line: %d\n" "function: %s\n" @@ -243,7 +252,7 @@ TORRENT_EXPORT void assert_fail(char const* expr, int line, char const* file "%s%s\n" "stack:\n" "%s\n" - , LIBTORRENT_REVISION, file, line, function, expr + , message, file, line, function, expr , value ? value : "", value ? "\n" : "" , stack); @@ -260,7 +269,8 @@ TORRENT_EXPORT void assert_fail(char const* expr, int line, char const* file #else -TORRENT_EXPORT void assert_fail(char const* expr, int line, char const* file, char const* function) {} +TORRENT_EXPORT void assert_fail(char const* expr, int line, char const* file + , char const* function, char const* value, int kind) {} #endif diff --git a/src/file_storage.cpp b/src/file_storage.cpp index 58aed73ee..9999821c3 100644 --- a/src/file_storage.cpp +++ b/src/file_storage.cpp @@ -55,7 +55,7 @@ namespace libtorrent int file_storage::piece_size(int index) const { - TORRENT_ASSERT(index >= 0 && index < num_pieces()); + TORRENT_ASSERT_PRECOND(index >= 0 && index < num_pieces()); if (index == num_pieces()-1) { size_type size_except_last = num_pieces() - 1; @@ -213,7 +213,7 @@ namespace libtorrent void file_storage::rename_file(int index, std::wstring const& new_filename) { - TORRENT_ASSERT(index >= 0 && index < int(m_files.size())); + TORRENT_ASSERT_PRECOND(index >= 0 && index < int(m_files.size())); std::string utf8; wchar_utf8(new_filename, utf8); m_files[index].set_name(utf8.c_str()); @@ -232,14 +232,14 @@ namespace libtorrent void file_storage::rename_file(int index, std::string const& new_filename) { - TORRENT_ASSERT(index >= 0 && index < int(m_files.size())); + TORRENT_ASSERT_PRECOND(index >= 0 && index < int(m_files.size())); m_files[index].set_name(new_filename.c_str()); update_path_index(m_files[index]); } void file_storage::rename_file_borrow(int index, char const* new_filename, int len) { - TORRENT_ASSERT(index >= 0 && index < int(m_files.size())); + TORRENT_ASSERT_PRECOND(index >= 0 && index < int(m_files.size())); m_files[index].set_name(new_filename, true, len); } @@ -303,7 +303,7 @@ namespace libtorrent std::vector file_storage::map_block(int piece, size_type offset , int size) const { - TORRENT_ASSERT(num_files() > 0); + TORRENT_ASSERT_PRECOND(num_files() > 0); std::vector ret; if (m_files.empty()) return ret; @@ -311,7 +311,7 @@ namespace libtorrent // find the file iterator and file offset internal_file_entry target; target.offset = piece * (size_type)m_piece_length + offset; - TORRENT_ASSERT(target.offset + size <= m_total_size); + TORRENT_ASSERT_PRECOND(target.offset + size <= m_total_size); TORRENT_ASSERT(!compare_file_offset(target, m_files.front())); std::vector::const_iterator file_iter = std::upper_bound( @@ -343,7 +343,7 @@ namespace libtorrent file_entry file_storage::at(int index) const { - TORRENT_ASSERT(index >= 0 && index < int(m_files.size())); + TORRENT_ASSERT_PRECOND(index >= 0 && index < int(m_files.size())); file_entry ret; internal_file_entry const& ife = m_files[index]; ret.path = file_path(index); @@ -364,8 +364,8 @@ namespace libtorrent peer_request file_storage::map_file(int file_index, size_type file_offset , int size) const { - TORRENT_ASSERT(file_index < num_files()); - TORRENT_ASSERT(file_index >= 0); + TORRENT_ASSERT_PRECOND(file_index < num_files()); + TORRENT_ASSERT_PRECOND(file_index >= 0); peer_request ret; if (file_index < 0 || file_index >= num_files()) @@ -398,8 +398,8 @@ namespace libtorrent void file_storage::add_file(std::string const& file, size_type size, int flags , std::time_t mtime, std::string const& symlink_path) { - TORRENT_ASSERT(!is_complete(file)); - TORRENT_ASSERT(size >= 0); + TORRENT_ASSERT_PRECOND(!is_complete(file)); + TORRENT_ASSERT_PRECOND(size >= 0); if (size < 0) size = 0; if (!has_parent_path(file)) { @@ -407,7 +407,7 @@ namespace libtorrent // path to the file (branch_path), which means that // all the other files need to be in the same top // directory as the first file. - TORRENT_ASSERT(m_files.empty()); + TORRENT_ASSERT_PRECOND(m_files.empty()); m_name = file; } else @@ -415,7 +415,7 @@ namespace libtorrent if (m_files.empty()) m_name = split_path(file).c_str(); } - TORRENT_ASSERT(m_name == split_path(file).c_str()); + TORRENT_ASSERT_PRECOND(m_name == split_path(file).c_str()); m_files.push_back(internal_file_entry()); internal_file_entry& e = m_files.back(); e.set_name(file.c_str()); @@ -442,14 +442,14 @@ namespace libtorrent void file_storage::add_file(file_entry const& ent, char const* filehash) { - TORRENT_ASSERT(ent.size >= 0); + TORRENT_ASSERT_PRECOND(ent.size >= 0); if (!has_parent_path(ent.path)) { // you have already added at least one file with a // path to the file (branch_path), which means that // all the other files need to be in the same top // directory as the first file. - TORRENT_ASSERT(m_files.empty()); + TORRENT_ASSERT_PRECOND(m_files.empty()); m_name = ent.path; } else @@ -490,7 +490,7 @@ namespace libtorrent std::string const& file_storage::symlink(int index) const { - TORRENT_ASSERT(index >= 0 && index < int(m_files.size())); + TORRENT_ASSERT_PRECOND(index >= 0 && index < int(m_files.size())); internal_file_entry const& fe = m_files[index]; TORRENT_ASSERT(fe.symlink_index < int(m_symlinks.size())); return m_symlinks[fe.symlink_index]; @@ -504,7 +504,7 @@ namespace libtorrent void file_storage::set_file_base(int index, size_type off) { - TORRENT_ASSERT(index >= 0 && index < int(m_files.size())); + TORRENT_ASSERT_PRECOND(index >= 0 && index < int(m_files.size())); if (int(m_file_base.size()) <= index) m_file_base.resize(index + 1, 0); m_file_base[index] = off; } @@ -517,7 +517,7 @@ namespace libtorrent std::string file_storage::file_path(int index, std::string const& save_path) const { - TORRENT_ASSERT(index >= 0 && index < int(m_files.size())); + TORRENT_ASSERT_PRECOND(index >= 0 && index < int(m_files.size())); internal_file_entry const& fe = m_files[index]; // -2 means this is an absolute path filename @@ -539,26 +539,26 @@ namespace libtorrent std::string file_storage::file_name(int index) const { - TORRENT_ASSERT(index >= 0 && index < int(m_files.size())); + TORRENT_ASSERT_PRECOND(index >= 0 && index < int(m_files.size())); internal_file_entry const& fe = m_files[index]; return fe.filename(); } size_type file_storage::file_size(int index) const { - TORRENT_ASSERT(index >= 0 && index < int(m_files.size())); + TORRENT_ASSERT_PRECOND(index >= 0 && index < int(m_files.size())); return m_files[index].size; } bool file_storage::pad_file_at(int index) const { - TORRENT_ASSERT(index >= 0 && index < int(m_files.size())); + TORRENT_ASSERT_PRECOND(index >= 0 && index < int(m_files.size())); return m_files[index].pad_file; } size_type file_storage::file_offset(int index) const { - TORRENT_ASSERT(index >= 0 && index < int(m_files.size())); + TORRENT_ASSERT_PRECOND(index >= 0 && index < int(m_files.size())); return m_files[index].offset; } @@ -581,7 +581,7 @@ namespace libtorrent std::string const& file_storage::symlink(internal_file_entry const& fe) const { - TORRENT_ASSERT(fe.symlink_index < int(m_symlinks.size())); + TORRENT_ASSERT_PRECOND(fe.symlink_index < int(m_symlinks.size())); return m_symlinks[fe.symlink_index]; } @@ -595,14 +595,14 @@ namespace libtorrent int file_storage::file_index(internal_file_entry const& fe) const { int index = &fe - &m_files[0]; - TORRENT_ASSERT(index >= 0 && index < int(m_files.size())); + TORRENT_ASSERT_PRECOND(index >= 0 && index < int(m_files.size())); return index; } void file_storage::set_file_base(internal_file_entry const& fe, size_type off) { int index = &fe - &m_files[0]; - TORRENT_ASSERT(index >= 0 && index < int(m_files.size())); + TORRENT_ASSERT_PRECOND(index >= 0 && index < int(m_files.size())); if (int(m_file_base.size()) <= index) m_file_base.resize(index + 1, 0); m_file_base[index] = off; } diff --git a/src/session.cpp b/src/session.cpp index 3eb0f00ec..7c3f0a90c 100644 --- a/src/session.cpp +++ b/src/session.cpp @@ -476,7 +476,7 @@ namespace libtorrent feed_handle session::add_feed(feed_settings const& feed) { // if you have auto-download enabled, you must specify a download directory! - TORRENT_ASSERT(!feed.auto_download || !feed.add_args.save_path.empty()); + TORRENT_ASSERT_PRECOND(!feed.auto_download || !feed.add_args.save_path.empty()); TORRENT_SYNC_CALL_RET1(feed_handle, add_feed, feed); return r; } diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 9d9947bb5..377caf3a2 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -1896,7 +1896,7 @@ namespace aux { // If you hit this assert, you're trying to set your cache to be // volatile and to suggest pieces out of it (or to make the cache // explicit) at the same time this is a bad configuration, don't do it - TORRENT_ASSERT(false); + TORRENT_ASSERT_PRECOND(false); m_settings.volatile_read_cache = false; } diff --git a/src/torrent_handle.cpp b/src/torrent_handle.cpp index a23475d8f..e29fd3e46 100644 --- a/src/torrent_handle.cpp +++ b/src/torrent_handle.cpp @@ -282,7 +282,7 @@ namespace libtorrent void torrent_handle::set_max_uploads(int max_uploads) const { - TORRENT_ASSERT(max_uploads >= 2 || max_uploads == -1); + TORRENT_ASSERT_PRECOND(max_uploads >= 2 || max_uploads == -1); TORRENT_ASYNC_CALL2(set_max_uploads, max_uploads, true); } @@ -294,13 +294,13 @@ namespace libtorrent void torrent_handle::set_max_connections(int max_connections) const { - TORRENT_ASSERT(max_connections >= 2 || max_connections == -1); + TORRENT_ASSERT_PRECOND(max_connections >= 2 || max_connections == -1); TORRENT_ASYNC_CALL2(set_max_connections, max_connections, true); } void torrent_handle::set_upload_limit(int limit) const { - TORRENT_ASSERT(limit >= -1); + TORRENT_ASSERT_PRECOND(limit >= -1); TORRENT_ASYNC_CALL2(set_upload_limit, limit, true); } @@ -312,7 +312,7 @@ namespace libtorrent void torrent_handle::set_download_limit(int limit) const { - TORRENT_ASSERT(limit >= -1); + TORRENT_ASSERT_PRECOND(limit >= -1); TORRENT_ASYNC_CALL2(set_download_limit, limit, true); } @@ -568,20 +568,20 @@ namespace libtorrent void torrent_handle::set_peer_upload_limit(tcp::endpoint ip, int limit) const { - TORRENT_ASSERT(limit >= -1); + TORRENT_ASSERT_PRECOND(limit >= -1); TORRENT_ASYNC_CALL2(set_peer_upload_limit, ip, limit); } void torrent_handle::set_peer_download_limit(tcp::endpoint ip, int limit) const { - TORRENT_ASSERT(limit >= -1); + TORRENT_ASSERT_PRECOND(limit >= -1); TORRENT_ASYNC_CALL2(set_peer_download_limit, ip, limit); } void torrent_handle::set_ratio(float ratio) const { - TORRENT_ASSERT(ratio >= 0.f); + TORRENT_ASSERT_PRECOND(ratio >= 0.f); if (ratio < 1.f && ratio > 0.f) ratio = 1.f; TORRENT_ASYNC_CALL1(set_ratio, ratio);