From 6495004302239ae0c775f05a0e78780c3b189502 Mon Sep 17 00:00:00 2001 From: Daniel Larimer Date: Fri, 9 Oct 2015 17:08:03 -0400 Subject: [PATCH 01/17] move potential yields outside of catch --- include/fc/crypto/city.hpp | 3 ++- src/rpc/json_connection.cpp | 16 +++++++++++----- src/thread/future.cpp | 16 +++++++--------- src/thread/mutex.cpp | 22 ++++++++++++---------- src/thread/task.cpp | 2 +- src/thread/thread_d.hpp | 5 +---- 6 files changed, 34 insertions(+), 30 deletions(-) diff --git a/include/fc/crypto/city.hpp b/include/fc/crypto/city.hpp index 7e42f37..7047ae8 100644 --- a/include/fc/crypto/city.hpp +++ b/include/fc/crypto/city.hpp @@ -47,9 +47,9 @@ namespace fc { -class uint128; template class array; +class uint128; // Hash function for a byte array. uint64_t city_hash64(const char *buf, size_t len); @@ -72,4 +72,5 @@ uint64_t city_hash_crc_64(const char *buf, size_t len); uint128 city_hash_crc_128(const char *s, size_t len); array city_hash_crc_256(const char *s, size_t len); + } // namespace fc diff --git a/src/rpc/json_connection.cpp b/src/rpc/json_connection.cpp index cd1d6b4..bde046a 100644 --- a/src/rpc/json_connection.cpp +++ b/src/rpc/json_connection.cpp @@ -68,6 +68,7 @@ namespace fc { namespace rpc { void handle_message( const variant_object& obj ) { wlog( "recv: ${msg}", ("msg", obj) ); + fc::exception_ptr eptr; try { auto m = obj.find("method"); @@ -158,6 +159,7 @@ namespace fc { namespace rpc { } else if( e != obj.end() ) //if error response { + fc::exception_ptr eptr; try { auto err = e->value().get_object(); @@ -173,8 +175,9 @@ namespace fc { namespace rpc { catch ( fc::exception& e ) { elog( "Error parsing exception: ${e}", ("e", e.to_detail_string() ) ); - await->second->set_exception( e.dynamic_copy_exception() ); + eptr = e.dynamic_copy_exception(); } + if( eptr ) await->second->set_exception( eptr ); } else // id found without error, result, nor method field { @@ -191,12 +194,14 @@ namespace fc { namespace rpc { { fc_elog( _logger, "json rpc exception: ${exception}", ("exception",e )); elog( "json rpc exception: ${exception}", ("exception",e )); - close(e.dynamic_copy_exception()); + eptr = e.dynamic_copy_exception(); } + if( eptr ) { close(eptr); } } void read_loop() { + fc::exception_ptr eptr; try { fc::string line; @@ -211,16 +216,17 @@ namespace fc { namespace rpc { catch ( eof_exception& eof ) { _eof = true; - close( eof.dynamic_copy_exception() ); + eptr = eof.dynamic_copy_exception(); } catch ( exception& e ) { - close( e.dynamic_copy_exception() ); + eptr = e.dynamic_copy_exception(); } catch ( ... ) { - close( fc::exception_ptr(new FC_EXCEPTION( unhandled_exception, "json connection read error" )) ); + eptr = fc::exception_ptr(new FC_EXCEPTION( unhandled_exception, "json connection read error" )); } + if( eptr ) close( eptr ); } void close( fc::exception_ptr e ) diff --git a/src/thread/future.cpp b/src/thread/future.cpp index d0b5252..1950086 100644 --- a/src/thread/future.cpp +++ b/src/thread/future.cpp @@ -62,16 +62,14 @@ namespace fc { } _enqueue_thread(); } - try - { - thread::current().wait_until( ptr(this,true), timeout_us ); - } - catch (...) - { - _dequeue_thread(); - throw; - } + std::exception_ptr e; + try { thread::current().wait_until( ptr(this,true), timeout_us ); } + catch (...) { e = std::current_exception(); } + _dequeue_thread(); + + if( e ) std::rethrow_exception(e); + if( _ready ) { if( _exceptp ) diff --git a/src/thread/mutex.cpp b/src/thread/mutex.cpp index 0ebd834..9f3f9ba 100644 --- a/src/thread/mutex.cpp +++ b/src/thread/mutex.cpp @@ -118,13 +118,18 @@ namespace fc { cc->next_blocked_mutex = m_blist; m_blist = cc; } // end lock scope + + + std::exception_ptr e; try { fc::thread::current().my->yield_until( abs_time, false ); return( 0 == cc->next_blocked_mutex ); } catch (...) { - cleanup( *this, m_blist_lock, m_blist, cc); - throw; + e = std::current_exception(); } + assert(e); + cleanup( *this, m_blist_lock, m_blist, cc); + std::rethrow_exception(e); } void mutex::lock() { @@ -166,6 +171,7 @@ namespace fc { #endif } + std::exception_ptr e; // cleanup calls yield so we need to move the exception outside of the catch block try { fc::thread::current().yield(false); @@ -174,17 +180,13 @@ namespace fc { assert(recursive_lock_count == 0); recursive_lock_count = 1; } - catch ( exception& e ) - { - wlog( "lock threw: ${e}", ("e", e)); - cleanup( *this, m_blist_lock, m_blist, current_context); - FC_RETHROW_EXCEPTION(e, warn, "lock threw: ${e}", ("e", e)); - } catch ( ... ) { - wlog( "lock threw unexpected exception" ); + e = std::current_exception(); + } + if( e ) { cleanup( *this, m_blist_lock, m_blist, current_context); - throw; + std::rethrow_exception(e); } } diff --git a/src/thread/task.cpp b/src/thread/task.cpp index 7f45522..b081872 100644 --- a/src/thread/task.cpp +++ b/src/thread/task.cpp @@ -56,7 +56,7 @@ namespace fc { } catch ( ... ) { - set_exception( std::make_shared( FC_LOG_MESSAGE( warn, "unhandled exception: ${diagnostic}", ("diagnostic",boost::current_exception_diagnostic_information()) ) ) ); + set_exception( std::make_shared( FC_LOG_MESSAGE( warn, "unhandled exception: ${diagnostic}", ("diagnostic",boost::current_exception_diagnostic_information()) ) ) ); } } diff --git a/src/thread/thread_d.hpp b/src/thread/thread_d.hpp index bb7370f..941b2fa 100644 --- a/src/thread/thread_d.hpp +++ b/src/thread/thread_d.hpp @@ -474,10 +474,7 @@ namespace fc { { self->process_tasks(); } - catch ( canceled_exception& ) - { - // allowed exception... - } + catch ( canceled_exception& ) { /* allowed exception */ } catch ( ... ) { elog( "fiber ${name} exited with uncaught exception: ${e}", ("e",fc::except_str())("name", self->name) ); From 1e10d3dc4774426e735eb6aabd8e0aa43799fe30 Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Mon, 12 Oct 2015 09:02:45 -0400 Subject: [PATCH 02/17] raw.hpp: Require high bits to be 0 when unpacking bool --- include/fc/io/raw.hpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/fc/io/raw.hpp b/include/fc/io/raw.hpp index c402cbb..49dc93f 100644 --- a/include/fc/io/raw.hpp +++ b/include/fc/io/raw.hpp @@ -236,7 +236,13 @@ namespace fc { // bool template inline void pack( Stream& s, const bool& v ) { pack( s, uint8_t(v) ); } - template inline void unpack( Stream& s, bool& v ) { uint8_t b; unpack( s, b ); v=(b!=0); } + template inline void unpack( Stream& s, bool& v ) + { + uint8_t b; + unpack( s, b ); + FC_ASSERT( (b & ~1) == 0 ); + v=(b!=0); + } namespace detail { From cb27b810e3531953391d5125dbfa9fb6e629c999 Mon Sep 17 00:00:00 2001 From: Daniel Larimer Date: Wed, 25 Nov 2015 12:49:49 -0500 Subject: [PATCH 03/17] adding support for unpacking shared_ptr --- include/fc/io/raw.hpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/fc/io/raw.hpp b/include/fc/io/raw.hpp index 49dc93f..223d317 100644 --- a/include/fc/io/raw.hpp +++ b/include/fc/io/raw.hpp @@ -122,6 +122,13 @@ namespace fc { s.read((char*)&v.data[0],N*sizeof(T)); } FC_RETHROW_EXCEPTIONS( warn, "fc::array", ("type",fc::get_typename::name())("length",N) ) } + template + inline void unpack( Stream& s, std::shared_ptr& v) + { try { + v = std::make_shared(); + unpack( s, *v ); + } FC_RETHROW_EXCEPTIONS( warn, "std::shared_ptr", ("type",fc::get_typename::name()) ) } + template inline void pack( Stream& s, const signed_int& v ) { uint32_t val = (v.value<<1) ^ (v.value>>31); do { From ad7ecbf061ae74c944c81da993a020c05d53c7b6 Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Fri, 4 Dec 2015 11:40:08 -0500 Subject: [PATCH 04/17] Build with WEBSOCKETPP_STRICT_MASKING --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index e119319..554cd16 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -289,6 +289,9 @@ ELSE() ENDIF() ENDIF() +# This will become unnecessary once we update to websocketpp which fixes upstream issue #395 +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWEBSOCKETPP_STRICT_MASKING") + target_include_directories(fc PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include ${Boost_INCLUDE_DIR} From d74eee811018f5f0b562b12af3a5afaa59cf60cb Mon Sep 17 00:00:00 2001 From: Michael Vandeberg Date: Thu, 7 Jan 2016 17:14:16 -0500 Subject: [PATCH 05/17] Implements deserialize for extended_public_key and extended_private_key. Implementation needed by cryptonomex/graphene#500 --- src/crypto/elliptic_common.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/crypto/elliptic_common.cpp b/src/crypto/elliptic_common.cpp index f1dafb2..88228b0 100644 --- a/src/crypto/elliptic_common.cpp +++ b/src/crypto/elliptic_common.cpp @@ -269,6 +269,11 @@ namespace fc { namespace ecc { memcpy( dest, key.begin(), key.size() ); return result; } + + extended_public_key extended_public_key::deserialize( const extended_key_data& data ) + { + return from_base58( _to_base58( data ) ); + } fc::string extended_public_key::str() const { @@ -335,6 +340,11 @@ namespace fc { namespace ecc { memcpy( dest, key.data(), key.data_size() ); return result; } + + extended_private_key extended_private_key::deserialize( const extended_key_data& data ) + { + return from_base58( _to_base58( data ) ); + } private_key extended_private_key::generate_a(int i) const { return derive_hardened_child(4*i + 0); } private_key extended_private_key::generate_b(int i) const { return derive_hardened_child(4*i + 1); } From 7b6431f20e06ffe700f1cb6df61f544360769e4b Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Fri, 8 Jan 2016 11:20:32 -0500 Subject: [PATCH 06/17] raw.hpp: Add pack() override for shared_ptr --- include/fc/io/raw.hpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/fc/io/raw.hpp b/include/fc/io/raw.hpp index 223d317..44597bf 100644 --- a/include/fc/io/raw.hpp +++ b/include/fc/io/raw.hpp @@ -110,12 +110,18 @@ namespace fc { s.read( (char*)&usec_as_int64, sizeof(usec_as_int64) ); usec = fc::microseconds(usec_as_int64); } FC_RETHROW_EXCEPTIONS( warn, "" ) } - + template inline void pack( Stream& s, const fc::array& v) { s.write((const char*)&v.data[0],N*sizeof(T)); } + template + inline void pack( Stream& s, const std::shared_ptr& v) + { + pack( s, *v ); + } + template inline void unpack( Stream& s, fc::array& v) { try { From 8eec508b8cd418f0719a58f10a11d7850e87b992 Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Fri, 8 Jan 2016 11:20:38 -0500 Subject: [PATCH 07/17] iostream.hpp: Add get(char&) override to allow unpack(fc::istream, unsigned_int) --- include/fc/io/iostream.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/fc/io/iostream.hpp b/include/fc/io/iostream.hpp index ee10efe..1ec632f 100644 --- a/include/fc/io/iostream.hpp +++ b/include/fc/io/iostream.hpp @@ -31,6 +31,7 @@ namespace fc { istream& read( char* buf, size_t len ); istream& read( const std::shared_ptr& buf, size_t len, size_t offset = 0 ); virtual char get(); + void get( char& c ) { c = get(); } }; typedef std::shared_ptr istream_ptr; From 9128edb0d6dcf5ff77802ae495aebd3c33cdf5a6 Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Tue, 12 Jan 2016 15:34:36 -0500 Subject: [PATCH 08/17] websocketpp: Define BOOST_ASIO_HAS_STD_CHRONO to fix clang compile --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 554cd16..9931b9a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,7 +37,6 @@ SET(BOOST_COMPONENTS) LIST(APPEND BOOST_COMPONENTS thread date_time system filesystem program_options signals serialization chrono unit_test_framework context locale iostreams) SET( Boost_USE_STATIC_LIBS ON CACHE STRING "ON or OFF" ) - IF( ECC_IMPL STREQUAL openssl ) SET( ECC_REST src/crypto/elliptic_impl_pub.cpp ) ELSE( ECC_IMPL STREQUAL openssl ) @@ -292,6 +291,8 @@ ENDIF() # This will become unnecessary once we update to websocketpp which fixes upstream issue #395 SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWEBSOCKETPP_STRICT_MASKING") +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBOOST_ASIO_HAS_STD_CHRONO") + target_include_directories(fc PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include ${Boost_INCLUDE_DIR} From 46ed83037312051d5c7046db940eddf58e1b5206 Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Thu, 21 Jan 2016 15:29:41 -0500 Subject: [PATCH 09/17] variant.cpp: Tighten bool parsing in variant::as_bool() cryptonomex/graphene#525 --- src/variant.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/variant.cpp b/src/variant.cpp index 7b73771..542ee66 100644 --- a/src/variant.cpp +++ b/src/variant.cpp @@ -431,7 +431,14 @@ bool variant::as_bool()const switch( get_type() ) { case string_type: - return **reinterpret_cast(this) == "true"; + { + const string& s = **reinterpret_cast(this); + if( s == "true" ) + return true; + if( s == "false" ) + return false; + FC_THROW_EXCEPTION( bad_cast_exception, "Cannot convert string to bool (only \"true\" or \"false\" can be converted)" ); + } case double_type: return *reinterpret_cast(this) != 0.0; case int64_type: From 845f8388c40bf78587e4bf98c14cedb9bf992e5a Mon Sep 17 00:00:00 2001 From: Daniel Larimer Date: Mon, 1 Feb 2016 18:29:30 -0500 Subject: [PATCH 10/17] add deque support to variant --- include/fc/variant.hpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/include/fc/variant.hpp b/include/fc/variant.hpp index e8596cd..513aac3 100644 --- a/include/fc/variant.hpp +++ b/include/fc/variant.hpp @@ -108,6 +108,11 @@ namespace fc template void from_variant( const variant& var, std::unordered_set& vo ); + template + void to_variant( const std::deque& var, variant& vo ); + template + void from_variant( const variant& var, std::deque& vo ); + template void to_variant( const fc::flat_set& var, variant& vo ); template @@ -452,6 +457,28 @@ namespace fc vo.insert( itr->as() ); } + /** @ingroup Serializable */ + template + void from_variant( const variant& var, std::deque& tmp ) + { + const variants& vars = var.get_array(); + tmp.clear(); + tmp.reserve( vars.size() ); + for( auto itr = vars.begin(); itr != vars.end(); ++itr ) + tmp.push_back( itr->as() ); + } + + /** @ingroup Serializable */ + template + void to_variant( const std::deque& t, variant& v ) + { + std::deque vars(t.size()); + for( size_t i = 0; i < t.size(); ++i ) + vars[i] = variant(t[i]); + v = std::move(vars); + } + + /** @ingroup Serializable */ template void from_variant( const variant& var, std::vector& tmp ) @@ -472,6 +499,8 @@ namespace fc vars[i] = variant(t[i]); v = std::move(vars); } + + /** @ingroup Serializable */ template void to_variant( const std::pair& t, variant& v ) From 4438c8aa801708dfc845c4138aa0bec55aca8719 Mon Sep 17 00:00:00 2001 From: Daniel Larimer Date: Tue, 2 Feb 2016 13:36:48 -0500 Subject: [PATCH 11/17] fix include dependency and redundancy of to_variant --- include/fc/container/deque.hpp | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/include/fc/container/deque.hpp b/include/fc/container/deque.hpp index d59a1ad..66f2c19 100644 --- a/include/fc/container/deque.hpp +++ b/include/fc/container/deque.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include namespace fc { namespace raw { @@ -31,19 +32,4 @@ namespace fc { } // namespace raw - template - void to_variant( const std::deque& var, variant& vo ) - { - std::vector vars; - vars.reserve(var.size()); - std::transform(var.begin(), var.end(), std::back_inserter(vars), [](const T& t) { return variant(t); }); - vo = vars; - } - template - void from_variant( const variant& var, std::deque& vo ) - { - const variants& vars = var.get_array(); - vo.clear(); - std::transform(vars.begin(), vars.end(), std::back_inserter(vo), [](const variant& t) { return t.template as(); }); - } } // namespace fc From 7840ef16e9fae8341efea5a882f484262d50d7e6 Mon Sep 17 00:00:00 2001 From: Daniel Larimer Date: Thu, 4 Feb 2016 16:32:13 -0500 Subject: [PATCH 12/17] adding rshift --- include/fc/crypto/sha256.hpp | 1 + src/crypto/_digest_common.cpp | 26 +++++++++++++++++++++++++- src/crypto/_digest_common.hpp | 1 + src/crypto/sha256.cpp | 5 +++++ 4 files changed, 32 insertions(+), 1 deletion(-) diff --git a/include/fc/crypto/sha256.hpp b/include/fc/crypto/sha256.hpp index 387a1d0..87fffa2 100644 --- a/include/fc/crypto/sha256.hpp +++ b/include/fc/crypto/sha256.hpp @@ -60,6 +60,7 @@ class sha256 return ds; } friend sha256 operator << ( const sha256& h1, uint32_t i ); + friend sha256 operator >> ( const sha256& h1, uint32_t i ); friend bool operator == ( const sha256& h1, const sha256& h2 ); friend bool operator != ( const sha256& h1, const sha256& h2 ); friend sha256 operator ^ ( const sha256& h1, const sha256& h2 ); diff --git a/src/crypto/_digest_common.cpp b/src/crypto/_digest_common.cpp index 2c5c652..67a015b 100644 --- a/src/crypto/_digest_common.cpp +++ b/src/crypto/_digest_common.cpp @@ -16,7 +16,7 @@ namespace fc { namespace detail { uint8_t* out8 = (uint8_t*) out; if (i >= 8) { - shift_l( in8, out8, n, i >> 3 ); + shift_l( in8, out8, n, i / 8 ); i &= 7; in8 = out8; } @@ -26,4 +26,28 @@ namespace fc { namespace detail { out8[p] = (in8[p] << i) | (in8[p+1]>>(8-i)); out8[p] = in8[p] << i; } + static void shift_r( const uint8_t* in, uint8_t* out, std::size_t n, unsigned int i) { + if (i < n) { + memcpy( out+i, in, n-i ); + } else { + i = n; + } + memset( out, 0, i ); + } + + void shift_r( const char* in, char* out, std::size_t n, unsigned int i) { + const uint8_t* in8 = (uint8_t*) in; + uint8_t* out8 = (uint8_t*) out; + + if (i >= 8) { + shift_r( in8, out8, n, i / 8 ); + i &= 7; + in8 = out8; + } + + std::size_t p; + for( p = n-1; p > 0; --p ) + out8[p] = (in8[p] >> i) | (in8[p-1]<<(8-i)); + out8[p] = in8[p] >> i; + } }} diff --git a/src/crypto/_digest_common.hpp b/src/crypto/_digest_common.hpp index 8aa21b3..8582309 100644 --- a/src/crypto/_digest_common.hpp +++ b/src/crypto/_digest_common.hpp @@ -4,4 +4,5 @@ */ namespace fc { namespace detail { void shift_l( const char* in, char* out, std::size_t n, unsigned int i); + void shift_r( const char* in, char* out, std::size_t n, unsigned int i); }} diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp index b043c2c..9c3b9e6 100644 --- a/src/crypto/sha256.cpp +++ b/src/crypto/sha256.cpp @@ -69,6 +69,11 @@ namespace fc { fc::detail::shift_l( h1.data(), result.data(), result.data_size(), i ); return result; } + sha256 operator >> ( const sha256& h1, uint32_t i ) { + sha256 result; + fc::detail::shift_r( h1.data(), result.data(), result.data_size(), i ); + return result; + } sha256 operator ^ ( const sha256& h1, const sha256& h2 ) { sha256 result; result._hash[0] = h1._hash[0] ^ h2._hash[0]; From 6ed77178266d917deedf8bb090cfa9f61905063b Mon Sep 17 00:00:00 2001 From: Eric Frias Date: Wed, 10 Feb 2016 15:25:54 -0500 Subject: [PATCH 13/17] Handle http requests to the websocket server async, in a similar manner to the way regular websocket messages were handled since 01445529f0af904f88cc6c60867b5c5d262aae1f. Fixes cryptonomex/graphene#251, and likely eliminates the need for the workaround used to fix cryptonomex/graphene#1 and cryptonomex/graphene#252 --- src/network/http/websocket.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/network/http/websocket.cpp b/src/network/http/websocket.cpp index cbb92ae..67745d9 100644 --- a/src/network/http/websocket.cpp +++ b/src/network/http/websocket.cpp @@ -199,25 +199,28 @@ namespace fc { namespace http { std::shared_ptr con = current_con->second; ++_pending_messages; auto f = fc::async([this,con,payload](){ if( _pending_messages ) --_pending_messages; con->on_message( payload ); }); - if( _pending_messages > 100 ) f.wait(); - + if( _pending_messages > 100 ) + f.wait(); }).wait(); }); _server.set_http_handler( [&]( connection_hdl hdl ){ _server_thread.async( [&](){ - auto current_con = std::make_shared>( _server.get_con_from_hdl(hdl) ); _on_connection( current_con ); auto con = _server.get_con_from_hdl(hdl); - wdump(("server")(con->get_request_body())); - auto response = current_con->on_http( con->get_request_body() ); - - con->set_body( response ); - con->set_status( websocketpp::http::status_code::ok ); - current_con->closed(); + con->defer_http_response(); + std::string request_body = con->get_request_body(); + wdump(("server")(request_body)); + fc::async([current_con, request_body, con] { + std::string response = current_con->on_http(request_body); + con->set_body( response ); + con->set_status( websocketpp::http::status_code::ok ); + con->send_http_response(); + current_con->closed(); + }, "call on_http"); }).wait(); }); From bde8a7f4245ad7fa65dc25021f95cc8c9c5a3f20 Mon Sep 17 00:00:00 2001 From: Daniel Larimer Date: Thu, 11 Feb 2016 17:16:39 -0500 Subject: [PATCH 14/17] fixes updates for deque to variant --- include/fc/container/deque.hpp | 23 ----------------------- include/fc/io/raw.hpp | 24 ++++++++++++++++++++++++ include/fc/variant.hpp | 9 ++++----- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/include/fc/container/deque.hpp b/include/fc/container/deque.hpp index 66f2c19..6a05dc8 100644 --- a/include/fc/container/deque.hpp +++ b/include/fc/container/deque.hpp @@ -6,29 +6,6 @@ namespace fc { namespace raw { - template - inline void pack( Stream& s, const std::deque& value ) { - pack( s, unsigned_int((uint32_t)value.size()) ); - auto itr = value.begin(); - auto end = value.end(); - while( itr != end ) { - fc::raw::pack( s, *itr ); - ++itr; - } - } - - template - inline void unpack( Stream& s, std::deque& value ) { - unsigned_int size; unpack( s, size ); - FC_ASSERT( size.value*sizeof(T) < MAX_ARRAY_ALLOC_SIZE ); - value.resize(size.value); - auto itr = value.begin(); - auto end = value.end(); - while( itr != end ) { - fc::raw::unpack( s, *itr ); - ++itr; - } - } } // namespace raw diff --git a/include/fc/io/raw.hpp b/include/fc/io/raw.hpp index 44597bf..1b62fa9 100644 --- a/include/fc/io/raw.hpp +++ b/include/fc/io/raw.hpp @@ -13,6 +13,7 @@ #include #include #include +#include namespace fc { namespace raw { @@ -443,6 +444,29 @@ namespace fc { } } + template + inline void pack( Stream& s, const std::deque& value ) { + pack( s, unsigned_int((uint32_t)value.size()) ); + auto itr = value.begin(); + auto end = value.end(); + while( itr != end ) { + fc::raw::pack( s, *itr ); + ++itr; + } + } + + template + inline void unpack( Stream& s, std::deque& value ) { + unsigned_int size; unpack( s, size ); + FC_ASSERT( size.value*sizeof(T) < MAX_ARRAY_ALLOC_SIZE ); + value.resize(size.value); + auto itr = value.begin(); + auto end = value.end(); + while( itr != end ) { + fc::raw::unpack( s, *itr ); + ++itr; + } + } template inline void pack( Stream& s, const std::vector& value ) { diff --git a/include/fc/variant.hpp b/include/fc/variant.hpp index 513aac3..11ab95a 100644 --- a/include/fc/variant.hpp +++ b/include/fc/variant.hpp @@ -463,7 +463,6 @@ namespace fc { const variants& vars = var.get_array(); tmp.clear(); - tmp.reserve( vars.size() ); for( auto itr = vars.begin(); itr != vars.end(); ++itr ) tmp.push_back( itr->as() ); } @@ -472,10 +471,10 @@ namespace fc template void to_variant( const std::deque& t, variant& v ) { - std::deque vars(t.size()); - for( size_t i = 0; i < t.size(); ++i ) - vars[i] = variant(t[i]); - v = std::move(vars); + std::vector vars(t.size()); + for( size_t i = 0; i < t.size(); ++i ) + vars[i] = variant(t[i]); + v = std::move(vars); } From e5ca765f1508f2a05bb980231ee8e4b8985b51cf Mon Sep 17 00:00:00 2001 From: Daniel Larimer Date: Mon, 15 Feb 2016 11:59:28 -0500 Subject: [PATCH 15/17] clean up logging --- src/thread/thread.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/thread/thread.cpp b/src/thread/thread.cpp index 776d257..eaa8e40 100644 --- a/src/thread/thread.cpp +++ b/src/thread/thread.cpp @@ -112,7 +112,7 @@ namespace fc { //wlog( "my ${n}", ("n",name()) ); if( my ) { - wlog( "calling quit() on ${n}",("n",my->name) ); + // wlog( "calling quit() on ${n}",("n",my->name) ); quit(); // deletes `my` } } @@ -157,7 +157,7 @@ namespace fc { async( [=](){quit();}, "thread::quit" );//.wait(); if( my->boost_thread ) { - wlog("destroying boost thread ${tid}",("tid",(uintptr_t)my->boost_thread->native_handle())); + //wlog("destroying boost thread ${tid}",("tid",(uintptr_t)my->boost_thread->native_handle())); my->boost_thread->join(); delete my; my = nullptr; @@ -243,7 +243,7 @@ namespace fc { } catch( canceled_exception& e ) { - wlog( "thread canceled: ${e}", ("e", e.to_detail_string()) ); + dlog( "thread canceled: ${e}", ("e", e.to_detail_string()) ); } delete my->current; my->current = 0; From 232d59525af8d2e3b56e8b18b2fdb7f58435a7f5 Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Fri, 19 Feb 2016 16:36:29 -0500 Subject: [PATCH 16/17] raw.hpp: Use fc::raw:: namespace explicitly everywhere, cleanup whitespace --- include/fc/io/raw.hpp | 212 +++++++++++++++++++++--------------------- 1 file changed, 106 insertions(+), 106 deletions(-) diff --git a/include/fc/io/raw.hpp b/include/fc/io/raw.hpp index 1b62fa9..bc5cd22 100644 --- a/include/fc/io/raw.hpp +++ b/include/fc/io/raw.hpp @@ -15,7 +15,7 @@ #include #include -namespace fc { +namespace fc { namespace raw { template inline void pack( Stream& s, const fc::exception& e ) @@ -76,7 +76,7 @@ namespace fc { template inline void unpack( Stream& s, fc::time_point_sec& tp ) - { try { + { try { uint32_t sec; s.read( (char*)&sec, sizeof(sec) ); tp = fc::time_point() + fc::seconds(sec); @@ -112,7 +112,7 @@ namespace fc { usec = fc::microseconds(usec_as_int64); } FC_RETHROW_EXCEPTIONS( warn, "" ) } - template + template inline void pack( Stream& s, const fc::array& v) { s.write((const char*)&v.data[0],N*sizeof(T)); } @@ -120,20 +120,20 @@ namespace fc { template inline void pack( Stream& s, const std::shared_ptr& v) { - pack( s, *v ); + fc::raw::pack( s, *v ); } - template - inline void unpack( Stream& s, fc::array& v) + template + inline void unpack( Stream& s, fc::array& v) { try { s.read((char*)&v.data[0],N*sizeof(T)); } FC_RETHROW_EXCEPTIONS( warn, "fc::array", ("type",fc::get_typename::name())("length",N) ) } - template - inline void unpack( Stream& s, std::shared_ptr& v) + template + inline void unpack( Stream& s, std::shared_ptr& v) { try { v = std::make_shared(); - unpack( s, *v ); + fc::raw::unpack( s, *v ); } FC_RETHROW_EXCEPTIONS( warn, "std::shared_ptr", ("type",fc::get_typename::name()) ) } template inline void pack( Stream& s, const signed_int& v ) { @@ -177,58 +177,58 @@ namespace fc { vi.value = static_cast(v); } - template inline void unpack( Stream& s, const T& vi ) + template inline void unpack( Stream& s, const T& vi ) { T tmp; - unpack( s, tmp ); + fc::raw::unpack( s, tmp ); FC_ASSERT( vi == tmp ); } - template inline void pack( Stream& s, const char* v ) { pack( s, fc::string(v) ); } - - template - void pack( Stream& s, const safe& v ) { pack( s, v.value ); } + template inline void pack( Stream& s, const char* v ) { fc::raw::pack( s, fc::string(v) ); } template - void unpack( Stream& s, fc::safe& v ) { unpack( s, v.value ); } + void pack( Stream& s, const safe& v ) { fc::raw::pack( s, v.value ); } - template + template + void unpack( Stream& s, fc::safe& v ) { fc::raw::unpack( s, v.value ); } + + template void pack( Stream& s, const fc::fwd& v ) { - pack( *v ); + fc::raw::pack( *v ); } - template + template void unpack( Stream& s, fc::fwd& v ) { - unpack( *v ); + fc::raw::unpack( *v ); } - template - void pack( Stream& s, const fc::smart_ref& v ) { pack( s, *v ); } + template + void pack( Stream& s, const fc::smart_ref& v ) { fc::raw::pack( s, *v ); } - template - void unpack( Stream& s, fc::smart_ref& v ) { unpack( s, *v ); } + template + void unpack( Stream& s, fc::smart_ref& v ) { fc::raw::unpack( s, *v ); } // optional - template + template void pack( Stream& s, const fc::optional& v ) { - pack( s, bool(!!v) ); - if( !!v ) pack( s, *v ); + fc::raw::pack( s, bool(!!v) ); + if( !!v ) fc::raw::pack( s, *v ); } template - void unpack( Stream& s, fc::optional& v ) + void unpack( Stream& s, fc::optional& v ) { try { - bool b; unpack( s, b ); - if( b ) { v = T(); unpack( s, *v ); } + bool b; fc::raw::unpack( s, b ); + if( b ) { v = T(); fc::raw::unpack( s, *v ); } } FC_RETHROW_EXCEPTIONS( warn, "optional<${type}>", ("type",fc::get_typename::name() ) ) } // std::vector - template inline void pack( Stream& s, const std::vector& value ) { - pack( s, unsigned_int((uint32_t)value.size()) ); + template inline void pack( Stream& s, const std::vector& value ) { + fc::raw::pack( s, unsigned_int((uint32_t)value.size()) ); if( value.size() ) s.write( &value.front(), (uint32_t)value.size() ); } - template inline void unpack( Stream& s, std::vector& value ) { - unsigned_int size; unpack( s, size ); + template inline void unpack( Stream& s, std::vector& value ) { + unsigned_int size; fc::raw::unpack( s, size ); FC_ASSERT( size.value < MAX_ARRAY_ALLOC_SIZE ); value.resize(size.value); if( value.size() ) @@ -237,29 +237,29 @@ namespace fc { // fc::string template inline void pack( Stream& s, const fc::string& v ) { - pack( s, unsigned_int((uint32_t)v.size())); + fc::raw::pack( s, unsigned_int((uint32_t)v.size())); if( v.size() ) s.write( v.c_str(), v.size() ); } template inline void unpack( Stream& s, fc::string& v ) { - std::vector tmp; unpack(s,tmp); + std::vector tmp; fc::raw::unpack(s,tmp); if( tmp.size() ) v = fc::string(tmp.data(),tmp.data()+tmp.size()); else v = fc::string(); } // bool - template inline void pack( Stream& s, const bool& v ) { pack( s, uint8_t(v) ); } + template inline void pack( Stream& s, const bool& v ) { fc::raw::pack( s, uint8_t(v) ); } template inline void unpack( Stream& s, bool& v ) { uint8_t b; - unpack( s, b ); + fc::raw::unpack( s, b ); FC_ASSERT( (b & ~1) == 0 ); v=(b!=0); } namespace detail { - + template struct pack_object_visitor { pack_object_visitor(const Class& _c, Stream& _s) @@ -267,9 +267,9 @@ namespace fc { template void operator()( const char* name )const { - raw::pack( s, c.*p ); + fc::raw::pack( s, c.*p ); } - private: + private: const Class& c; Stream& s; }; @@ -280,11 +280,11 @@ namespace fc { :c(_c),s(_s){} template - inline void operator()( const char* name )const + inline void operator()( const char* name )const { try { - raw::unpack( s, c.*p ); + fc::raw::unpack( s, c.*p ); } FC_RETHROW_EXCEPTIONS( warn, "Error unpacking field ${field}", ("field",name) ) } - private: + private: Class& c; Stream& s; }; @@ -300,23 +300,23 @@ namespace fc { template<> struct if_class { template - static inline void pack( Stream& s, const T& v ) { - s.write( (char*)&v, sizeof(v) ); + static inline void pack( Stream& s, const T& v ) { + s.write( (char*)&v, sizeof(v) ); } template - static inline void unpack( Stream& s, T& v ) { - s.read( (char*)&v, sizeof(v) ); + static inline void unpack( Stream& s, T& v ) { + s.read( (char*)&v, sizeof(v) ); } }; template struct if_enum { template - static inline void pack( Stream& s, const T& v ) { + static inline void pack( Stream& s, const T& v ) { fc::reflector::visit( pack_object_visitor( v, s ) ); } template - static inline void unpack( Stream& s, T& v ) { + static inline void unpack( Stream& s, T& v ) { fc::reflector::visit( unpack_object_visitor( v, s ) ); } }; @@ -327,32 +327,32 @@ namespace fc { fc::raw::pack(s, (int64_t)v); } template - static inline void unpack( Stream& s, T& v ) { + static inline void unpack( Stream& s, T& v ) { int64_t temp; fc::raw::unpack(s, temp); v = (T)temp; } - }; + }; template struct if_reflected { template - static inline void pack( Stream& s, const T& v ) { + static inline void pack( Stream& s, const T& v ) { if_class::type>::pack(s,v); } template - static inline void unpack( Stream& s, T& v ) { + static inline void unpack( Stream& s, T& v ) { if_class::type>::unpack(s,v); } }; template<> struct if_reflected { template - static inline void pack( Stream& s, const T& v ) { + static inline void pack( Stream& s, const T& v ) { if_enum< typename fc::reflector::is_enum >::pack(s,v); } template - static inline void unpack( Stream& s, T& v ) { + static inline void unpack( Stream& s, T& v ) { if_enum< typename fc::reflector::is_enum >::unpack(s,v); } }; @@ -361,7 +361,7 @@ namespace fc { template inline void pack( Stream& s, const std::unordered_set& value ) { - pack( s, unsigned_int((uint32_t)value.size()) ); + fc::raw::pack( s, unsigned_int((uint32_t)value.size()) ); auto itr = value.begin(); auto end = value.end(); while( itr != end ) { @@ -371,7 +371,7 @@ namespace fc { } template inline void unpack( Stream& s, std::unordered_set& value ) { - unsigned_int size; unpack( s, size ); + unsigned_int size; fc::raw::unpack( s, size ); value.clear(); FC_ASSERT( size.value*sizeof(T) < MAX_ARRAY_ALLOC_SIZE ); value.reserve(size.value); @@ -386,19 +386,19 @@ namespace fc { template inline void pack( Stream& s, const std::pair& value ) { - pack( s, value.first ); - pack( s, value.second ); + fc::raw::pack( s, value.first ); + fc::raw::pack( s, value.second ); } template - inline void unpack( Stream& s, std::pair& value ) + inline void unpack( Stream& s, std::pair& value ) { - unpack( s, value.first ); - unpack( s, value.second ); + fc::raw::unpack( s, value.first ); + fc::raw::unpack( s, value.second ); } - template + template inline void pack( Stream& s, const std::unordered_map& value ) { - pack( s, unsigned_int((uint32_t)value.size()) ); + fc::raw::pack( s, unsigned_int((uint32_t)value.size()) ); auto itr = value.begin(); auto end = value.end(); while( itr != end ) { @@ -407,9 +407,9 @@ namespace fc { } } template - inline void unpack( Stream& s, std::unordered_map& value ) + inline void unpack( Stream& s, std::unordered_map& value ) { - unsigned_int size; unpack( s, size ); + unsigned_int size; fc::raw::unpack( s, size ); value.clear(); FC_ASSERT( size.value*(sizeof(K)+sizeof(V)) < MAX_ARRAY_ALLOC_SIZE ); value.reserve(size.value); @@ -422,7 +422,7 @@ namespace fc { } template inline void pack( Stream& s, const std::map& value ) { - pack( s, unsigned_int((uint32_t)value.size()) ); + fc::raw::pack( s, unsigned_int((uint32_t)value.size()) ); auto itr = value.begin(); auto end = value.end(); while( itr != end ) { @@ -431,9 +431,9 @@ namespace fc { } } template - inline void unpack( Stream& s, std::map& value ) + inline void unpack( Stream& s, std::map& value ) { - unsigned_int size; unpack( s, size ); + unsigned_int size; fc::raw::unpack( s, size ); value.clear(); FC_ASSERT( size.value*(sizeof(K)+sizeof(V)) < MAX_ARRAY_ALLOC_SIZE ); for( uint32_t i = 0; i < size.value; ++i ) @@ -446,7 +446,7 @@ namespace fc { template inline void pack( Stream& s, const std::deque& value ) { - pack( s, unsigned_int((uint32_t)value.size()) ); + fc::raw::pack( s, unsigned_int((uint32_t)value.size()) ); auto itr = value.begin(); auto end = value.end(); while( itr != end ) { @@ -457,7 +457,7 @@ namespace fc { template inline void unpack( Stream& s, std::deque& value ) { - unsigned_int size; unpack( s, size ); + unsigned_int size; fc::raw::unpack( s, size ); FC_ASSERT( size.value*sizeof(T) < MAX_ARRAY_ALLOC_SIZE ); value.resize(size.value); auto itr = value.begin(); @@ -470,7 +470,7 @@ namespace fc { template inline void pack( Stream& s, const std::vector& value ) { - pack( s, unsigned_int((uint32_t)value.size()) ); + fc::raw::pack( s, unsigned_int((uint32_t)value.size()) ); auto itr = value.begin(); auto end = value.end(); while( itr != end ) { @@ -481,7 +481,7 @@ namespace fc { template inline void unpack( Stream& s, std::vector& value ) { - unsigned_int size; unpack( s, size ); + unsigned_int size; fc::raw::unpack( s, size ); FC_ASSERT( size.value*sizeof(T) < MAX_ARRAY_ALLOC_SIZE ); value.resize(size.value); auto itr = value.begin(); @@ -494,7 +494,7 @@ namespace fc { template inline void pack( Stream& s, const std::set& value ) { - pack( s, unsigned_int((uint32_t)value.size()) ); + fc::raw::pack( s, unsigned_int((uint32_t)value.size()) ); auto itr = value.begin(); auto end = value.end(); while( itr != end ) { @@ -505,93 +505,93 @@ namespace fc { template inline void unpack( Stream& s, std::set& value ) { - unsigned_int size; unpack( s, size ); + unsigned_int size; fc::raw::unpack( s, size ); for( uint64_t i = 0; i < size.value; ++i ) { T tmp; - unpack( s, tmp ); + fc::raw::unpack( s, tmp ); value.insert( std::move(tmp) ); } } - template + template inline void pack( Stream& s, const T& v ) { fc::raw::detail::if_reflected< typename fc::reflector::is_defined >::pack(s,v); } - template - inline void unpack( Stream& s, T& v ) + template + inline void unpack( Stream& s, T& v ) { try { fc::raw::detail::if_reflected< typename fc::reflector::is_defined >::unpack(s,v); } FC_RETHROW_EXCEPTIONS( warn, "error unpacking ${type}", ("type",fc::get_typename::name() ) ) } template - inline size_t pack_size( const T& v ) + inline size_t pack_size( const T& v ) { - datastream ps; - raw::pack(ps,v ); + datastream ps; + fc::raw::pack(ps,v ); return ps.tellp(); } template inline std::vector pack( const T& v ) { - datastream ps; - raw::pack(ps,v ); + datastream ps; + fc::raw::pack(ps,v ); std::vector vec(ps.tellp()); if( vec.size() ) { - datastream ds( vec.data(), size_t(vec.size()) ); - raw::pack(ds,v); + datastream ds( vec.data(), size_t(vec.size()) ); + fc::raw::pack(ds,v); } return vec; } template - inline T unpack( const std::vector& s ) + inline T unpack( const std::vector& s ) { try { T tmp; if( s.size() ) { - datastream ds( s.data(), size_t(s.size()) ); - raw::unpack(ds,tmp); + datastream ds( s.data(), size_t(s.size()) ); + fc::raw::unpack(ds,tmp); } return tmp; } FC_RETHROW_EXCEPTIONS( warn, "error unpacking ${type}", ("type",fc::get_typename::name() ) ) } template - inline void unpack( const std::vector& s, T& tmp ) + inline void unpack( const std::vector& s, T& tmp ) { try { if( s.size() ) { - datastream ds( s.data(), size_t(s.size()) ); - raw::unpack(ds,tmp); + datastream ds( s.data(), size_t(s.size()) ); + fc::raw::unpack(ds,tmp); } } FC_RETHROW_EXCEPTIONS( warn, "error unpacking ${type}", ("type",fc::get_typename::name() ) ) } template inline void pack( char* d, uint32_t s, const T& v ) { - datastream ds(d,s); - raw::pack(ds,v ); + datastream ds(d,s); + fc::raw::pack(ds,v ); } template - inline T unpack( const char* d, uint32_t s ) + inline T unpack( const char* d, uint32_t s ) { try { T v; datastream ds( d, s ); - raw::unpack(ds,v); + fc::raw::unpack(ds,v); return v; } FC_RETHROW_EXCEPTIONS( warn, "error unpacking ${type}", ("type",fc::get_typename::name() ) ) } template - inline void unpack( const char* d, uint32_t s, T& v ) + inline void unpack( const char* d, uint32_t s, T& v ) { try { datastream ds( d, s ); - raw::unpack(ds,v); + fc::raw::unpack(ds,v); return v; } FC_RETHROW_EXCEPTIONS( warn, "error unpacking ${type}", ("type",fc::get_typename::name() ) ) } template - struct pack_static_variant + struct pack_static_variant { Stream& stream; pack_static_variant( Stream& s ):stream(s){} @@ -599,7 +599,7 @@ namespace fc { typedef void result_type; template void operator()( const T& v )const { - pack( stream, v ); + fc::raw::pack( stream, v ); } }; @@ -612,25 +612,25 @@ namespace fc { typedef void result_type; template void operator()( T& v )const { - unpack( stream, v ); + fc::raw::unpack( stream, v ); } }; - template + template void pack( Stream& s, const static_variant& sv ) { - pack( s, unsigned_int(sv.which()) ); + fc::raw::pack( s, unsigned_int(sv.which()) ); sv.visit( pack_static_variant(s) ); } template void unpack( Stream& s, static_variant& sv ) { unsigned_int w; - unpack( s, w ); + fc::raw::unpack( s, w ); sv.set_which(w.value); sv.visit( unpack_static_variant(s) ); } - + } } // namespace fc::raw From 83b4de067a6c99704a6d21d6dfc8b1e838ddcaf7 Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Thu, 25 Feb 2016 01:53:32 -0500 Subject: [PATCH 17/17] future.cpp: Fix use-after-free bug cryptonomex/graphene#597 --- src/thread/future.cpp | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/src/thread/future.cpp b/src/thread/future.cpp index 1950086..2111584 100644 --- a/src/thread/future.cpp +++ b/src/thread/future.cpp @@ -63,18 +63,42 @@ namespace fc { _enqueue_thread(); } std::exception_ptr e; - try { thread::current().wait_until( ptr(this,true), timeout_us ); } + + // + // Create shared_ptr to take ownership of this; i.e. this will + // be deleted when p_this goes out of scope. Consequently, + // it would be Very Bad to let p_this go out of scope + // before we're done reading/writing instance variables! + // See https://github.com/cryptonomex/graphene/issues/597 + // + + ptr p_this = ptr( this, true ); + + try + { + // + // We clone p_this here because the wait_until() API requires us + // to use std::move(). I.e. wait_until() takes ownership of any + // pointer passed to it. Since we want to keep ownership ourselves, + // we need to have two shared_ptr's to this: + // + // - p_this to keep this alive until the end of the current function + // - p_this2 to be owned by wait_until() as the wait_until() API requires + // + ptr p_this2 = p_this; + thread::current().wait_until( std::move( p_this2 ), timeout_us ); + } catch (...) { e = std::current_exception(); } _dequeue_thread(); if( e ) std::rethrow_exception(e); - if( _ready ) + if( _ready ) { - if( _exceptp ) + if( _exceptp ) _exceptp->dynamic_rethrow_exception(); - return; + return; } FC_THROW_EXCEPTION( timeout_exception, "" ); }