Logging: Change arguments of message handler to avoid conversions

Introduce a new QtMessageHandler that takes QString instead of
char *: This avoids converting to local8bit , only to convert it back
to utf16 for Windows.

The old QMessageHandler is kept for a transition period, but will
be removed before Qt 5.0.

Also fix qEmergencyOut (that is called in OOM situations) to not rely
on the default message handler.

Change-Id: Iee0ce5838f97175c98788b847964273dd22d4a37
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Kai Koehne 2012-04-02 13:48:06 +02:00 committed by Qt by Nokia
parent a3f90fd44f
commit d9a1c2dff8
8 changed files with 160 additions and 94 deletions

View File

@ -246,20 +246,21 @@ const TInputType &myMin(const TInputType &value1, const TInputType &value2)
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const char *msg) void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{ {
QByteArray localMsg = msg.toLocal8Bit();
switch (type) { switch (type) {
case QtDebugMsg: case QtDebugMsg:
fprintf(stderr, "Debug: %s (%s:%u, %s)\n", msg, context.file, context.line, context.function); fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break; break;
case QtWarningMsg: case QtWarningMsg:
fprintf(stderr, "Warning: %s (%s:%u, %s)\n", msg, context.file, context.line, context.function); fprintf(stderr, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break; break;
case QtCriticalMsg: case QtCriticalMsg:
fprintf(stderr, "Critical: %s (%s:%u, %s)\n", msg, context.file, context.line, context.function); fprintf(stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break; break;
case QtFatalMsg: case QtFatalMsg:
fprintf(stderr, "Fatal: %s (%s:%u, %s)\n", msg, context.file, context.line, context.function); fprintf(stderr, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
abort(); abort();
} }
} }

View File

@ -440,7 +440,7 @@ QT_BEGIN_NAMESPACE
Finally, the QtMsgType definition identifies the various messages Finally, the QtMsgType definition identifies the various messages
that can be generated and sent to a Qt message handler; that can be generated and sent to a Qt message handler;
QMessageHandler is a type definition for a pointer to a function with QtMessageHandler is a type definition for a pointer to a function with
the signature the signature
\c {void myMessageHandler(QtMsgType, const QMessageLogContext &, const char *)}. \c {void myMessageHandler(QtMsgType, const QMessageLogContext &, const char *)}.
QMessageLogContext class contains the line, file, and function the QMessageLogContext class contains the line, file, and function the
@ -476,7 +476,7 @@ QT_BEGIN_NAMESPACE
accept a \l qreal value as their argument returning the value accept a \l qreal value as their argument returning the value
rounded up to the nearest integer and 64-bit integer respectively, rounded up to the nearest integer and 64-bit integer respectively,
the qInstallMessageHandler() function which installs the given the qInstallMessageHandler() function which installs the given
QMessageHandler, and the qVersion() function which returns the QtMessageHandler, and the qVersion() function which returns the
version number of Qt at run-time as a string. version number of Qt at run-time as a string.
\section1 Macros \section1 Macros
@ -694,7 +694,7 @@ QT_BEGIN_NAMESPACE
\value QtSystemMsg \value QtSystemMsg
\sa QMessageHandler, qInstallMessageHandler() \sa QtMessageHandler, qInstallMessageHandler()
*/ */
/*! \typedef QFunctionPointer /*! \typedef QFunctionPointer
@ -3026,12 +3026,12 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters)
\snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 7 \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 7
This typedef is deprecated, you should use QMessageHandler instead. This typedef is deprecated, you should use QtMessageHandler instead.
\sa QtMsgType, QMessageHandler, qInstallMsgHandler(), qInstallMessageHandler() \sa QtMsgType, QtMessageHandler, qInstallMsgHandler(), qInstallMessageHandler()
*/ */
/*! /*!
\typedef QMessageHandler \typedef QtMessageHandler
\relates <QtGlobal> \relates <QtGlobal>
\since 5.0 \since 5.0
@ -3044,7 +3044,7 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters)
*/ */
/*! /*!
\fn QMessageHandler qInstallMessageHandler(QMessageHandler handler) \fn QtMessageHandler qInstallMessageHandler(QtMessageHandler handler)
\relates <QtGlobal> \relates <QtGlobal>
\since 5.0 \since 5.0
@ -3074,7 +3074,7 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters)
\snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 23 \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 23
\sa QMessageHandler, QtMsgType, qDebug(), qWarning(), qCritical(), qFatal(), \sa QtMessageHandler, QtMsgType, qDebug(), qWarning(), qCritical(), qFatal(),
{Debugging Techniques} {Debugging Techniques}
*/ */

View File

@ -49,7 +49,7 @@
#include "qcoreapplication.h" #include "qcoreapplication.h"
#include "qthread.h" #include "qthread.h"
#endif #endif
#ifdef Q_OS_WINCE #ifdef Q_OS_WIN
#include <qt_windows.h> #include <qt_windows.h>
#endif #endif
@ -66,7 +66,7 @@ QT_BEGIN_NAMESPACE
The class provides information about the source code location a qDebug(), qWarning(), The class provides information about the source code location a qDebug(), qWarning(),
qCritical() or qFatal() message was generated. qCritical() or qFatal() message was generated.
\sa QMessageLogger, QMessageHandler, qInstallMessageHandler() \sa QMessageLogger, QtMessageHandler, qInstallMessageHandler()
*/ */
/*! /*!
@ -92,6 +92,7 @@ QT_BEGIN_NAMESPACE
\internal \internal
Uses a local buffer to output the message. Not locale safe + cuts off Uses a local buffer to output the message. Not locale safe + cuts off
everything after character 255, but will work in out of memory situations. everything after character 255, but will work in out of memory situations.
Stop the execution afterwards.
*/ */
static void qEmergencyOut(QtMsgType msgType, const char *msg, va_list ap) static void qEmergencyOut(QtMsgType msgType, const char *msg, va_list ap)
{ {
@ -99,8 +100,33 @@ static void qEmergencyOut(QtMsgType msgType, const char *msg, va_list ap)
emergency_buf[255] = '\0'; emergency_buf[255] = '\0';
if (msg) if (msg)
qvsnprintf(emergency_buf, 255, msg, ap); qvsnprintf(emergency_buf, 255, msg, ap);
QMessageLogContext context;
qt_message_output(msgType, context, emergency_buf); #if defined(Q_OS_WIN) && defined(QT_BUILD_CORE_LIB)
OutputDebugStringA(emergency_buf);
#else
fprintf(stderr, "%s", emergency_buf);
fflush(stderr);
#endif
if (msgType == QtFatalMsg
|| (msgType == QtWarningMsg
&& (!qgetenv("QT_FATAL_WARNINGS").isNull())) ) {
#if defined(Q_CC_MSVC) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR)
// get the current report mode
int reportMode = _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW);
_CrtSetReportMode(_CRT_ERROR, reportMode);
int ret = _CrtDbgReport(_CRT_ERROR, __FILE__, __LINE__, QT_VERSION_STR,
msg);
if (ret == 1)
_CrtDbgBreak();
#endif
#if (defined(Q_OS_UNIX) || defined(Q_CC_MINGW))
abort(); // trap; generates core dump
#else
exit(1); // goodbye cruel world
#endif
}
} }
#endif #endif
@ -116,10 +142,10 @@ static void qt_message(QtMsgType msgType, const QMessageLogContext &context, con
return; return;
} }
#endif #endif
QByteArray buf; QString buf;
if (msg) { if (msg) {
QT_TRY { QT_TRY {
buf = QString().vsprintf(msg, ap).toLocal8Bit(); buf = QString().vsprintf(msg, ap);
} QT_CATCH(const std::bad_alloc &) { } QT_CATCH(const std::bad_alloc &) {
#if !defined(QT_NO_EXCEPTIONS) #if !defined(QT_NO_EXCEPTIONS)
qEmergencyOut(msgType, msg, ap); qEmergencyOut(msgType, msg, ap);
@ -128,7 +154,7 @@ static void qt_message(QtMsgType msgType, const QMessageLogContext &context, con
#endif #endif
} }
} }
qt_message_output(msgType, context, buf.constData()); qt_message_output(msgType, context, buf);
} }
#undef qDebug #undef qDebug
@ -452,13 +478,13 @@ QMessagePattern::QMessagePattern()
else { else {
fprintf(stderr, "%s\n", fprintf(stderr, "%s\n",
QString::fromLatin1("QT_MESSAGE_PATTERN: Unknown placeholder %1\n" QString::fromLatin1("QT_MESSAGE_PATTERN: Unknown placeholder %1\n"
).arg(lexeme).toLocal8Bit().constData()); ).arg(lexeme).toLatin1().constData());
fflush(stderr); fflush(stderr);
tokens[i] = emptyTokenC; tokens[i] = emptyTokenC;
} }
} else { } else {
char *literal = new char[lexeme.size() + 1]; char *literal = new char[lexeme.size() + 1];
strncpy(literal, lexeme.toLocal8Bit().constData(), lexeme.size()); strncpy(literal, lexeme.toLatin1().constData(), lexeme.size());
literal[lexeme.size()] = '\0'; literal[lexeme.size()] = '\0';
literalsVar.append(literal); literalsVar.append(literal);
tokens[i] = literal; tokens[i] = literal;
@ -484,16 +510,16 @@ Q_GLOBAL_STATIC(QMessagePattern, qMessagePattern)
/*! /*!
\internal \internal
*/ */
Q_CORE_EXPORT QByteArray qMessageFormatString(QtMsgType type, const QMessageLogContext &context, Q_CORE_EXPORT QString qMessageFormatString(QtMsgType type, const QMessageLogContext &context,
const char *str) const QString &str)
{ {
QByteArray message; QString message;
QMessagePattern *pattern = qMessagePattern(); QMessagePattern *pattern = qMessagePattern();
if (!pattern) { if (!pattern) {
// after destruction of static QMessagePattern instance // after destruction of static QMessagePattern instance
message.append(str); message.append(str);
message.append('\n'); message.append(QLatin1Char('\n'));
return message; return message;
} }
@ -503,86 +529,102 @@ Q_CORE_EXPORT QByteArray qMessageFormatString(QtMsgType type, const QMessageLogC
if (token == messageTokenC) { if (token == messageTokenC) {
message.append(str); message.append(str);
} else if (token == categoryTokenC) { } else if (token == categoryTokenC) {
message.append(context.category); message.append(QLatin1String(context.category));
} else if (token == typeTokenC) { } else if (token == typeTokenC) {
switch (type) { switch (type) {
case QtDebugMsg: message.append("debug"); break; case QtDebugMsg: message.append(QLatin1String("debug")); break;
case QtWarningMsg: message.append("warning"); break; case QtWarningMsg: message.append(QLatin1String("warning")); break;
case QtCriticalMsg:message.append("critical"); break; case QtCriticalMsg:message.append(QLatin1String("critical")); break;
case QtFatalMsg: message.append("fatal"); break; case QtFatalMsg: message.append(QLatin1String("fatal")); break;
} }
} else if (token == fileTokenC) { } else if (token == fileTokenC) {
if (context.file) if (context.file)
message.append(context.file); message.append(QLatin1String(context.file));
else else
message.append("unknown"); message.append(QLatin1String("unknown"));
} else if (token == lineTokenC) { } else if (token == lineTokenC) {
message.append(QByteArray::number(context.line)); message.append(QString::number(context.line));
} else if (token == functionTokenC) { } else if (token == functionTokenC) {
if (context.function) if (context.function)
message.append(qCleanupFuncinfo(context.function)); message.append(QString::fromLatin1(qCleanupFuncinfo(context.function)));
else else
message.append("unknown"); message.append(QLatin1String("unknown"));
#ifndef QT_BOOTSTRAPPED #ifndef QT_BOOTSTRAPPED
} else if (token == pidTokenC) { } else if (token == pidTokenC) {
message.append(QByteArray::number(QCoreApplication::applicationPid())); message.append(QString::number(QCoreApplication::applicationPid()));
} else if (token == appnameTokenC) { } else if (token == appnameTokenC) {
message.append(QCoreApplication::applicationName().toUtf8().constData()); message.append(QCoreApplication::applicationName());
} else if (token == threadidTokenC) { } else if (token == threadidTokenC) {
message.append("0x" + QByteArray::number(qlonglong(QThread::currentThread()->currentThread()), 16)); message.append(QLatin1String("0x"));
message.append(QString::number(qlonglong(QThread::currentThread()->currentThread()), 16));
#endif #endif
} else { } else {
message.append(token); message.append(QLatin1String(token));
} }
} }
message.append('\n'); message.append(QLatin1Char('\n'));
return message; return message;
} }
static QtMsgHandler msgHandler = 0; // pointer to debug handler (without context) static QtMsgHandler msgHandler = 0; // pointer to debug handler (without context)
static QMessageHandler messageHandler = 0; // pointer to debug handler (with context) static QtMessageHandler messageHandler = 0; // pointer to debug handler (with context)
static QMessageHandler messageHandler2 = 0; // TODO: Remove before Qt5.0 beta
/*! /*!
\internal \internal
*/ */
static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &context, static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &context,
const char *buf) const QString &buf)
{ {
QByteArray logMessage = qMessageFormatString(type, context, buf); QString logMessage = qMessageFormatString(type, context, buf);
#if defined(Q_OS_WINCE) #if defined(Q_OS_WINCE)
QString fstr = QString::fromLocal8Bit(logMessage); OutputDebugString(reinterpret_cast<const wchar_t *> (logMessage.utf16()));
OutputDebugString(reinterpret_cast<const wchar_t *> (fstr.utf16()));
#else #else
fprintf(stderr, "%s", logMessage.constData()); fprintf(stderr, "%s", logMessage.toLocal8Bit().constData());
fflush(stderr); fflush(stderr);
#endif #endif
} }
/*!
\internal
*/
static void qDefaultMessageHandler2(QtMsgType type, const QMessageLogContext &context,
const char *buf)
{
qDefaultMessageHandler(type, context, QString::fromLocal8Bit(buf));
}
/*! /*!
\internal \internal
*/ */
static void qDefaultMsgHandler(QtMsgType type, const char *buf) static void qDefaultMsgHandler(QtMsgType type, const char *buf)
{ {
QMessageLogContext emptyContext; QMessageLogContext emptyContext;
qDefaultMessageHandler(type, emptyContext, buf); qDefaultMessageHandler(type, emptyContext, QLatin1String(buf));
} }
/*! /*!
\internal \internal
*/ */
void qt_message_output(QtMsgType msgType, const QMessageLogContext &context, const char *buf) void qt_message_output(QtMsgType msgType, const QMessageLogContext &context, const QString &message)
{ {
if (!msgHandler) if (!msgHandler)
msgHandler = qDefaultMsgHandler; msgHandler = qDefaultMsgHandler;
if (!messageHandler) if (!messageHandler)
messageHandler = qDefaultMessageHandler; messageHandler = qDefaultMessageHandler;
if (!messageHandler2)
messageHandler2 = qDefaultMessageHandler2;
if (messageHandler == qDefaultMessageHandler
&& messageHandler2 != qDefaultMessageHandler2)
(*messageHandler2)(msgType, context, message.toLocal8Bit().constData());
// prefer new message handler over the old one // prefer new message handler over the old one
if (msgHandler == qDefaultMsgHandler if (msgHandler == qDefaultMsgHandler
|| messageHandler != qDefaultMessageHandler) { || messageHandler != qDefaultMessageHandler) {
(*messageHandler)(msgType, context, buf); (*messageHandler)(msgType, context, message);
} else { } else {
(*msgHandler)(msgType, buf); (*msgHandler)(msgType, message.toLocal8Bit().constData());
} }
if (msgType == QtFatalMsg if (msgType == QtFatalMsg
@ -593,14 +635,12 @@ void qt_message_output(QtMsgType msgType, const QMessageLogContext &context, con
// get the current report mode // get the current report mode
int reportMode = _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW); int reportMode = _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW);
_CrtSetReportMode(_CRT_ERROR, reportMode); _CrtSetReportMode(_CRT_ERROR, reportMode);
#if !defined(Q_OS_WINCE)
int ret = _CrtDbgReport(_CRT_ERROR, context.file, context.line, QT_VERSION_STR, buf); int ret = _CrtDbgReportW(_CRT_ERROR, reinterpret_cast<const wchar_t *> (
#else QString::fromLatin1(context.file).utf16()),
int ret = _CrtDbgReportW(_CRT_ERROR, _CRT_WIDE(context.file),
context.line, _CRT_WIDE(QT_VERSION_STR), context.line, _CRT_WIDE(QT_VERSION_STR),
reinterpret_cast<const wchar_t *> ( reinterpret_cast<const wchar_t *> (
QString::fromLatin1(buf).utf16())); message.utf16()));
#endif
if (ret == 0 && reportMode & _CRTDBG_MODE_WNDW) if (ret == 0 && reportMode & _CRTDBG_MODE_WNDW)
return; // ignore return; // ignore
else if (ret == 1) else if (ret == 1)
@ -626,8 +666,9 @@ void qErrnoWarning(const char *msg, ...)
buf.vsprintf(msg, ap); buf.vsprintf(msg, ap);
va_end(ap); va_end(ap);
QMessageLogger().critical("%s (%s)", buf.toLocal8Bit().constData(), buf += QLatin1String(" (") + qt_error_string(-1) + QLatin1Char(')');
qt_error_string(-1).toLocal8Bit().constData()); QMessageLogContext context;
qt_message_output(QtCriticalMsg, context, buf);
} }
void qErrnoWarning(int code, const char *msg, ...) void qErrnoWarning(int code, const char *msg, ...)
@ -641,22 +682,29 @@ void qErrnoWarning(int code, const char *msg, ...)
buf.vsprintf(msg, ap); buf.vsprintf(msg, ap);
va_end(ap); va_end(ap);
QMessageLogger().critical("%s (%s)", buf.toLocal8Bit().constData(), buf += QLatin1String(" (") + qt_error_string(code) + QLatin1Char(')');
qt_error_string(code).toLocal8Bit().constData()); QMessageLogContext context;
qt_message_output(QtCriticalMsg, context, buf);
} }
#if defined(Q_OS_WIN) && defined(QT_BUILD_CORE_LIB) #if defined(Q_OS_WIN) && defined(QT_BUILD_CORE_LIB)
extern bool usingWinMain; extern bool usingWinMain;
extern Q_CORE_EXPORT void qWinMsgHandler(QtMsgType t, const char *str); extern Q_CORE_EXPORT void qWinMsgHandler(QtMsgType t, const char *str);
extern Q_CORE_EXPORT void qWinMessageHandler(QtMsgType t, const QMessageLogContext &context, extern Q_CORE_EXPORT void qWinMessageHandler(QtMsgType t, const QMessageLogContext &context,
const char *str); const QString &str);
void qWinMessageHandler2(QtMsgType t, const QMessageLogContext &context,
const char *str)
{
qWinMessageHandler(t, context, QString::fromLocal8Bit(str));
}
#endif #endif
QMessageHandler qInstallMessageHandler(QMessageHandler h) QtMessageHandler qInstallMessageHandler(QtMessageHandler h)
{ {
if (!messageHandler) if (!messageHandler)
messageHandler = qDefaultMessageHandler; messageHandler = qDefaultMessageHandler;
QMessageHandler old = messageHandler; QtMessageHandler old = messageHandler;
messageHandler = h; messageHandler = h;
#if defined(Q_OS_WIN) && defined(QT_BUILD_CORE_LIB) #if defined(Q_OS_WIN) && defined(QT_BUILD_CORE_LIB)
if (!messageHandler && usingWinMain) if (!messageHandler && usingWinMain)
@ -665,6 +713,19 @@ QMessageHandler qInstallMessageHandler(QMessageHandler h)
return old; return old;
} }
QMessageHandler qInstallMessageHandler(QMessageHandler h)
{
if (!messageHandler2)
messageHandler2 = qDefaultMessageHandler2;
QMessageHandler old = messageHandler2;
messageHandler2 = h;
#if defined(Q_OS_WIN) && defined(QT_BUILD_CORE_LIB)
if (!messageHandler2 && usingWinMain)
messageHandler2 = qWinMessageHandler2;
#endif
return old;
}
QtMsgHandler qInstallMsgHandler(QtMsgHandler h) QtMsgHandler qInstallMsgHandler(QtMsgHandler h)
{ {
//if handler is 0, set it to the //if handler is 0, set it to the

View File

@ -151,7 +151,8 @@ private:
# define qWarning QT_NO_QWARNING_MACRO # define qWarning QT_NO_QWARNING_MACRO
#endif #endif
Q_CORE_EXPORT void qt_message_output(QtMsgType, const QMessageLogContext &context, const char *buf); Q_CORE_EXPORT void qt_message_output(QtMsgType, const QMessageLogContext &context,
const QString &message);
Q_CORE_EXPORT void qErrnoWarning(int code, const char *msg, ...); Q_CORE_EXPORT void qErrnoWarning(int code, const char *msg, ...);
Q_CORE_EXPORT void qErrnoWarning(const char *msg, ...); Q_CORE_EXPORT void qErrnoWarning(const char *msg, ...);
@ -160,6 +161,10 @@ Q_CORE_EXPORT void qErrnoWarning(const char *msg, ...);
typedef void (*QtMsgHandler)(QtMsgType, const char *); typedef void (*QtMsgHandler)(QtMsgType, const char *);
Q_CORE_EXPORT QtMsgHandler qInstallMsgHandler(QtMsgHandler); Q_CORE_EXPORT QtMsgHandler qInstallMsgHandler(QtMsgHandler);
typedef void (*QtMessageHandler)(QtMsgType, const QMessageLogContext &, const QString &);
Q_CORE_EXPORT QtMessageHandler qInstallMessageHandler(QtMessageHandler);
// TODO: Remove before Qt5.0 Beta
typedef void (*QMessageHandler)(QtMsgType, const QMessageLogContext &, const char *); typedef void (*QMessageHandler)(QtMsgType, const QMessageLogContext &, const char *);
Q_CORE_EXPORT QMessageHandler qInstallMessageHandler(QMessageHandler); Q_CORE_EXPORT QMessageHandler qInstallMessageHandler(QMessageHandler);

View File

@ -85,7 +85,7 @@ public:
QT_TRY { QT_TRY {
qt_message_output(stream->type, qt_message_output(stream->type,
stream->context, stream->context,
stream->buffer.toLocal8Bit().data()); stream->buffer);
} QT_CATCH(std::bad_alloc&) { /* We're out of memory - give up. */ } } QT_CATCH(std::bad_alloc&) { /* We're out of memory - give up. */ }
} }
delete stream; delete stream;

