Add a thread-safe wxSysErrorMsgStr()
Implement wxSysErrorMsg's functionality without using static buffers; have the caller provide the buffer. When the caller uses the original API and does not provide a buffer, a static buffer is still used. wxSysErrorMsgStr() returns a wxString. Also use strerror_r() instead of strerror() on platforms other than MSW.
This commit is contained in:
parent
3926538fea
commit
343318d73e
@ -1188,6 +1188,9 @@ WXDLLIMPEXP_BASE unsigned long wxSysErrorCode();
|
||||
// return the error message for given (or last if 0) error code
|
||||
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
|
||||
// stdio, iostream &c for log messages for easy redirection
|
||||
@ -1393,6 +1396,7 @@ public:
|
||||
// Dummy macros to replace some functions.
|
||||
#define wxSysErrorCode() (unsigned long)0
|
||||
#define wxSysErrorMsg( X ) (const wxChar*)NULL
|
||||
#define wxSysErrorMsgStr( X ) wxEmptyString
|
||||
|
||||
// Fake symbolic trace masks... for those that are used frequently
|
||||
#define wxTRACE_OleCalls wxEmptyString // OLE interface calls
|
||||
|
@ -1226,6 +1226,23 @@ unsigned long wxSysErrorCode();
|
||||
@a errCode is 0 (default), the last error code (as returned by
|
||||
wxSysErrorCode()) is used.
|
||||
|
||||
Use this function instead of wxSysErrorMsg(), as the latter one is not
|
||||
thread-safe.
|
||||
|
||||
@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()
|
||||
|
||||
@header{wx/log.h}
|
||||
|
@ -48,6 +48,8 @@
|
||||
// other standard headers
|
||||
#include <errno.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <time.h>
|
||||
@ -1055,15 +1057,12 @@ unsigned long wxSysErrorCode()
|
||||
#endif //Win/Unix
|
||||
}
|
||||
|
||||
// get error message from system
|
||||
const wxChar *wxSysErrorMsg(unsigned long nErrCode)
|
||||
static const wxChar* GetSysErrorMsg(wxChar* szBuf, size_t len, unsigned long nErrCode)
|
||||
{
|
||||
if ( nErrCode == 0 )
|
||||
nErrCode = wxSysErrorCode();
|
||||
|
||||
#if defined(__WINDOWS__)
|
||||
static wxChar s_szBuf[1024];
|
||||
|
||||
// get error message from system
|
||||
LPVOID lpMsgBuf;
|
||||
if ( ::FormatMessage
|
||||
@ -1079,8 +1078,8 @@ const wxChar *wxSysErrorMsg(unsigned long nErrCode)
|
||||
{
|
||||
// if this happens, something is seriously wrong, so don't use _() here
|
||||
// for safety
|
||||
wxSprintf(s_szBuf, wxS("unknown error %lx"), nErrCode);
|
||||
return s_szBuf;
|
||||
wxSprintf(szBuf, wxS("unknown error %lx"), nErrCode);
|
||||
return szBuf;
|
||||
}
|
||||
|
||||
|
||||
@ -1088,34 +1087,61 @@ const wxChar *wxSysErrorMsg(unsigned long nErrCode)
|
||||
// Crashes on SmartPhone (FIXME)
|
||||
if( lpMsgBuf != 0 )
|
||||
{
|
||||
wxStrlcpy(s_szBuf, (const wxChar *)lpMsgBuf, WXSIZEOF(s_szBuf));
|
||||
wxStrlcpy(szBuf, (const wxChar *)lpMsgBuf, len);
|
||||
|
||||
LocalFree(lpMsgBuf);
|
||||
|
||||
// returned string is ended with '\r\n' - bad
|
||||
size_t len = wxStrlen(s_szBuf);
|
||||
size_t len = wxStrlen(szBuf);
|
||||
if ( len >= 2 ) {
|
||||
// truncate string
|
||||
if ( s_szBuf[len - 2] == wxS('\r') )
|
||||
s_szBuf[len - 2] = wxS('\0');
|
||||
if ( szBuf[len - 2] == wxS('\r') )
|
||||
szBuf[len - 2] = wxS('\0');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s_szBuf[0] = wxS('\0');
|
||||
szBuf[0] = wxS('\0');
|
||||
}
|
||||
|
||||
return s_szBuf;
|
||||
return szBuf;
|
||||
#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
|
||||
static wchar_t s_wzBuf[1024];
|
||||
wxConvCurrent->MB2WC(s_wzBuf, strerror((int)nErrCode),
|
||||
WXSIZEOF(s_wzBuf) - 1);
|
||||
return s_wzBuf;
|
||||
wxConvCurrent->MB2WC(szBuf, errorMsg, len - 1);
|
||||
szBuf[len - 1] = wxS('\0');
|
||||
#else
|
||||
return strerror((int)nErrCode);
|
||||
wxStrlcpy(szBuf, errorMsg, len);
|
||||
#endif
|
||||
return szBuf;
|
||||
#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
|
||||
|
Loading…
Reference in New Issue
Block a user