Skip to content

Commit

Permalink
Debugger: Allow trace service to send data on exit
Browse files Browse the repository at this point in the history
Add a statusAboutToBeChanged virtual that allows
services to send data e.g. on application exit.

Change-Id: I28fa513ab2a12d6973c444aac3062d64a0957207
Reviewed-by: Christiaan Janssen <christiaan.janssen@nokia.com>
  • Loading branch information
Kai Koehne authored and Qt by Nokia committed Feb 9, 2012
1 parent 4a224c4 commit 82dfeca
Show file tree
Hide file tree
Showing 11 changed files with 133 additions and 30 deletions.
11 changes: 8 additions & 3 deletions src/declarative/debugger/qdeclarativedebugserver.cpp
Expand Up @@ -221,6 +221,10 @@ void QDeclarativeDebugServerThread::run()
}

exec();

// make sure events still waiting are processed
QEventLoop eventLoop;
eventLoop.processEvents(QEventLoop::AllEvents);
}

bool QDeclarativeDebugServer::hasDebuggingClient() const
Expand Down Expand Up @@ -325,6 +329,7 @@ QDeclarativeDebugServer::~QDeclarativeDebugServer()
QReadLocker(&d->pluginsLock);
{
foreach (QDeclarativeDebugService *service, d->plugins.values()) {
service->statusAboutToBeChanged(QDeclarativeDebugService::NotConnected);
service->d_func()->server = 0;
service->d_func()->status = QDeclarativeDebugService::NotConnected;
service->statusChanged(QDeclarativeDebugService::NotConnected);
Expand All @@ -333,8 +338,7 @@ QDeclarativeDebugServer::~QDeclarativeDebugServer()

if (d->thread) {
d->thread->exit();
if (!d->thread->wait(1000))
d->thread->terminate();
d->thread->wait();
delete d->thread;
}
delete d->connection;
Expand Down Expand Up @@ -487,8 +491,9 @@ bool QDeclarativeDebugServer::removeService(QDeclarativeDebugService *service)
}
{
QReadLocker(&d->pluginsLock);
d->advertisePlugins();
QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::NotConnected;
service->statusAboutToBeChanged(newStatus);
d->advertisePlugins();
service->d_func()->server = 0;
service->d_func()->status = newStatus;
service->statusChanged(newStatus);
Expand Down
4 changes: 4 additions & 0 deletions src/declarative/debugger/qdeclarativedebugservice.cpp
Expand Up @@ -253,6 +253,10 @@ bool QDeclarativeDebugService::waitForMessage()
return d->server->waitForMessage(this);
}

void QDeclarativeDebugService::statusAboutToBeChanged(Status)
{
}

void QDeclarativeDebugService::statusChanged(Status)
{
}
Expand Down
1 change: 1 addition & 0 deletions src/declarative/debugger/qdeclarativedebugservice_p.h
Expand Up @@ -96,6 +96,7 @@ class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugService : public QObject

Status registerService();

virtual void statusAboutToBeChanged(Status);
virtual void statusChanged(Status);
virtual void messageReceived(const QByteArray &);

Expand Down
17 changes: 15 additions & 2 deletions src/declarative/debugger/qdeclarativedebugtrace.cpp
Expand Up @@ -299,14 +299,27 @@ void QDeclarativeDebugTrace::sendMessages()
QList<QByteArray> messages;
for (int i = 0; i < m_data.count(); ++i)
messages << m_data.at(i).toByteArray();
QDeclarativeDebugService::sendMessages(messages);
m_data.clear();

//indicate completion
QByteArray data;
QDataStream ds(&data, QIODevice::WriteOnly);
ds << (qint64)-1 << (int)Complete;
sendMessage(data);
messages << data;

QDeclarativeDebugService::sendMessages(messages);
}

void QDeclarativeDebugTrace::statusAboutToBeChanged(QDeclarativeDebugService::Status newStatus)
{
if (status() == newStatus)
return;

if (status() == Enabled
&& m_enabled) {
stopProfilingImpl();
sendMessages();
}
}

void QDeclarativeDebugTrace::messageReceived(const QByteArray &message)
Expand Down
3 changes: 2 additions & 1 deletion src/declarative/debugger/qdeclarativedebugtrace_p.h
Expand Up @@ -100,7 +100,7 @@ class Q_DECLARATIVE_EXPORT QDeclarativeDebugTrace : public QDeclarativeDebugServ
RangeData,
RangeLocation,
RangeEnd,
Complete,
Complete, // end of transmission

MaximumMessage
};
Expand Down Expand Up @@ -145,6 +145,7 @@ class Q_DECLARATIVE_EXPORT QDeclarativeDebugTrace : public QDeclarativeDebugServ
~QDeclarativeDebugTrace();

