system: reduce chance of message() throwing in response to ticket #2098

[SVN r49093]
This commit is contained in:
Beman Dawes
2008-10-01 18:57:48 +00:00
parent 84ff2d0f04
commit 463cefcf94

View File

@@ -61,11 +61,12 @@ namespace
const char * generic_error_category::name() const const char * generic_error_category::name() const
{ {
return "GENERIC"; return "generic";
} }
std::string generic_error_category::message( int ev ) const std::string generic_error_category::message( int ev ) const
{ {
static std::string unknown_err( "Unknown error" );
// strerror_r is preferred because it is always thread safe, // strerror_r is preferred because it is always thread safe,
// however, we fallback to strerror in certain cases because: // however, we fallback to strerror in certain cases because:
// -- Windows doesn't provide strerror_r. // -- Windows doesn't provide strerror_r.
@@ -81,15 +82,19 @@ namespace
|| (defined(__osf__) && !defined(_REENTRANT))\ || (defined(__osf__) && !defined(_REENTRANT))\
|| (defined(__vms)) || (defined(__vms))
const char * c_str = std::strerror( ev ); const char * c_str = std::strerror( ev );
return std::string( c_str ? c_str : "Unknown error" ); return c_str
# else ? std::string( c_str )
: unknown_err;
# else // use strerror_r
char buf[64]; char buf[64];
char * bp = buf; char * bp = buf;
std::size_t sz = sizeof(buf); std::size_t sz = sizeof(buf);
# if defined(__CYGWIN__) || defined(__USE_GNU) # if defined(__CYGWIN__) || defined(__USE_GNU)
// Oddball version of strerror_r // Oddball version of strerror_r
const char * c_str = strerror_r( ev, bp, sz ); const char * c_str = strerror_r( ev, bp, sz );
return std::string( c_str ? c_str : "Unknown error" ); return c_str
? std::string( c_str )
: unknown_err;
# else # else
// POSIX version of strerror_r // POSIX version of strerror_r
int result; int result;
@@ -100,7 +105,9 @@ namespace
# if defined (__sgi) # if defined (__sgi)
const char * c_str = strerror( ev ); const char * c_str = strerror( ev );
result = 0; result = 0;
return std::string( c_str ? c_str : "Unknown error" ); return c_str
? std::string( c_str )
: unknown_err;
# else # else
result = strerror_r( ev, bp, sz ); result = strerror_r( ev, bp, sz );
# endif # endif
@@ -113,26 +120,27 @@ namespace
result = errno; result = errno;
# endif # endif
if ( result != ERANGE ) break; if ( result != ERANGE ) break;
if ( sz > sizeof(buf) ) std::free( bp ); if ( sz > sizeof(buf) ) std::free( bp );
sz *= 2; sz *= 2;
if ( (bp = static_cast<char*>(std::malloc( sz ))) == 0 ) if ( (bp = static_cast<char*>(std::malloc( sz ))) == 0 )
return std::string( "ENOMEM" ); return std::string( "ENOMEM" );
} }
} }
std::string msg();
try try
{ {
std::string msg( ( result == invalid_argument ) ? "Unknown error" : bp ); msg = ( ( result == invalid_argument ) ? "Unknown error" : bp );
if ( sz > sizeof(buf) ) std::free( bp );
sz = 0;
return msg;
} }
catch(...) catch(...)
{ {
if ( sz > sizeof(buf) ) std::free( bp ); // just eat the exception
throw;
} }
# endif
# endif if ( sz > sizeof(buf) ) std::free( bp );
sz = 0;
return msg;
# endif // else POSIX version of strerror_r
# endif // else use strerror_r
} }
// system_error_category implementation --------------------------------// // system_error_category implementation --------------------------------//