@ -74,7 +74,7 @@ bool fTestNet = false;
bool fNoListen = false ;
bool fNoListen = false ;
bool fLogTimestamps = false ;
bool fLogTimestamps = false ;
CMedianFilter < int64 > vTimeOffsets ( 200 , 0 ) ;
CMedianFilter < int64 > vTimeOffsets ( 200 , 0 ) ;
bool fReopenDebugLog = false ;
volatile bool fReopenDebugLog = false ;
// Init OpenSSL library multithreading support
// Init OpenSSL library multithreading support
static CCriticalSection * * ppmutexOpenSSL ;
static CCriticalSection * * ppmutexOpenSSL ;
@ -195,39 +195,54 @@ uint256 GetRandHash()
//
// OutputDebugStringF (aka printf -- there is a #define that we really
// should get rid of one day) has been broken a couple of times now
// by well-meaning people adding mutexes in the most straightforward way.
// It breaks because it may be called by global destructors during shutdown.
// Since the order of destruction of static/global objects is undefined,
// defining a mutex as a global object doesn't work (the mutex gets
// destroyed, and then some later destructor calls OutputDebugStringF,
// maybe indirectly, and you get a core dump at shutdown trying to lock
// the mutex).
static boost : : once_flag debugPrintInitFlag = BOOST_ONCE_INIT ;
// We use boost::call_once() to make sure these are initialized in
// in a thread-safe manner the first time it is called:
static FILE * fileout = NULL ;
static boost : : mutex * mutexDebugLog = NULL ;
inline int OutputDebugStringF ( const char * pszFormat , . . . )
static void DebugPrintInit ( )
{
{
int ret = 0 ;
assert ( fileout = = NULL ) ;
assert ( mutexDebugLog = = NULL ) ;
boost : : filesystem : : path pathDebug = GetDataDir ( ) / " debug.log " ;
fileout = fopen ( pathDebug . string ( ) . c_str ( ) , " a " ) ;
if ( fileout ) setbuf ( fileout , NULL ) ; // unbuffered
mutexDebugLog = new boost : : mutex ( ) ;
}
int OutputDebugStringF ( const char * pszFormat , . . . )
{
int ret = 0 ; // Returns total number of characters written
if ( fPrintToConsole )
if ( fPrintToConsole )
{
{
// print to console
// print to console
va_list arg_ptr ;
va_list arg_ptr ;
va_start ( arg_ptr , pszFormat ) ;
va_start ( arg_ptr , pszFormat ) ;
ret = vprintf ( pszFormat , arg_ptr ) ;
ret + = vprintf ( pszFormat , arg_ptr ) ;
va_end ( arg_ptr ) ;
va_end ( arg_ptr ) ;
}
}
else if ( ! fPrintToDebugger )
else if ( ! fPrintToDebugger )
{
// print to debug.log
static FILE * fileout = NULL ;
if ( ! fileout )
{
boost : : filesystem : : path pathDebug = GetDataDir ( ) / " debug.log " ;
fileout = fopen ( pathDebug . string ( ) . c_str ( ) , " a " ) ;
if ( fileout ) setbuf ( fileout , NULL ) ; // unbuffered
}
if ( fileout )
{
{
static bool fStartedNewLine = true ;
static bool fStartedNewLine = true ;
boost : : call_once ( & DebugPrintInit , debugPrintInitFlag ) ;
if ( fileout = = NULL )
return ret ;
// This routine may be called by global destructors during shutdown.
// Since the order of destruction of static/global objects is undefined,
// allocate mutexDebugLog on the heap the first time this routine
// is called to avoid crashes during shutdown.
static boost : : mutex * mutexDebugLog = NULL ;
if ( mutexDebugLog = = NULL ) mutexDebugLog = new boost : : mutex ( ) ;
boost : : mutex : : scoped_lock scoped_lock ( * mutexDebugLog ) ;
boost : : mutex : : scoped_lock scoped_lock ( * mutexDebugLog ) ;
// reopen the log file, if requested
// reopen the log file, if requested
@ -240,7 +255,7 @@ inline int OutputDebugStringF(const char* pszFormat, ...)
// Debug print useful for profiling
// Debug print useful for profiling
if ( fLogTimestamps & & fStartedNewLine )
if ( fLogTimestamps & & fStartedNewLine )
fprintf ( fileout , " %s " , DateTimeStrFormat ( " %Y-%m-%d %H:%M:%S " , GetTime ( ) ) . c_str ( ) ) ;
ret + = fprintf ( fileout , " %s " , DateTimeStrFormat ( " %Y-%m-%d %H:%M:%S " , GetTime ( ) ) . c_str ( ) ) ;
if ( pszFormat [ strlen ( pszFormat ) - 1 ] = = ' \n ' )
if ( pszFormat [ strlen ( pszFormat ) - 1 ] = = ' \n ' )
fStartedNewLine = true ;
fStartedNewLine = true ;
else
else
@ -248,10 +263,9 @@ inline int OutputDebugStringF(const char* pszFormat, ...)
va_list arg_ptr ;
va_list arg_ptr ;
va_start ( arg_ptr , pszFormat ) ;
va_start ( arg_ptr , pszFormat ) ;
ret = vfprintf ( fileout , pszFormat , arg_ptr ) ;
ret + = vfprintf ( fileout , pszFormat , arg_ptr ) ;
va_end ( arg_ptr ) ;
va_end ( arg_ptr ) ;
}
}
}
# ifdef WIN32
# ifdef WIN32
if ( fPrintToDebugger )
if ( fPrintToDebugger )
@ -273,6 +287,7 @@ inline int OutputDebugStringF(const char* pszFormat, ...)
{
{
OutputDebugStringA ( buffer . substr ( line_start , line_end - line_start ) . c_str ( ) ) ;
OutputDebugStringA ( buffer . substr ( line_start , line_end - line_start ) . c_str ( ) ) ;
line_start = line_end + 1 ;
line_start = line_end + 1 ;
ret + = line_end - line_start ;
}
}
buffer . erase ( 0 , line_start ) ;
buffer . erase ( 0 , line_start ) ;
}
}