fix cin crash

This commit is contained in:
Daniel Larimer 2012-12-18 14:08:40 -05:00
parent 274146229e
commit afbbf4e8db
8 changed files with 63 additions and 22 deletions

View file

@ -51,8 +51,7 @@ set( sources
src/url.cpp src/url.cpp
src/process.cpp src/process.cpp
src/http_connection.cpp src/http_connection.cpp
src/url.cpp src/http_server.cpp
# src/http_server.cpp
src/json_rpc_connection.cpp src/json_rpc_connection.cpp
src/json_rpc_stream_connection.cpp src/json_rpc_stream_connection.cpp
src/json_rpc_tcp_connection.cpp src/json_rpc_tcp_connection.cpp

View file

@ -44,6 +44,7 @@ namespace fc {
}; };
struct cin_t : virtual public istream { struct cin_t : virtual public istream {
~cin_t();
virtual size_t readsome( char* buf, size_t len ); virtual size_t readsome( char* buf, size_t len );
virtual istream& read( char* buf, size_t len ); virtual istream& read( char* buf, size_t len );
virtual bool eof()const; virtual bool eof()const;

View file

@ -1,5 +1,4 @@
#ifndef FC_MUTEX_HPP_ #pragma once
#define FC_MUTEX_HPP_
#include <fc/time.hpp> #include <fc/time.hpp>
#include <fc/spin_yield_lock.hpp> #include <fc/spin_yield_lock.hpp>
@ -107,4 +106,3 @@ namespace fc {
} // namespace fc } // namespace fc
#endif // MACE_CMT_MUTEX_HPP_

View file

@ -0,0 +1,11 @@
#pragma once
namespace fc {
template<typename T>
class scoped_lock {
public:
scoped_lock( T& l ):_lock(l) { _lock.lock(); }
~scoped_lock() { _lock.unlock(); }
T& _lock;
};
}

View file

@ -28,11 +28,11 @@ namespace fc {
template<typename Other> template<typename Other>
shared_ptr( const shared_ptr<Other>& o ) shared_ptr( const shared_ptr<Other>& o )
:_ptr(o.get()) { :_ptr(o.get()) {
if(_ptr) _ptr->retain(); if(_ptr != nullptr ) _ptr->retain();
} }
shared_ptr( T* t, bool inc = false ) shared_ptr( T* t, bool inc = false )
:_ptr(t) { if( inc ) t->retain(); } :_ptr(t) { if( inc && t != nullptr) t->retain(); }
shared_ptr():_ptr(nullptr){} shared_ptr():_ptr(nullptr){}
@ -42,25 +42,27 @@ namespace fc {
} }
shared_ptr( shared_ptr& p ) { shared_ptr( shared_ptr& p ) {
_ptr = p._ptr; _ptr = p._ptr;
if( _ptr ) _ptr->retain(); if( _ptr != nullptr ) _ptr->retain();
} }
shared_ptr( shared_ptr&& p ) { shared_ptr( shared_ptr&& p ) {
_ptr = p._ptr; _ptr = p._ptr;
p._ptr = nullptr; p._ptr = nullptr;
} }
~shared_ptr() { if( _ptr ) { _ptr->release(); } } ~shared_ptr() { if( nullptr != _ptr ) { _ptr->release(); } }
shared_ptr& reset( T* v = 0, bool inc = false ) { shared_ptr& reset( T* v = nullptr, bool inc = false ) {
if( v == _ptr ) return *this; if( v == _ptr ) return *this;
if( _ptr ) _ptr->release(); if( inc && nullptr != v ) v->retain();
if( nullptr != _ptr ) _ptr->release();
_ptr = v; _ptr = v;
if( _ptr && inc ) _ptr->retain();
return *this; return *this;
} }
shared_ptr& operator=(const shared_ptr& p ) { shared_ptr& operator=(const shared_ptr& p ) {
shared_ptr tmp(p); if( _ptr == p._ptr ) return *this;
fc_swap(tmp._ptr,_ptr); if( _ptr != nullptr ) _ptr->release();
_ptr = p._ptr;
if( _ptr != nullptr ) _ptr->retain();
return *this; return *this;
} }
shared_ptr& operator=(shared_ptr&& p ) { shared_ptr& operator=(shared_ptr&& p ) {

View file

@ -1,5 +1,4 @@
#ifndef _FC_SPIN_YIELD_LOCK_HPP_ #pragma once
#define _FC_SPIN_YIELD_LOCK_HPP_
namespace boost { namespace boost {
template<typename T> class atomic; template<typename T> class atomic;
@ -38,4 +37,3 @@ namespace fc {
} // namespace fc } // namespace fc
#endif // _FC_SPIN_YIELD_LOCK_HPP_

View file

@ -4,7 +4,10 @@
#include <iostream> #include <iostream>
#include <string.h> #include <string.h>
#include <fc/log.hpp> #include <fc/log.hpp>
#include <fc/mutex.hpp>
#include <fc/scoped_lock.hpp>
#include <string> #include <string>
#include <boost/thread/mutex.hpp>
namespace fc { namespace fc {
ostream& operator<<( ostream& o, const char* v ) { ostream& operator<<( ostream& o, const char* v ) {
@ -32,18 +35,27 @@ namespace fc {
buf[write_pos&0xfffff] = c; buf[write_pos&0xfffff] = c;
++write_pos; ++write_pos;
auto tmp = read_ready; // copy read_ready because it is accessed from multiple threads fc::promise<void>::ptr tmp;
{ // copy read_ready because it is accessed from multiple threads
fc::scoped_lock<boost::mutex> lock( read_ready_mutex );
tmp = read_ready;
}
if( tmp && !tmp->ready() ) { if( tmp && !tmp->ready() ) {
tmp->set_value(); tmp->set_value();
} }
std::cin.read(&c,1); std::cin.read(&c,1);
} }
eof = true; eof = true;
auto tmp = read_ready; // copy read_ready because it is accessed from multiple threads fc::promise<void>::ptr tmp;
{ // copy read_ready because it is accessed from multiple threads
fc::scoped_lock<boost::mutex> lock( read_ready_mutex );
tmp = read_ready;
}
if( tmp && !tmp->ready() ) { if( tmp && !tmp->ready() ) {
tmp->set_value(); tmp->set_value();
} }
} }
boost::mutex read_ready_mutex;
fc::promise<void>::ptr read_ready; fc::promise<void>::ptr read_ready;
fc::promise<void>::ptr write_ready; fc::promise<void>::ptr write_ready;
@ -105,17 +117,34 @@ namespace fc {
return u; return u;
} }
cin_t::~cin_t() {
wlog( "~cin_t" );
/*
cin_buffer& b = get_cin_buffer();
if( b.read_ready ) {
b.read_ready->wait();
}
*/
}
istream& cin_t::read( char* buf, size_t len ) { istream& cin_t::read( char* buf, size_t len ) {
cin_buffer& b = get_cin_buffer(); cin_buffer& b = get_cin_buffer();
do { do {
while( !b.eof && (b.write_pos - b.read_pos)==0 ){ while( !b.eof && (b.write_pos - b.read_pos)==0 ){
// wait for more... // wait for more...
fc::promise<void>::ptr rr( new fc::promise<void>() ); fc::promise<void>::ptr rr( new fc::promise<void>() );
b.read_ready = rr; // b.read_ready = rr;
{ // copy read_ready because it is accessed from multiple threads
fc::scoped_lock<boost::mutex> lock( b.read_ready_mutex );
b.read_ready = rr;
}
if( b.write_pos - b.read_pos == 0 ) { if( b.write_pos - b.read_pos == 0 ) {
rr->wait(); rr->wait();
} }
b.read_ready.reset(); b.read_ready.reset();
{ // copy read_ready because it is accessed from multiple threads
fc::scoped_lock<boost::mutex> lock( b.read_ready_mutex );
b.read_ready.reset();
}
} }
if( b.eof ) return *this; if( b.eof ) return *this;
size_t r = readsome( buf, len ); size_t r = readsome( buf, len );

View file

@ -5,9 +5,12 @@
namespace fc { namespace fc {
retainable::retainable() retainable::retainable()
:_ref_count(1) { } :_ref_count(1) {
static_assert( sizeof(_ref_count) == sizeof(boost::atomic<int32_t>), "failed to reserve enough space" );
}
retainable::~retainable() { retainable::~retainable() {
assert( _ref_count <= 0 );
assert( _ref_count == 0 ); assert( _ref_count == 0 );
} }
void retainable::retain() { void retainable::retain() {
@ -15,8 +18,8 @@ namespace fc {
} }
void retainable::release() { void retainable::release() {
if( 1 == ((boost::atomic<int32_t>*)&_ref_count)->fetch_sub(1, boost::memory_order_release ) ) {
boost::atomic_thread_fence(boost::memory_order_acquire); boost::atomic_thread_fence(boost::memory_order_acquire);
if( 1 == ((boost::atomic<int32_t>*)&_ref_count)->fetch_sub(1, boost::memory_order_release ) ) {
delete this; delete this;
} }
} }