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:
Lauri Nurmi
2016-10-25 12:01:03 +03:00
parent 3926538fea
commit 343318d73e
3 changed files with 64 additions and 17 deletions

View File

@@ -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