Merge branch 'syserrormsgstr'

Add thread-safe wxSysErrorMsgStr() to be used instead of wxSysErrorMsg().

Closes https://github.com/wxWidgets/wxWidgets/pull/343
This commit is contained in:
Vadim Zeitlin
2016-11-27 15:08:31 +01:00
8 changed files with 83 additions and 35 deletions

View File

@@ -1188,6 +1188,9 @@ WXDLLIMPEXP_BASE unsigned long wxSysErrorCode();
// return the error message for given (or last if 0) error code // return the error message for given (or last if 0) error code
WXDLLIMPEXP_BASE const wxChar* wxSysErrorMsg(unsigned long nErrCode = 0); WXDLLIMPEXP_BASE const wxChar* wxSysErrorMsg(unsigned long nErrCode = 0);
// return the error message for given (or last if 0) error code
WXDLLIMPEXP_BASE wxString wxSysErrorMsgStr(unsigned long nErrCode = 0);
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// define wxLog<level>() functions which can be used by application instead of // define wxLog<level>() functions which can be used by application instead of
// stdio, iostream &c for log messages for easy redirection // stdio, iostream &c for log messages for easy redirection
@@ -1393,6 +1396,7 @@ public:
// Dummy macros to replace some functions. // Dummy macros to replace some functions.
#define wxSysErrorCode() (unsigned long)0 #define wxSysErrorCode() (unsigned long)0
#define wxSysErrorMsg( X ) (const wxChar*)NULL #define wxSysErrorMsg( X ) (const wxChar*)NULL
#define wxSysErrorMsgStr( X ) wxEmptyString
// Fake symbolic trace masks... for those that are used frequently // Fake symbolic trace masks... for those that are used frequently
#define wxTRACE_OleCalls wxEmptyString // OLE interface calls #define wxTRACE_OleCalls wxEmptyString // OLE interface calls
@@ -1475,13 +1479,13 @@ wxSafeShowMessage(const wxString& title, const wxString& text);
#define wxLogApiError(api, rc) \ #define wxLogApiError(api, rc) \
wxLogDebug(wxT("%s(%d): '%s' failed with error 0x%08lx (%s)."), \ wxLogDebug(wxT("%s(%d): '%s' failed with error 0x%08lx (%s)."), \
__FILE__, __LINE__, api, \ __FILE__, __LINE__, api, \
(long)rc, wxSysErrorMsg(rc)) (long)rc, wxSysErrorMsgStr(rc))
#else // !VC++ #else // !VC++
#define wxLogApiError(api, rc) \ #define wxLogApiError(api, rc) \
wxLogDebug(wxT("In file %s at line %d: '%s' failed with ") \ wxLogDebug(wxT("In file %s at line %d: '%s' failed with ") \
wxT("error 0x%08lx (%s)."), \ wxT("error 0x%08lx (%s)."), \
__FILE__, __LINE__, api, \ __FILE__, __LINE__, api, \
(long)rc, wxSysErrorMsg(rc)) (long)rc, wxSysErrorMsgStr(rc))
#endif // VC++/!VC++ #endif // VC++/!VC++
#define wxLogLastError(api) wxLogApiError(api, wxSysErrorCode()) #define wxLogLastError(api) wxLogApiError(api, wxSysErrorCode())

View File

@@ -1215,7 +1215,7 @@ void wxSafeShowMessage(const wxString& title, const wxString& text);
Returns the error code from the last system call. This function uses Returns the error code from the last system call. This function uses
@c errno on Unix platforms and @c GetLastError under Win32. @c errno on Unix platforms and @c GetLastError under Win32.
@see wxSysErrorMsg(), wxLogSysError() @see wxSysErrorMsgStr(), wxLogSysError()
@header{wx/log.h} @header{wx/log.h}
*/ */
@@ -1226,6 +1226,25 @@ unsigned long wxSysErrorCode();
@a errCode is 0 (default), the last error code (as returned by @a errCode is 0 (default), the last error code (as returned by
wxSysErrorCode()) is used. wxSysErrorCode()) is used.
Use this function instead of wxSysErrorMsg(), as the latter one is not
thread-safe.
@since 3.1.0
@see wxSysErrorCode(), wxLogSysError()
@header{wx/log.h}
*/
wxString wxSysErrorMsgStr(unsigned long errCode = 0);
/**
Returns the error message corresponding to the given system error code. If
@a errCode is 0 (default), the last error code (as returned by
wxSysErrorCode()) is used.
Use wxSysErrorMsgStr() instead of this function especially in a
multi-threaded application.
@see wxSysErrorCode(), wxLogSysError() @see wxSysErrorCode(), wxLogSysError()
@header{wx/log.h} @header{wx/log.h}
@@ -1440,7 +1459,7 @@ void wxVLogStatus(const char* formatString, va_list argPtr);
form of this function takes the error code explicitly as the first form of this function takes the error code explicitly as the first
argument. argument.
@see wxSysErrorCode(), wxSysErrorMsg() @see wxSysErrorCode(), wxSysErrorMsgStr()
@header{wx/log.h} @header{wx/log.h}
*/ */