View File

@ -141,29 +141,28 @@ public:
}; };
// defined in qlogging.cpp // defined in qlogging.cpp
extern Q_CORE_EXPORT QByteArray qMessageFormatString(QtMsgType type, extern Q_CORE_EXPORT QString qMessageFormatString(QtMsgType type,
const QMessageLogContext &context, const QMessageLogContext &context,
const char *str); const QString &str);
Q_CORE_EXPORT void qWinMessageHandler(QtMsgType t, const QMessageLogContext &context, const char *str) Q_CORE_EXPORT void qWinMessageHandler(QtMsgType t, const QMessageLogContext &context, const QString &str)
{ {
// cannot use QMutex here, because qWarning()s in the QMutex // cannot use QMutex here, because qWarning()s in the QMutex
// implementation may cause this function to recurse // implementation may cause this function to recurse
static QWinMsgHandlerCriticalSection staticCriticalSection; static QWinMsgHandlerCriticalSection staticCriticalSection;
QByteArray message = qMessageFormatString(t, context, str); QString message = qMessageFormatString(t, context, str);
QString s(QString::fromLocal8Bit(message));
// OutputDebugString is not threadsafe. // OutputDebugString is not threadsafe.
staticCriticalSection.lock(); staticCriticalSection.lock();
OutputDebugString((wchar_t*)s.utf16()); OutputDebugString((wchar_t*)message.utf16());
staticCriticalSection.unlock(); staticCriticalSection.unlock();
} }
Q_CORE_EXPORT void qWinMsgHandler(QtMsgType t, const char *str) Q_CORE_EXPORT void qWinMsgHandler(QtMsgType t, const char *str)
{ {
QMessageLogContext emptyContext; QMessageLogContext emptyContext;
qWinMessageHandler(t, emptyContext, str); qWinMessageHandler(t, emptyContext, QString::fromLocal8Bit(str));
} }
/***************************************************************************** /*****************************************************************************
@ -189,7 +188,7 @@ void qWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdParam,
usingWinMain = true; usingWinMain = true;
// Install default debug handler // Install default debug handler
qInstallMsgHandler(qWinMsgHandler); qInstallMessageHandler(qWinMessageHandler);
// Create command line // Create command line
argv = qWinCmdLine<char>(cmdParam, int(strlen(cmdParam)), argc); argv = qWinCmdLine<char>(cmdParam, int(strlen(cmdParam)), argc);

View File

@ -73,13 +73,13 @@ int s_line;
const char *s_function; const char *s_function;
static QString s_message; static QString s_message;
void customMessageHandler(QtMsgType type, const QMessageLogContext &context, const char *msg) void customMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{ {
s_type = type; s_type = type;
s_file = context.file; s_file = context.file;
s_line = context.line; s_line = context.line;
s_function = context.function; s_function = context.function;
s_message = QString::fromLocal8Bit(msg); s_message = msg;
} }
void customMsgHandler(QtMsgType type, const char *msg) void customMsgHandler(QtMsgType type, const char *msg)
@ -101,7 +101,7 @@ void tst_qmessagehandler::initTestCase()
void tst_qmessagehandler::cleanup() void tst_qmessagehandler::cleanup()
{ {
qInstallMsgHandler(0); qInstallMsgHandler(0);
qInstallMessageHandler(0); qInstallMessageHandler((QtMessageHandler)0);
s_type = QtFatalMsg; s_type = QtFatalMsg;
s_file = 0; s_file = 0;
s_line = 0; s_line = 0;
@ -117,7 +117,7 @@ void tst_qmessagehandler::defaultHandler()
void tst_qmessagehandler::installMessageHandler() void tst_qmessagehandler::installMessageHandler()
{ {
QMessageHandler oldHandler = qInstallMessageHandler(customMessageHandler); QtMessageHandler oldHandler = qInstallMessageHandler(customMessageHandler);
qDebug("installMessageHandler"); int line = __LINE__; qDebug("installMessageHandler"); int line = __LINE__;
@ -127,7 +127,7 @@ void tst_qmessagehandler::installMessageHandler()
QCOMPARE(s_function, Q_FUNC_INFO); QCOMPARE(s_function, Q_FUNC_INFO);
QCOMPARE(s_line, line); QCOMPARE(s_line, line);
QMessageHandler myHandler = qInstallMessageHandler(oldHandler); QtMessageHandler myHandler = qInstallMessageHandler(oldHandler);
QCOMPARE((void*)myHandler, (void*)customMessageHandler); QCOMPARE((void*)myHandler, (void*)customMessageHandler);
} }

View File

@ -74,12 +74,12 @@ void tst_QDebug::assignment() const
} }
static QtMsgType s_msgType; static QtMsgType s_msgType;
static QByteArray s_msg; static QString s_msg;
static QByteArray s_file; static QByteArray s_file;
static int s_line; static int s_line;
static QByteArray s_function; static QByteArray s_function;
static void myMessageHandler(QtMsgType type, const QMessageLogContext &context, const char *msg) static void myMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{ {
s_msg = msg; s_msg = msg;
s_msgType = type; s_msgType = type;
@ -94,7 +94,7 @@ static void myMessageHandler(QtMsgType type, const QMessageLogContext &context,
class MessageHandlerSetter class MessageHandlerSetter
{ {
public: public:
MessageHandlerSetter(QMessageHandler newMessageHandler) MessageHandlerSetter(QtMessageHandler newMessageHandler)
: oldMessageHandler(qInstallMessageHandler(newMessageHandler)) : oldMessageHandler(qInstallMessageHandler(newMessageHandler))
{ } { }
@ -104,7 +104,7 @@ public:
} }
private: private:
QMessageHandler oldMessageHandler; QtMessageHandler oldMessageHandler;
}; };
/*! \internal /*! \internal
@ -116,7 +116,7 @@ void tst_QDebug::warningWithoutDebug() const
{ qWarning() << "A qWarning() message"; } { qWarning() << "A qWarning() message"; }
QString file = __FILE__; int line = __LINE__ - 1; QString function = Q_FUNC_INFO; QString file = __FILE__; int line = __LINE__ - 1; QString function = Q_FUNC_INFO;
QCOMPARE(s_msgType, QtWarningMsg); QCOMPARE(s_msgType, QtWarningMsg);
QCOMPARE(QString::fromLatin1(s_msg.data()), QString::fromLatin1("A qWarning() message ")); QCOMPARE(s_msg, QString::fromLatin1("A qWarning() message "));
QCOMPARE(QString::fromLatin1(s_file), file); QCOMPARE(QString::fromLatin1(s_file), file);
QCOMPARE(s_line, line); QCOMPARE(s_line, line);
QCOMPARE(QString::fromLatin1(s_function), function); QCOMPARE(QString::fromLatin1(s_function), function);
@ -131,7 +131,7 @@ void tst_QDebug::criticalWithoutDebug() const
{ qCritical() << "A qCritical() message"; } { qCritical() << "A qCritical() message"; }
QString file = __FILE__; int line = __LINE__ - 1; QString function = Q_FUNC_INFO; QString file = __FILE__; int line = __LINE__ - 1; QString function = Q_FUNC_INFO;
QCOMPARE(s_msgType, QtCriticalMsg); QCOMPARE(s_msgType, QtCriticalMsg);
QCOMPARE(QString::fromLatin1(s_msg), QString::fromLatin1("A qCritical() message ")); QCOMPARE(s_msg, QString::fromLatin1("A qCritical() message "));
QCOMPARE(QString::fromLatin1(s_file), file); QCOMPARE(QString::fromLatin1(s_file), file);
QCOMPARE(s_line, line); QCOMPARE(s_line, line);
QCOMPARE(QString::fromLatin1(s_function), function); QCOMPARE(QString::fromLatin1(s_function), function);
@ -143,7 +143,7 @@ void tst_QDebug::debugWithBool() const
{ qDebug() << false << true; } { qDebug() << false << true; }
QString file = __FILE__; int line = __LINE__ - 1; QString function = Q_FUNC_INFO; QString file = __FILE__; int line = __LINE__ - 1; QString function = Q_FUNC_INFO;
QCOMPARE(s_msgType, QtDebugMsg); QCOMPARE(s_msgType, QtDebugMsg);
QCOMPARE(QString::fromLatin1(s_msg), QString::fromLatin1("false true ")); QCOMPARE(s_msg, QString::fromLatin1("false true "));
QCOMPARE(QString::fromLatin1(s_file), file); QCOMPARE(QString::fromLatin1(s_file), file);
QCOMPARE(s_line, line); QCOMPARE(s_line, line);
QCOMPARE(QString::fromLatin1(s_function), function); QCOMPARE(QString::fromLatin1(s_function), function);
@ -161,7 +161,7 @@ void tst_QDebug::veryLongWarningMessage() const
} }
QString file = __FILE__; int line = __LINE__ - 2; QString function = Q_FUNC_INFO; QString file = __FILE__; int line = __LINE__ - 2; QString function = Q_FUNC_INFO;
QCOMPARE(s_msgType, QtWarningMsg); QCOMPARE(s_msgType, QtWarningMsg);
QCOMPARE(QString::fromLatin1(s_msg), QString::fromLatin1("Test output:\n")+test+QString::fromLatin1("\nend")); QCOMPARE(s_msg, QString::fromLatin1("Test output:\n")+test+QString::fromLatin1("\nend"));
QCOMPARE(QString::fromLatin1(s_file), file); QCOMPARE(QString::fromLatin1(s_file), file);
QCOMPARE(s_line, line); QCOMPARE(s_line, line);
QCOMPARE(QString::fromLatin1(s_function), function); QCOMPARE(QString::fromLatin1(s_function), function);
@ -178,7 +178,7 @@ void tst_QDebug::qDebugQStringRef() const
{ qDebug() << inRef; } { qDebug() << inRef; }
QString file = __FILE__; int line = __LINE__ - 1; QString function = Q_FUNC_INFO; QString file = __FILE__; int line = __LINE__ - 1; QString function = Q_FUNC_INFO;
QCOMPARE(s_msgType, QtDebugMsg); QCOMPARE(s_msgType, QtDebugMsg);
QCOMPARE(QString::fromLatin1(s_msg), QString::fromLatin1("\"input\" ")); QCOMPARE(s_msg, QString::fromLatin1("\"input\" "));
QCOMPARE(QString::fromLatin1(s_file), file); QCOMPARE(QString::fromLatin1(s_file), file);
QCOMPARE(s_line, line); QCOMPARE(s_line, line);
QCOMPARE(QString::fromLatin1(s_function), function); QCOMPARE(QString::fromLatin1(s_function), function);
@ -192,7 +192,7 @@ void tst_QDebug::qDebugQStringRef() const
{ qDebug() << inRef; } { qDebug() << inRef; }
QString file = __FILE__; int line = __LINE__ - 1; QString function = Q_FUNC_INFO; QString file = __FILE__; int line = __LINE__ - 1; QString function = Q_FUNC_INFO;
QCOMPARE(s_msgType, QtDebugMsg); QCOMPARE(s_msgType, QtDebugMsg);
QCOMPARE(QString::fromLatin1(s_msg), QString::fromLatin1("\"\" ")); QCOMPARE(s_msg, QString::fromLatin1("\"\" "));
QCOMPARE(QString::fromLatin1(s_file), file); QCOMPARE(QString::fromLatin1(s_file), file);
QCOMPARE(s_line, line); QCOMPARE(s_line, line);
QCOMPARE(QString::fromLatin1(s_function), function); QCOMPARE(QString::fromLatin1(s_function), function);
@ -205,7 +205,7 @@ void tst_QDebug::qDebugQLatin1String() const
{ qDebug() << QLatin1String("foo") << QLatin1String("") << QLatin1String("barbaz", 3); } { qDebug() << QLatin1String("foo") << QLatin1String("") << QLatin1String("barbaz", 3); }
QString file = __FILE__; int line = __LINE__ - 1; QString function = Q_FUNC_INFO; QString file = __FILE__; int line = __LINE__ - 1; QString function = Q_FUNC_INFO;
QCOMPARE(s_msgType, QtDebugMsg); QCOMPARE(s_msgType, QtDebugMsg);
QCOMPARE(QString::fromLatin1(s_msg), QString::fromLatin1("\"foo\" \"\" \"bar\" ")); QCOMPARE(s_msg, QString::fromLatin1("\"foo\" \"\" \"bar\" "));
QCOMPARE(QString::fromLatin1(s_file), file); QCOMPARE(QString::fromLatin1(s_file), file);
QCOMPARE(s_line, line); QCOMPARE(s_line, line);
QCOMPARE(QString::fromLatin1(s_function), function); QCOMPARE(QString::fromLatin1(s_function), function);
@ -214,11 +214,11 @@ void tst_QDebug::qDebugQLatin1String() const
void tst_QDebug::defaultMessagehandler() const void tst_QDebug::defaultMessagehandler() const
{ {
MessageHandlerSetter mhs(0); MessageHandlerSetter mhs(0);
QMessageHandler defaultMessageHandler1 = qInstallMessageHandler(0); QtMessageHandler defaultMessageHandler1 = qInstallMessageHandler((QtMessageHandler)0);
QMessageHandler defaultMessageHandler2 = qInstallMessageHandler(myMessageHandler); QtMessageHandler defaultMessageHandler2 = qInstallMessageHandler(myMessageHandler);
bool same = (*defaultMessageHandler1 == *defaultMessageHandler2); bool same = (*defaultMessageHandler1 == *defaultMessageHandler2);
QVERIFY(same); QVERIFY(same);
QMessageHandler messageHandler = qInstallMessageHandler(0); QtMessageHandler messageHandler = qInstallMessageHandler((QtMessageHandler)0);
same = (*messageHandler == *myMessageHandler); same = (*messageHandler == *myMessageHandler);
QVERIFY(same); QVERIFY(same);
} }