protected:
virtual void statusAboutToBeChanged(Status status);
virtual void messageReceived(const QByteArray &);

private:
Expand Down
39 changes: 30 additions & 9 deletions src/declarative/debugger/qv8profilerservice.cpp
Expand Up @@ -97,16 +97,14 @@ class QV8ProfilerServicePrivate : public QDeclarativeDebugServicePrivate
QList<QV8ProfilerData> m_data;

bool initialized;
bool m_enabled;
QList<QString> m_ongoing;
};

QV8ProfilerService::QV8ProfilerService(QObject *parent)
: QDeclarativeDebugService(*(new QV8ProfilerServicePrivate()), QLatin1String("V8Profiler"), 1, parent)
{
Q_D(QV8ProfilerService);

d->m_enabled = false;

if (registerService() == Enabled) {
// ,block mode, client attached
while (!d->initialized)
Expand All @@ -129,6 +127,20 @@ void QV8ProfilerService::initialize()
v8ProfilerInstance();
}

void QV8ProfilerService::statusAboutToBeChanged(QDeclarativeDebugService::Status newStatus)
{
Q_D(QV8ProfilerService);

if (status() == newStatus)
return;

if (status() == Enabled) {
foreach (const QString &title, d->m_ongoing)
QMetaObject::invokeMethod(this, "stopProfiling", Qt::QueuedConnection, Q_ARG(QString, title));
sendProfilingData();
}
}

void QV8ProfilerService::messageReceived(const QByteArray &message)
{
Q_D(QV8ProfilerService);
Expand All @@ -141,13 +153,12 @@ void QV8ProfilerService::messageReceived(const QByteArray &message)

if (command == "V8PROFILER") {
ds >> title;
if (option == "start" && !d->m_enabled) {
QMetaObject::invokeMethod(this, "startProfiling", Qt::QueuedConnection, Q_ARG(QString, QString::fromUtf8(title)));
d->m_enabled = true;
} else if (option == "stop" && d->m_enabled) {
QMetaObject::invokeMethod(this, "stopProfiling", Qt::QueuedConnection, Q_ARG(QString, QString::fromUtf8(title)));
QString titleStr = QString::fromUtf8(title);
if (option == "start") {
QMetaObject::invokeMethod(this, "startProfiling", Qt::QueuedConnection, Q_ARG(QString, titleStr));
} else if (option == "stop" && d->initialized) {
QMetaObject::invokeMethod(this, "stopProfiling", Qt::QueuedConnection, Q_ARG(QString, titleStr));
QMetaObject::invokeMethod(this, "sendProfilingData", Qt::QueuedConnection);
d->m_enabled = false;
}
d->initialized = true;
}
Expand All @@ -165,7 +176,12 @@ void QV8ProfilerService::messageReceived(const QByteArray &message)

void QV8ProfilerService::startProfiling(const QString &title)
{
Q_D(QV8ProfilerService);
// Start Profiling

if (d->m_ongoing.contains(title))
return;

v8::HandleScope handle_scope;
v8::Handle<v8::String> v8title = v8::String::New(reinterpret_cast<const uint16_t*>(title.data()), title.size());
v8::CpuProfiler::StartProfiling(v8title);
Expand All @@ -175,6 +191,11 @@ void QV8ProfilerService::stopProfiling(const QString &title)
{
Q_D(QV8ProfilerService);
// Stop profiling

if (!d->m_ongoing.contains(title))
return;
d->m_ongoing.removeOne(title);

v8::HandleScope handle_scope;
v8::Handle<v8::String> v8title = v8::String::New(reinterpret_cast<const uint16_t*>(title.data()), title.size());
const v8::CpuProfile *cpuProfile = v8::CpuProfiler::StopProfiling(v8title);
Expand Down
1 change: 1 addition & 0 deletions src/declarative/debugger/qv8profilerservice_p.h
Expand Up @@ -104,6 +104,7 @@ public slots:
void sendProfilingData();

protected:
void statusAboutToBeChanged(Status status);
void messageReceived(const QByteArray &);

private:
Expand Down
@@ -0,0 +1,9 @@
import QtQuick 2.0

Item {
Timer {
running: true
interval: 1
onTriggered: Qt.quit();
}
}
Expand Up @@ -92,14 +92,15 @@ class tst_QDeclarativeDebugTrace : public QDeclarativeDataTest
QDeclarativeDebugConnection *m_connection;
QDeclarativeDebugTraceClient *m_client;

void connect(bool block);
void connect(bool block, const QString &testFile);

private slots:
void cleanup();

void blockingConnectWithTraceEnabled();
void blockingConnectWithTraceDisabled();
void nonBlockingConnect();
void profileOnExit();
};

void QDeclarativeDebugTraceClient::messageReceived(const QByteArray &message)
Expand Down Expand Up @@ -147,7 +148,6 @@ void QDeclarativeDebugTraceClient::messageReceived(const QByteArray &message)
}
case QDeclarativeDebugTrace::Complete: {
emit complete();
QVERIFY(stream.atEnd());
return;
}
case QDeclarativeDebugTrace::RangeStart: {
Expand All @@ -166,7 +166,7 @@ void QDeclarativeDebugTraceClient::messageReceived(const QByteArray &message)
break;
}
case QDeclarativeDebugTrace::RangeLocation: {
stream >> data.detailType >> data.detailData >> data.line;
stream >> data.detailType >> data.detailData >> data.line >> data.column;
QVERIFY(data.detailType >= 0 && data.detailType < QDeclarativeDebugTrace::MaximumRangeType);
QVERIFY(data.line >= -2);
break;
Expand All @@ -180,7 +180,7 @@ void QDeclarativeDebugTraceClient::messageReceived(const QByteArray &message)
traceMessages.append(data);
}

void tst_QDeclarativeDebugTrace::connect(bool block)
void tst_QDeclarativeDebugTrace::connect(bool block, const QString &testFile)
{
const QString executable = QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene";
QStringList arguments;
Expand All @@ -190,7 +190,7 @@ void tst_QDeclarativeDebugTrace::connect(bool block)
else
arguments << QString("-qmljsdebugger=port:"STR_PORT);

arguments << testFile("test.qml");
arguments << QDeclarativeDataTest::instance()->testFile(testFile);

m_process = new QDeclarativeDebugProcess(executable);
m_process->start(QStringList() << arguments);
Expand All @@ -215,7 +215,7 @@ void tst_QDeclarativeDebugTrace::cleanup()

void tst_QDeclarativeDebugTrace::blockingConnectWithTraceEnabled()
{
connect(true);
connect(true, "test.qml");
QTRY_COMPARE(m_client->status(), QDeclarativeDebugClient::Enabled);

m_client->setTraceStatus(true);
Expand All @@ -238,7 +238,7 @@ void tst_QDeclarativeDebugTrace::blockingConnectWithTraceEnabled()

void tst_QDeclarativeDebugTrace::blockingConnectWithTraceDisabled()
{
connect(true);
connect(true, "test.qml");
QTRY_COMPARE(m_client->status(), QDeclarativeDebugClient::Enabled);

m_client->setTraceStatus(false);
Expand All @@ -263,7 +263,7 @@ void tst_QDeclarativeDebugTrace::blockingConnectWithTraceDisabled()

void tst_QDeclarativeDebugTrace::nonBlockingConnect()
{
connect(false);
connect(false, "test.qml");
QTRY_COMPARE(m_client->status(), QDeclarativeDebugClient::Enabled);

m_client->setTraceStatus(true);
Expand All @@ -283,6 +283,28 @@ void tst_QDeclarativeDebugTrace::nonBlockingConnect()
QCOMPARE(m_client->traceMessages.last().detailType, (int)QDeclarativeDebugTrace::EndTrace);
}

void tst_QDeclarativeDebugTrace::profileOnExit()
{
connect(true, "exit.qml");
QTRY_COMPARE(m_client->status(), QDeclarativeDebugClient::Enabled);

m_client->setTraceStatus(true);

if (!QDeclarativeDebugTest::waitForSignal(m_client, SIGNAL(complete()))) {
QString failMsg
= QString("No trace received in time. App output: \n%1\n").arg(m_process->output());
QFAIL(qPrintable(failMsg));
}

// must start with "StartTrace"
QCOMPARE(m_client->traceMessages.first().messageType, (int)QDeclarativeDebugTrace::Event);
QCOMPARE(m_client->traceMessages.first().detailType, (int)QDeclarativeDebugTrace::StartTrace);

// must end with "EndTrace"
QCOMPARE(m_client->traceMessages.last().messageType, (int)QDeclarativeDebugTrace::Event);
QCOMPARE(m_client->traceMessages.last().detailType, (int)QDeclarativeDebugTrace::EndTrace);
}

QTEST_MAIN(tst_QDeclarativeDebugTrace)

#include "tst_qdeclarativedebugtrace.moc"
11 changes: 11 additions & 0 deletions tests/auto/declarative/debugger/qv8profilerservice/data/exit.qml
@@ -0,0 +1,11 @@
import QtQuick 2.0

Item {
Timer {
running: true
interval: 1
onTriggered: {
Qt.quit();
}
}
}

0 comments on commit 82dfeca

Please sign in to comment.