View File

@@ -48,6 +48,8 @@
// other standard headers // other standard headers
#include <errno.h> #include <errno.h>
#include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <time.h> #include <time.h>
@@ -416,7 +418,7 @@ wxLog::CallDoLogNow(wxLogLevel level,
{ {
const long err = static_cast<long>(num); const long err = static_cast<long>(num);
suffix.Printf(_(" (error %ld: %s)"), err, wxSysErrorMsg(err)); suffix.Printf(_(" (error %ld: %s)"), err, wxSysErrorMsgStr(err));
} }
#if wxUSE_LOG_TRACE #if wxUSE_LOG_TRACE
@@ -1055,15 +1057,12 @@ unsigned long wxSysErrorCode()
#endif //Win/Unix #endif //Win/Unix
} }
// get error message from system static const wxChar* GetSysErrorMsg(wxChar* szBuf, size_t len, unsigned long nErrCode)
const wxChar *wxSysErrorMsg(unsigned long nErrCode)
{ {
if ( nErrCode == 0 ) if ( nErrCode == 0 )
nErrCode = wxSysErrorCode(); nErrCode = wxSysErrorCode();
#if defined(__WINDOWS__) #if defined(__WINDOWS__)
static wxChar s_szBuf[1024];
// get error message from system // get error message from system
LPVOID lpMsgBuf; LPVOID lpMsgBuf;
if ( ::FormatMessage if ( ::FormatMessage
@@ -1079,8 +1078,8 @@ const wxChar *wxSysErrorMsg(unsigned long nErrCode)
{ {
// if this happens, something is seriously wrong, so don't use _() here // if this happens, something is seriously wrong, so don't use _() here
// for safety // for safety
wxSprintf(s_szBuf, wxS("unknown error %lx"), nErrCode); wxSprintf(szBuf, wxS("unknown error %lx"), nErrCode);
return s_szBuf; return szBuf;
} }
@@ -1088,35 +1087,61 @@ const wxChar *wxSysErrorMsg(unsigned long nErrCode)
// Crashes on SmartPhone (FIXME) // Crashes on SmartPhone (FIXME)
if( lpMsgBuf != 0 ) if( lpMsgBuf != 0 )
{ {
wxStrlcpy(s_szBuf, (const wxChar *)lpMsgBuf, WXSIZEOF(s_szBuf)); wxStrlcpy(szBuf, (const wxChar *)lpMsgBuf, len);
LocalFree(lpMsgBuf); LocalFree(lpMsgBuf);
// returned string is capitalized and ended with '\r\n' - bad // returned string is ended with '\r\n' - bad
s_szBuf[0] = (wxChar)wxTolower(s_szBuf[0]); size_t len = wxStrlen(szBuf);
size_t len = wxStrlen(s_szBuf); if ( len >= 2 ) {
if ( len > 0 ) {
// truncate string // truncate string
if ( s_szBuf[len - 2] == wxS('\r') ) if ( szBuf[len - 2] == wxS('\r') )
s_szBuf[len - 2] = wxS('\0'); szBuf[len - 2] = wxS('\0');
} }
} }
else else
{ {
s_szBuf[0] = wxS('\0'); szBuf[0] = wxS('\0');
} }
return s_szBuf; return szBuf;
#else // !__WINDOWS__ #else // !__WINDOWS__
char buffer[1024];
char *errorMsg = buffer;
#ifdef _GNU_SOURCE // GNU-specific strerror_r
// GNU's strerror_r has a weird interface -- it doesn't
// necessarily copy anything to the buffer given; use return
// value instead.
errorMsg = strerror_r((int)nErrCode, buffer, sizeof(buffer));
#else // XSI-compliant strerror_r
strerror_r((int)nErrCode, buffer, sizeof(buffer));
#endif
// at this point errorMsg might not point to buffer anymore
szBuf[0] = wxS('\0');
#if wxUSE_UNICODE #if wxUSE_UNICODE
static wchar_t s_wzBuf[1024]; wxConvCurrent->MB2WC(szBuf, errorMsg, len - 1);
wxConvCurrent->MB2WC(s_wzBuf, strerror((int)nErrCode), szBuf[len - 1] = wxS('\0');
WXSIZEOF(s_wzBuf) - 1);
return s_wzBuf;
#else #else
return strerror((int)nErrCode); wxStrlcpy(szBuf, errorMsg, len);
#endif #endif
return szBuf;
#endif // __WINDOWS__/!__WINDOWS__ #endif // __WINDOWS__/!__WINDOWS__
} }
// get error message from system
const wxChar *wxSysErrorMsg(unsigned long nErrCode)
{
static wxChar s_szBuf[1024];
return GetSysErrorMsg(s_szBuf, WXSIZEOF(s_szBuf), nErrCode);
}
// get error message from system as wxString
wxString wxSysErrorMsgStr(unsigned long nErrCode)
{
wxChar szBuf[1024];
return GetSysErrorMsg(szBuf, WXSIZEOF(szBuf), nErrCode);
}
#endif // wxUSE_LOG #endif // wxUSE_LOG

View File

@@ -2411,7 +2411,7 @@ wxMBConv_iconv::ToWChar(wchar_t *dst, size_t dstLen,
if (ICONV_FAILED(cres, srcLen)) if (ICONV_FAILED(cres, srcLen))
{ {
//VS: it is ok if iconv fails, hence trace only //VS: it is ok if iconv fails, hence trace only
wxLogTrace(TRACE_STRCONV, wxT("iconv failed: %s"), wxSysErrorMsg(wxSysErrorCode())); wxLogTrace(TRACE_STRCONV, wxT("iconv failed: %s"), wxSysErrorMsgStr(wxSysErrorCode()));
return wxCONV_FAILED; return wxCONV_FAILED;
} }
@@ -2479,7 +2479,7 @@ size_t wxMBConv_iconv::FromWChar(char *dst, size_t dstLen,
if (ICONV_FAILED(cres, inbuflen)) if (ICONV_FAILED(cres, inbuflen))
{ {
wxLogTrace(TRACE_STRCONV, wxT("iconv failed: %s"), wxSysErrorMsg(wxSysErrorCode())); wxLogTrace(TRACE_STRCONV, wxT("iconv failed: %s"), wxSysErrorMsgStr(wxSysErrorCode()));
return wxCONV_FAILED; return wxCONV_FAILED;
} }

View File

@@ -212,7 +212,7 @@ const wxString& wxDbgHelpDLL::GetErrorMessage()
void wxDbgHelpDLL::LogError(const wxChar *func) void wxDbgHelpDLL::LogError(const wxChar *func)
{ {
::OutputDebugString(wxString::Format(wxT("dbghelp: %s() failed: %s\r\n"), ::OutputDebugString(wxString::Format(wxT("dbghelp: %s() failed: %s\r\n"),
func, wxSysErrorMsg(::GetLastError())).t_str()); func, wxSysErrorMsgStr(::GetLastError())).t_str());
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@@ -470,7 +470,7 @@ wxString wxDialUpManagerMSW::GetErrorString(DWORD error)
{ {
case ERROR_INVALID_PARAMETER: case ERROR_INVALID_PARAMETER:
// this was a standard Win32 error probably // this was a standard Win32 error probably
return wxString(wxSysErrorMsg(error)); return wxSysErrorMsgStr(error);
default: default:
{ {
@@ -1258,7 +1258,7 @@ static DWORD wxRasMonitorThread(wxRasThreadData *data)
( (
wxT("WaitForMultipleObjects(RasMonitor) failed: 0x%08lx (%s)"), wxT("WaitForMultipleObjects(RasMonitor) failed: 0x%08lx (%s)"),
err, err,
wxSysErrorMsg(err) wxSysErrorMsgStr(err)
); );
// no sense in continuing, who knows if the handles we're // no sense in continuing, who knows if the handles we're

View File

@@ -27,7 +27,7 @@
#include "wx/secretstore.h" #include "wx/secretstore.h"
#include "wx/private/secretstore.h" #include "wx/private/secretstore.h"
#include "wx/log.h" // wxSysErrorMsg() #include "wx/log.h" // wxSysErrorMsgStr()
// Somewhat surprisingly, wincred.h is not self-contained and relies on some // Somewhat surprisingly, wincred.h is not self-contained and relies on some
// standard Windows macros being defined without including the headers defining // standard Windows macros being defined without including the headers defining
@@ -84,7 +84,7 @@ public:
if ( !::CredWrite(&cred, 0) ) if ( !::CredWrite(&cred, 0) )
{ {
errmsg = wxSysErrorMsg(); errmsg = wxSysErrorMsgStr();
return false; return false;
} }
@@ -103,7 +103,7 @@ public:
// Not having the password for this service/user combination is not // Not having the password for this service/user combination is not
// an error, but anything else is. // an error, but anything else is.
if ( ::GetLastError() != ERROR_NOT_FOUND ) if ( ::GetLastError() != ERROR_NOT_FOUND )
errmsg = wxSysErrorMsg(); errmsg = wxSysErrorMsgStr();
return NULL; return NULL;
} }
@@ -123,7 +123,7 @@ public:
{ {
// Same logic as in Load() above. // Same logic as in Load() above.
if ( ::GetLastError() != ERROR_NOT_FOUND ) if ( ::GetLastError() != ERROR_NOT_FOUND )
errmsg = wxSysErrorMsg(); errmsg = wxSysErrorMsgStr();
return false; return false;
} }

View File

@@ -1371,7 +1371,7 @@ void WXDLLIMPEXP_BASE wxWakeUpMainThread()
wxS("Failed to wake up main thread: PostThreadMessage(WM_NULL) ") wxS("Failed to wake up main thread: PostThreadMessage(WM_NULL) ")
wxS("failed with error 0x%08lx (%s)."), wxS("failed with error 0x%08lx (%s)."),
ec, ec,
wxSysErrorMsg(ec) wxSysErrorMsgStr(ec)
); );
} }
} }