Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
Marco Bubke
flatpak-qt-creator
Commits
20eb6a1b
Commit
20eb6a1b
authored
Jan 15, 2009
by
Oswald Buddenhagen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
user gdb's --tty option for collecting app output
parent
72b6a105
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
300 additions
and
18 deletions
+300
-18
src/plugins/debugger/debugger.pro
src/plugins/debugger/debugger.pro
+2
-0
src/plugins/debugger/gdbengine.cpp
src/plugins/debugger/gdbengine.cpp
+21
-18
src/plugins/debugger/gdbengine.h
src/plugins/debugger/gdbengine.h
+7
-0
src/plugins/debugger/outputcollector.cpp
src/plugins/debugger/outputcollector.cpp
+179
-0
src/plugins/debugger/outputcollector.h
src/plugins/debugger/outputcollector.h
+91
-0
No files found.
src/plugins/debugger/debugger.pro
View file @
20eb6a1b
...
...
@@ -30,6 +30,7 @@ HEADERS += attachexternaldialog.h \
imports
.
h
\
moduleshandler
.
h
\
moduleswindow
.
h
\
outputcollector
.
h
\
procinterrupt
.
h
\
registerhandler
.
h
\
registerwindow
.
h
\
...
...
@@ -56,6 +57,7 @@ SOURCES += attachexternaldialog.cpp \
gdbmi
.
cpp
\
moduleshandler
.
cpp
\
moduleswindow
.
cpp
\
outputcollector
.
cpp
\
procinterrupt
.
cpp
\
registerhandler
.
cpp
\
registerwindow
.
cpp
\
...
...
src/plugins/debugger/gdbengine.cpp
View file @
20eb6a1b
...
...
@@ -252,6 +252,7 @@ void GdbEngine::init()
m_pendingRequests
=
0
;
m_gdbVersion
=
100
;
m_shared
=
0
;
m_outputCodec
=
QTextCodec
::
codecForLocale
();
m_oldestAcceptableToken
=
-
1
;
...
...
@@ -266,6 +267,8 @@ void GdbEngine::init()
SLOT
(
exitDebugger
()));
// Output
connect
(
&
m_outputCollector
,
SIGNAL
(
byteDelivery
(
QByteArray
)),
SLOT
(
readDebugeeOutput
(
QByteArray
)));
connect
(
this
,
SIGNAL
(
gdbResponseAvailable
()),
this
,
SLOT
(
handleResponse
()),
Qt
::
QueuedConnection
);
...
...
@@ -355,6 +358,12 @@ static void skipTerminator(const char *&from, const char *to)
skipSpaces
(
from
,
to
);
}
void
GdbEngine
::
readDebugeeOutput
(
const
QByteArray
&
data
)
{
emit
applicationOutputAvailable
(
m_outputCodec
->
toUnicode
(
data
.
constData
(),
data
.
length
(),
&
m_outputCodecState
));
}
// called asyncronously as response to Gdb stdout output in
// gdbResponseAvailable()
void
GdbEngine
::
handleResponse
()
...
...
@@ -407,22 +416,6 @@ void GdbEngine::handleResponse()
break
;
}
if
(
token
==
-
1
&&
*
from
!=
'&'
&&
*
from
!=
'~'
&&
*
from
!=
'*'
)
{
// FIXME: On Linux the application's std::out is merged in here.
// High risk of falsely interpreting this as MI output.
// We assume that we _always_ use tokens, so not finding a token
// is a positive indication for the presence of application output.
QString
s
;
while
(
from
!=
to
&&
*
from
!=
'\n'
)
s
+=
*
from
++
;
//qDebug() << "UNREQUESTED DATA " << s << " TAKEN AS APPLICATION OUTPUT";
//s += '\n';
m_inbuffer
=
QByteArray
(
from
,
to
-
from
);
emit
applicationOutputAvailable
(
s
);
continue
;
}
// next char decides kind of record
const
char
c
=
*
from
++
;
//qDebug() << "CODE:" << c;
...
...
@@ -590,8 +583,7 @@ static void fixMac(QByteArray &out)
void
GdbEngine
::
readGdbStandardError
()
{
QByteArray
err
=
m_gdbProc
.
readAllStandardError
();
emit
applicationOutputAvailable
(
err
);
qWarning
()
<<
"Unexpected gdb stderr:"
<<
m_gdbProc
.
readAllStandardError
();
}
void
GdbEngine
::
readGdbStandardOutput
()
...
...
@@ -1484,6 +1476,7 @@ void GdbEngine::exitDebugger()
m_varToType
.
clear
();
m_dataDumperState
=
DataDumperUninitialized
;
m_shared
=
0
;
m_outputCollector
.
shutdown
();
//q->settings()->m_debugDumpers = false;
}
...
...
@@ -1506,6 +1499,15 @@ bool GdbEngine::startDebugger()
return
false
;
}
if
(
!
m_outputCollector
.
listen
())
{
QMessageBox
::
critical
(
q
->
mainWindow
(),
tr
(
"Debugger Startup Failure"
),
tr
(
"Cannot set up communication with child process: %1"
)
.
arg
(
m_outputCollector
.
errorString
()));
return
false
;
}
gdbArgs
.
prepend
(
QLatin1String
(
"--tty="
)
+
m_outputCollector
.
serverName
());
//gdbArgs.prepend(QLatin1String("--quiet"));
gdbArgs
.
prepend
(
QLatin1String
(
"mi"
));
gdbArgs
.
prepend
(
QLatin1String
(
"-i"
));
...
...
@@ -1533,6 +1535,7 @@ bool GdbEngine::startDebugger()
if
(
m_gdbProc
.
state
()
!=
QProcess
::
Running
)
{
QMessageBox
::
critical
(
q
->
mainWindow
(),
tr
(
"Debugger Startup Failure"
),
tr
(
"Cannot start debugger: %1"
).
arg
(
m_gdbProc
.
errorString
()));
m_outputCollector
.
shutdown
();
return
false
;
}
...
...
src/plugins/debugger/gdbengine.h
View file @
20eb6a1b
...
...
@@ -36,6 +36,7 @@
#include "idebuggerengine.h"
#include "gdbmi.h"
#include "outputcollector.h"
#include <QtCore/QByteArray>
#include <QtCore/QHash>
...
...
@@ -43,6 +44,7 @@
#include <QtCore/QObject>
#include <QtCore/QProcess>
#include <QtCore/QPoint>
#include <QtCore/QTextCodec>
#include <QtCore/QVariant>
QT_BEGIN_NAMESPACE
...
...
@@ -173,6 +175,7 @@ private slots:
void
gdbProcError
(
QProcess
::
ProcessError
error
);
void
readGdbStandardOutput
();
void
readGdbStandardError
();
void
readDebugeeOutput
(
const
QByteArray
&
data
);
private:
int
terminationIndex
(
const
QByteArray
&
buffer
,
int
&
length
);
...
...
@@ -190,6 +193,10 @@ private:
void
handleQueryPwd
(
const
GdbResultRecord
&
response
);
void
handleQuerySources
(
const
GdbResultRecord
&
response
);
OutputCollector
m_outputCollector
;
QTextCodec
*
m_outputCodec
;
QTextCodec
::
ConverterState
m_outputCodecState
;
QByteArray
m_inbuffer
;
QProcess
m_gdbProc
;
...
...
src/plugins/debugger/outputcollector.cpp
0 → 100644
View file @
20eb6a1b
/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the packaging
** of this file. Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
#include "outputcollector.h"
#ifdef Q_OS_WIN
#include <QtNetwork/QLocalServer>
#include <QtNetwork/QLocalSocket>
#else
#include <QtCore/QFile>
#include <QtCore/QSocketNotifier>
#include <QtCore/QTemporaryFile>
#include <QtCore/QVarLengthArray>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#endif
namespace
Debugger
{
namespace
Internal
{
OutputCollector
::
OutputCollector
(
QObject
*
parent
)
:
QObject
(
parent
)
{
#ifdef Q_OS_WIN
m_server
=
0
;
m_socket
=
0
;
#endif
}
OutputCollector
::~
OutputCollector
()
{
shutdown
();
}
bool
OutputCollector
::
listen
()
{
#ifdef Q_OS_WIN
if
(
m_server
)
return
m_server
->
isListening
();
m_server
=
new
QLocalServer
(
this
);
connect
(
m_server
,
SIGNAL
(
newConnection
()),
SLOT
(
newConnectionAvailable
()));
return
m_server
->
listen
(
QLatin1String
(
"creator-"
)
+
QCoreApplication
::
applicationPid
());
// XXX how to make that secure?
#else
if
(
!
m_serverPath
.
isEmpty
())
return
true
;
QByteArray
codedServerPath
;
forever
{
{
QTemporaryFile
tf
;
if
(
!
tf
.
open
())
{
m_errorString
=
tr
(
"Cannot create temporary file: %2"
).
arg
(
tf
.
errorString
());
m_serverPath
.
clear
();
return
false
;
}
m_serverPath
=
tf
.
fileName
();
}
// By now the temp file was deleted again
codedServerPath
=
QFile
::
encodeName
(
m_serverPath
);
if
(
!::
mkfifo
(
codedServerPath
.
constData
(),
0600
))
break
;
if
(
errno
!=
EEXIST
)
{
m_errorString
=
tr
(
"Cannot create FiFo %1: %2"
).
arg
(
m_serverPath
,
strerror
(
errno
));
m_serverPath
.
clear
();
return
false
;
}
}
if
((
m_serverFd
=
::
open
(
codedServerPath
.
constData
(),
O_RDONLY
|
O_NONBLOCK
))
<
0
)
{
m_errorString
=
tr
(
"Cannot open FiFo %1: %2"
).
arg
(
m_serverPath
,
strerror
(
errno
));
m_serverPath
.
clear
();
return
false
;
}
m_serverNotifier
=
new
QSocketNotifier
(
m_serverFd
,
QSocketNotifier
::
Read
,
this
);
connect
(
m_serverNotifier
,
SIGNAL
(
activated
(
int
)),
SLOT
(
bytesAvailable
()));
return
true
;
#endif
}
void
OutputCollector
::
shutdown
()
{
#ifdef Q_OS_WIN
delete
m_server
;
// Deletes socket as well (QObject parent)
m_server
=
0
;
m_socket
=
0
;
#else
if
(
!
m_serverPath
.
isEmpty
())
{
::
close
(
m_serverFd
);
::
unlink
(
QFile
::
encodeName
(
m_serverPath
).
constData
());
delete
m_serverNotifier
;
m_serverPath
.
clear
();
}
#endif
}
QString
OutputCollector
::
errorString
()
const
{
#ifdef Q_OS_WIN
return
m_socket
?
m_socket
->
errorString
()
:
m_server
->
errorString
();
#else
return
m_errorString
;
#endif
}
QString
OutputCollector
::
serverName
()
const
{
#ifdef Q_OS_WIN
return
m_server
->
fullServerPath
();
#else
return
m_serverPath
;
#endif
}
#ifdef Q_OS_WIN
void
OutputCollector
::
newConnectionAvailable
()
{
if
(
m_socket
)
return
;
m_socket
=
m_server
->
nextPendingConnection
();
connect
(
m_socket
,
SIGNAL
(
bytesAvailable
()),
SLOT
(
bytesAvailable
()));
}
#endif
void
OutputCollector
::
bytesAvailable
()
{
#ifdef Q_OS_WIN
emit
byteDelivery
(
m_socket
->
readAll
());
#else
size_t
nbytes
=
0
;
if
(
::
ioctl
(
m_serverFd
,
FIONREAD
,
(
char
*
)
&
nbytes
)
<
0
)
return
;
QVarLengthArray
<
char
,
8192
>
buff
(
nbytes
);
if
(
::
read
(
m_serverFd
,
buff
.
data
(),
nbytes
)
!=
(
int
)
nbytes
)
return
;
if
(
nbytes
)
// Skip EOF notifications
emit
byteDelivery
(
QByteArray
::
fromRawData
(
buff
.
data
(),
nbytes
));
#endif
}
}
// namespace Internal
}
// namespace Debugger
src/plugins/debugger/outputcollector.h
0 → 100644
View file @
20eb6a1b
/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the packaging
** of this file. Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
#ifndef OUTPUT_COLLECTOR_H
#define OUTPUT_COLLECTOR_H
#include <QtCore/QByteArray>
#include <QtCore/QObject>
QT_BEGIN_NAMESPACE
class
QLocalServer
;
class
QLocalSocket
;
class
QSocketNotifier
;
QT_END_NAMESPACE
namespace
Debugger
{
namespace
Internal
{
///////////////////////////////////////////////////////////////////////
//
// OutputCollector
//
///////////////////////////////////////////////////////////////////////
class
OutputCollector
:
public
QObject
{
Q_OBJECT
public:
OutputCollector
(
QObject
*
parent
=
0
);
~
OutputCollector
();
bool
listen
();
void
shutdown
();
QString
serverName
()
const
;
QString
errorString
()
const
;
signals:
void
byteDelivery
(
const
QByteArray
&
data
);
private
slots
:
void
bytesAvailable
();
#ifdef Q_OS_WIN
void
newConnectionAvailable
();
#endif
private:
#ifdef Q_OS_WIN
QLocalServer
*
m_server
;
QLocalSocket
*
m_socket
;
#else
QString
m_serverPath
;
int
m_serverFd
;
QSocketNotifier
*
m_serverNotifier
;
QString
m_errorString
;
#endif
};
}
// namespace Internal
}
// namespace Debugger
#endif // OUTPUT_COLLECTOR_H
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment