Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Marco Bubke
flatpak-qt-creator
Commits
7195c6b5
Commit
7195c6b5
authored
Jan 14, 2011
by
hjk
Browse files
debugger: re-do state transitions in combined C++/Qml engine
This still needs a lot of work and sanitizing.
parent
adf74394
Changes
7
Expand all
Hide whitespace changes
Inline
Side-by-side
src/plugins/debugger/debuggerconstants.h
View file @
7195c6b5
...
...
@@ -114,9 +114,12 @@ enum DebuggerState
InferiorSetupRequested
,
InferiorSetupFailed
,
InferiorSetupOk
,
EngineRunRequested
,
EngineRunFailed
,
EngineRunOk
,
InferiorUnrunnable
,
// Used in the core dump adapter
InferiorRunRequested
,
// Debuggee requested to run
...
...
@@ -124,16 +127,19 @@ enum DebuggerState
InferiorRunFailed
,
// Debuggee running
InferiorStopRequested
,
// Debuggee running, stop requested
InferiorStopSpontaneous
,
// Debuggee stopped spontaneously
InferiorStopOk
,
// Debuggee stopped
InferiorStopFailed
,
// Debuggee not stopped, will kill debugger
InferiorExitOk
,
InferiorShutdownRequested
,
InferiorShutdownOk
,
InferiorShutdownFailed
,
InferiorShutdownOk
,
EngineShutdownRequested
,
EngineShutdownOk
,
EngineShutdownFailed
,
EngineShutdownOk
,
DebuggerFinished
};
...
...
src/plugins/debugger/debuggerengine.cpp
View file @
7195c6b5
This diff is collapsed.
Click to expand it.
src/plugins/debugger/debuggerengine.h
View file @
7195c6b5
...
...
@@ -241,6 +241,7 @@ public:
virtual
void
updateViews
();
bool
isSlaveEngine
()
const
;
bool
isMasterEngine
()
const
;
DebuggerEngine
*
masterEngine
()
const
;
signals:
...
...
@@ -320,7 +321,7 @@ protected:
virtual
void
frameUp
();
virtual
void
frameDown
();
DebuggerRunControl
*
runControl
()
const
;
// FIXME: Protect.
DebuggerRunControl
*
runControl
()
const
;
static
QString
msgWatchpointTriggered
(
BreakpointId
id
,
int
number
,
quint64
address
);
...
...
@@ -338,12 +339,18 @@ protected:
static
bool
isCppBreakpoint
(
const
Internal
::
BreakpointParameters
&
p
);
bool
isStateDebugging
()
const
;
void
setStateDebugging
(
bool
on
);
private:
// Wrapper engine needs access to state of its subengines.
friend
class
Internal
::
QmlCppEngine
;
friend
class
Internal
::
DebuggerPluginPrivate
;
void
setState
(
DebuggerState
state
,
bool
forced
=
false
);
virtual
void
setState
(
DebuggerState
state
,
bool
forced
=
false
);
virtual
void
setSilentState
(
DebuggerState
state
);
virtual
void
slaveEngineStateChanged
(
DebuggerEngine
*
engine
,
DebuggerState
state
);
friend
class
DebuggerEnginePrivate
;
DebuggerEnginePrivate
*
d
;
...
...
src/plugins/debugger/gdb/gdbengine.cpp
View file @
7195c6b5
...
...
@@ -141,7 +141,10 @@ static bool stateAcceptsGdbCommands(DebuggerState state)
return
true
;
case
DebuggerNotReady
:
case
InferiorStopFailed
:
case
InferiorStopSpontaneous
:
case
InferiorSetupOk
:
case
EngineRunFailed
:
case
EngineRunOk
:
case
InferiorRunFailed
:
case
EngineShutdownOk
:
case
EngineShutdownFailed
:
...
...
src/plugins/debugger/qml/qmlcppengine.cpp
View file @
7195c6b5
...
...
@@ -5,9 +5,12 @@
#include "debuggercore.h"
#include <qmljseditor/qmljseditorconstants.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <utils/qtcassert.h>
#include <QtCore/QTimer>
namespace
Debugger
{
...
...
@@ -42,14 +45,12 @@ private:
DebuggerEngine
*
m_qmlEngine
;
DebuggerEngine
*
m_cppEngine
;
DebuggerEngine
*
m_activeEngine
;
DebuggerState
m_errorState
;
};
QmlCppEnginePrivate
::
QmlCppEnginePrivate
()
:
m_qmlEngine
(
0
),
m_cppEngine
(
0
),
m_activeEngine
(
0
),
m_errorState
(
InferiorRunOk
)
m_activeEngine
(
0
)
{}
...
...
@@ -70,10 +71,12 @@ QmlCppEngine::QmlCppEngine(const DebuggerStartParameters &sp)
}
d
->
m_activeEngine
=
d
->
m_cppEngine
;
connect
(
d
->
m_cppEngine
,
SIGNAL
(
stateChanged
(
DebuggerState
)),
SLOT
(
slaveEngineStateChanged
(
DebuggerState
)));
connect
(
d
->
m_qmlEngine
,
SIGNAL
(
stateChanged
(
DebuggerState
)),
SLOT
(
slaveEngineStateChanged
(
DebuggerState
)));
if
(
1
)
{
setStateDebugging
(
true
);
d
->
m_cppEngine
->
setStateDebugging
(
true
);
d
->
m_qmlEngine
->
setStateDebugging
(
true
);
}
}
QmlCppEngine
::~
QmlCppEngine
()
...
...
@@ -217,61 +220,66 @@ void QmlCppEngine::detachDebugger()
void
QmlCppEngine
::
executeStep
()
{
notifyInferiorRunRequested
();
d
->
m_activeEngine
->
executeStep
();
}
void
QmlCppEngine
::
executeStepOut
()
{
notifyInferiorRunRequested
();
d
->
m_activeEngine
->
executeStepOut
();
}
void
QmlCppEngine
::
executeNext
()
{
notifyInferiorRunRequested
();
d
->
m_activeEngine
->
executeNext
();
}
void
QmlCppEngine
::
executeStepI
()
{
notifyInferiorRunRequested
();
d
->
m_activeEngine
->
executeStepI
();
}
void
QmlCppEngine
::
executeNextI
()
{
notifyInferiorRunRequested
();
d
->
m_activeEngine
->
executeNextI
();
}
void
QmlCppEngine
::
executeReturn
()
{
notifyInferiorRunRequested
();
d
->
m_activeEngine
->
executeReturn
();
}
void
QmlCppEngine
::
continueInferior
()
{
if
(
d
->
m_activeEngine
->
state
()
==
InferiorStopOk
)
{
d
->
m_activeEngine
->
continueInferior
();
qDebug
()
<<
"
\n
MASTER CONTINUE INFERIOR"
<<
d
->
m_cppEngine
->
state
()
<<
d
->
m_qmlEngine
->
state
();
notifyInferiorRunRequested
();
if
(
d
->
m_cppEngine
->
state
()
==
InferiorStopOk
)
{
d
->
m_cppEngine
->
continueInferior
();
}
else
if
(
d
->
m_qmlEngine
->
state
()
==
InferiorStopOk
)
{
d
->
m_qmlEngine
->
continueInferior
();
}
else
{
notifyInferiorRunRequested
();
QTC_ASSERT
(
false
,
qDebug
()
<<
"MASTER CANNOT CONTINUE INFERIOR"
<<
d
->
m_cppEngine
->
state
()
<<
d
->
m_qmlEngine
->
state
());
notifyEngineIll
();
}
}
void
QmlCppEngine
::
interruptInferior
()
{
if
(
d
->
m_activeEngine
->
state
()
==
InferiorRunOk
)
{
d
->
m_activeEngine
->
requestInterruptInferior
();
}
else
{
if
(
d
->
m_activeEngine
->
state
()
==
InferiorStopOk
&&
(
!
checkErrorState
(
InferiorStopFailed
)))
{
notifyInferiorStopOk
();
}
}
qDebug
()
<<
"
\n
MASTER INTERRUPT INFERIOR"
;
}
void
QmlCppEngine
::
requestInterruptInferior
()
{
qDebug
()
<<
"
\n
MASTER REQUEST INTERUPT INFERIOR"
;
DebuggerEngine
::
requestInterruptInferior
();
if
(
d
->
m_activeEngine
->
state
()
==
InferiorRunOk
)
{
d
->
m_activeEngine
->
requestInterruptInferior
();
}
d
->
m_cppEngine
->
requestInterruptInferior
();
}
void
QmlCppEngine
::
executeRunToLine
(
const
QString
&
fileName
,
int
lineNumber
)
...
...
@@ -306,240 +314,264 @@ void QmlCppEngine::frameDown()
/////////////////////////////////////////////////////////
bool
QmlCppEngine
::
checkErrorState
(
const
DebuggerState
stateToCheck
)
void
QmlCppEngine
::
setupEngine
(
)
{
if
(
d
->
m_errorState
!=
stateToCheck
)
return
false
;
qDebug
()
<<
"
\n
MASTER SETUP ENGINE"
;
QTC_ASSERT
(
d
->
m_cppEngine
->
state
()
==
DebuggerNotReady
,
/**/
);
QTC_ASSERT
(
d
->
m_qmlEngine
->
state
()
==
DebuggerNotReady
,
/**/
);
d
->
m_qmlEngine
->
setSilentState
(
EngineSetupRequested
);
d
->
m_cppEngine
->
setSilentState
(
EngineSetupRequested
);
d
->
m_qmlEngine
->
setupEngine
();
// Always succeeds.
d
->
m_cppEngine
->
setupEngine
();
// May fail.
}
// reset state ( so that more than one error can accumulate over time )
d
->
m_errorState
=
InferiorRunOk
;
switch
(
stateToCheck
)
{
case
InferiorRunOk
:
// nothing to do
break
;
case
EngineRunFailed
:
notifyEngineRunFailed
();
break
;
case
EngineSetupFailed
:
notifyEngineSetupFailed
();
break
;
case
EngineShutdownFailed
:
notifyEngineShutdownFailed
();
break
;
case
InferiorSetupFailed
:
notifyInferiorSetupFailed
();
break
;
case
InferiorRunFailed
:
notifyInferiorRunFailed
();
break
;
case
InferiorUnrunnable
:
notifyInferiorUnrunnable
();
break
;
case
InferiorStopFailed
:
notifyInferiorStopFailed
();
break
;
case
InferiorShutdownFailed
:
notifyInferiorShutdownFailed
();
break
;
default:
// unexpected
break
;
}
return
true
;
void
QmlCppEngine
::
notifyEngineRunAndInferiorRunOk
()
{
qDebug
()
<<
"
\n
MASTER NOTIFY ENGINE RUN AND INFERIOR RUN OK"
;
DebuggerEngine
::
notifyEngineRunAndInferiorRunOk
();
}
void
QmlCppEngine
::
notifyInferiorRunOk
()
{
qDebug
()
<<
"
\n
MASTER NOTIFY INFERIOR RUN OK"
;
DebuggerEngine
::
notifyInferiorRunOk
();
}
void
QmlCppEngine
::
setupEngine
()
void
QmlCppEngine
::
notifyInferiorSpontaneousStop
()
{
d
->
m_cppEngine
->
startDebugger
(
runControl
());
qDebug
()
<<
"
\n
MASTER SPONTANEOUS STOP OK"
;
DebuggerEngine
::
notifyInferiorSpontaneousStop
();
}
void
QmlCppEngine
::
setup
Inferior
()
void
QmlCppEngine
::
notify
Inferior
ShutdownOk
()
{
if
(
!
checkErrorState
(
InferiorSetupFailed
))
{
notifyInferiorSetupOk
();
}
qDebug
()
<<
"
\n
MASTER INFERIOR SHUTDOWN OK"
;
DebuggerEngine
::
notifyInferiorShutdownOk
();
}
void
QmlCppEngine
::
runEngine
()
void
QmlCppEngine
::
setupInferior
()
{
if
(
!
checkErrorState
(
EngineRunFailed
))
{
if
(
d
->
m_errorState
==
InferiorRunOk
)
{
switch
(
d
->
m_activeEngine
->
state
())
{
case
InferiorRunOk
:
notifyEngineRunAndInferiorRunOk
();
break
;
case
InferiorStopOk
:
notifyEngineRunAndInferiorStopOk
();
break
;
default:
// not supported?
notifyEngineRunFailed
();
break
;
}
}
else
{
notifyEngineRunFailed
();
}
}
qDebug
()
<<
"
\n
MASTER SETUP INFERIOR"
;
QTC_ASSERT
(
d
->
m_cppEngine
->
state
()
==
EngineSetupOk
,
/**/
);
QTC_ASSERT
(
d
->
m_qmlEngine
->
state
()
==
EngineSetupOk
,
/**/
);
d
->
m_qmlEngine
->
setSilentState
(
InferiorSetupRequested
);
d
->
m_cppEngine
->
setSilentState
(
InferiorSetupRequested
);
d
->
m_cppEngine
->
setupInferior
();
d
->
m_qmlEngine
->
setupInferior
();
}
void
QmlCppEngine
::
shutdownInferior
()
void
QmlCppEngine
::
runEngine
()
{
if
(
!
checkErrorState
(
InferiorShutdownFailed
))
{
if
(
d
->
m_cppEngine
->
state
()
==
InferiorS
topOk
)
{
d
->
m_
cpp
Engine
->
quitDebugger
(
);
}
else
{
notifyInferiorShutdownOk
(
);
}
}
qDebug
()
<<
"
\n
MASTER RUN ENGINE"
;
QTC_ASSERT
(
d
->
m_cppEngine
->
state
()
==
InferiorS
etupOk
,
/**/
);
QTC_ASSERT
(
d
->
m_
qml
Engine
->
state
()
==
InferiorSetupOk
,
/**/
);
d
->
m_qmlEngine
->
setSilentState
(
EngineRunRequested
);
d
->
m_cppEngine
->
setSilentState
(
EngineRunRequested
);
d
->
m_cppEngine
->
runEngine
();
d
->
m_qmlEngine
->
runEngine
();
}
void
QmlCppEngine
::
initEngineShutdown
()
void
QmlCppEngine
::
shutdownInferior
()
{
if
(
d
->
m_qmlEngine
->
state
()
!=
DebuggerFinished
)
{
d
->
m_qmlEngine
->
quitDebugger
();
}
else
if
(
d
->
m_cppEngine
->
state
()
!=
DebuggerFinished
)
{
d
->
m_cppEngine
->
quitDebugger
();
}
else
if
(
state
()
==
EngineSetupRequested
)
{
if
(
!
runControl
()
||
d
->
m_errorState
==
EngineSetupFailed
)
{
notifyEngineSetupFailed
();
}
else
{
notifyEngineSetupOk
();
}
}
else
if
(
state
()
==
InferiorStopRequested
)
{
checkErrorState
(
InferiorStopFailed
);
}
else
if
(
state
()
==
InferiorShutdownRequested
&&
!
checkErrorState
(
InferiorShutdownFailed
))
{
notifyInferiorShutdownOk
();
}
else
if
(
state
()
!=
DebuggerFinished
)
{
quitDebugger
();
}
qDebug
()
<<
"
\n
MASTER SHUTDOWN INFERIOR"
;
d
->
m_qmlEngine
->
quitDebugger
();
}
void
QmlCppEngine
::
shutdownEngine
()
{
if
(
!
checkErrorState
(
EngineShutdownFailed
))
{
showStatusMessage
(
tr
(
"Debugging finished"
));
notifyEngineShutdownOk
();
}
qDebug
()
<<
"
\n
MASTER SHUTDOWN ENGINE"
;
QTC_ASSERT
(
d
->
m_cppEngine
->
state
()
==
InferiorShutdownOk
,
/**/
);
QTC_ASSERT
(
d
->
m_qmlEngine
->
state
()
==
InferiorShutdownOk
,
/**/
);
d
->
m_qmlEngine
->
setSilentState
(
EngineShutdownRequested
);
d
->
m_cppEngine
->
setSilentState
(
EngineShutdownRequested
);
d
->
m_qmlEngine
->
shutdownEngine
();
d
->
m_cppEngine
->
shutdownEngine
();
}
void
QmlCppEngine
::
set
upSlaveEngine
(
)
void
QmlCppEngine
::
set
State
(
DebuggerState
newState
,
bool
forced
)
{
if
(
d
->
m_qmlEngine
->
state
()
==
DebuggerNotReady
)
d
->
m_qmlEngine
->
startDebugger
(
runControl
());
qDebug
()
<<
"SET MASTER STATE: "
<<
newState
;
qDebug
()
<<
" CPP STATE: "
<<
d
->
m_cppEngine
->
state
();
qDebug
()
<<
" QML STATE: "
<<
d
->
m_qmlEngine
->
state
();
DebuggerEngine
::
setState
(
newState
,
forced
);
}
void
QmlCppEngine
::
slaveEngineStateChanged
(
const
DebuggerState
newState
)
void
QmlCppEngine
::
slaveEngineStateChanged
(
DebuggerEngine
*
slaveEngine
,
const
DebuggerState
newState
)
{
DebuggerEngine
*
slaveEngine
=
qobject_cast
<
DebuggerEngine
*>
(
sender
())
;
if
(
newState
==
InferiorStopOk
&&
slaveEngine
!
=
d
->
m_
active
Engine
)
{
QString
engineName
=
slave
Engine
==
d
->
m_cppEngine
?
QLatin1String
(
"C++"
)
:
QLatin1String
(
"QML"
);
showStatusMessage
(
tr
(
"%1 debugger activated"
).
arg
(
engineName
))
;
d
->
m_activeEngine
=
d
->
m_qmlEngine
;
}
const
bool
isCpp
=
slaveEngine
==
d
->
m_cppEngine
;
//const bool isQml =
slaveEngine
=
= d->m_
qml
Engine
;
DebuggerEngine
*
otherEngine
=
isCpp
?
d
->
m_qml
Engine
:
d
->
m_cppEngine
;
qDebug
()
<<
"GOT SLAVE STATE: "
<<
slaveEngine
<<
newState
;
qDebug
()
<<
" OTHER ENGINE: "
<<
otherEngine
<<
otherEngine
->
state
()
;
qDebug
()
<<
" COMBINED ENGINE: "
<<
this
<<
state
()
<<
isDying
();
switch
(
newState
)
{
case
InferiorRunOk
:
// startup?
if
(
d
->
m_qmlEngine
->
state
()
==
DebuggerNotReady
)
{
setupSlaveEngine
();
}
else
if
(
d
->
m_cppEngine
->
state
()
==
DebuggerNotReady
)
{
setupEngine
();
}
else
if
(
state
()
==
EngineSetupRequested
)
{
case
DebuggerNotReady
:
case
InferiorUnrunnable
:
break
;
case
EngineSetupRequested
:
break
;
case
EngineSetupFailed
:
notifyEngineSetupFailed
();
break
;
case
EngineSetupOk
:
if
(
otherEngine
->
state
()
==
EngineSetupOk
)
notifyEngineSetupOk
();
}
else
// breakpoint?
if
(
state
()
==
InferiorStopOk
)
{
continueInferior
();
}
else
if
(
state
()
==
InferiorStopRequested
)
{
checkErrorState
(
InferiorStopFailed
);
}
else
if
(
state
()
==
InferiorRunRequested
&&
(
!
checkErrorState
(
InferiorRunFailed
))
&&
(
!
checkErrorState
(
InferiorUnrunnable
)))
{
notifyInferiorRunOk
();
else
qDebug
()
<<
"... WAITING FOR OTHER ENGINE SETUP..."
;
break
;
case
InferiorSetupRequested
:
break
;
case
InferiorSetupFailed
:
notifyInferiorSetupFailed
();
break
;
case
InferiorSetupOk
:
if
(
otherEngine
->
state
()
==
InferiorSetupOk
)
notifyInferiorSetupOk
();
else
qDebug
()
<<
"... WAITING FOR OTHER INFERIOR SETUP..."
;
break
;
case
EngineRunRequested
:
break
;
case
EngineRunFailed
:
notifyEngineRunFailed
();
break
;
case
EngineRunOk
:
if
(
otherEngine
->
state
()
==
EngineRunOk
)
{
// This is conditionalized on isMasterEngine() in the
// base class, so do it here manually.
slaveEngine
->
setSilentState
(
InferiorRunOk
);
otherEngine
->
setSilentState
(
InferiorRunOk
);
notifyEngineRunAndInferiorRunOk
();
}
else
{
qDebug
()
<<
"... WAITING FOR OTHER ENGINE RUN..."
;
}
break
;
case
InferiorRunRequested
:
// follow the inferior
if
(
state
()
==
InferiorStopOk
&&
checkErrorState
(
InferiorRunOk
))
{
continueInferior
();
break
;
case
InferiorRunFailed
:
notifyInferiorRunFailed
();
break
;
case
InferiorRunOk
:
qDebug
()
<<
"PLANNED INFERIOR RUN"
;
if
(
otherEngine
->
state
()
==
InferiorRunOk
)
notifyInferiorRunOk
();
else
qDebug
()
<<
" **** INFERIOR RUN NOT OK ****"
;
break
;
case
InferiorStopSpontaneous
:
notifyInferiorSpontaneousStop
();
slaveEngine
->
setSilentState
(
InferiorStopOk
);
if
(
slaveEngine
!=
d
->
m_activeEngine
)
{
QString
engineName
=
slaveEngine
==
d
->
m_cppEngine
?
QLatin1String
(
"C++"
)
:
QLatin1String
(
"QML"
);
showStatusMessage
(
tr
(
"%1 debugger activated"
).
arg
(
engineName
));
d
->
m_activeEngine
=
slaveEngine
;
}
break
;
case
InferiorStopRequested
:
// follow the inferior
if
(
state
()
==
InferiorRunOk
&&
checkErrorState
(
InferiorRunOk
))
{
requestInterruptInferior
();
}
break
;
case
InferiorStopFailed
:
notifyInferiorStopFailed
();
break
;
case
InferiorStopOk
:
// check breakpoints
if
(
state
()
==
InferiorRunRequested
)
{
checkErrorState
(
InferiorRunFailed
);
}
else
if
(
checkErrorState
(
InferiorRunOk
))
{
if
(
state
()
==
InferiorRunOk
)
{
requestInterruptInferior
();
}
else
if
(
state
()
==
InferiorStopRequested
)
{
interruptInferior
();
if
(
isDying
())
{
qDebug
()
<<
"... AN INFERIOR STOPPED DURING SHUTDOWN "
;
}
else
{
if
(
otherEngine
->
state
()
==
InferiorShutdownOk
)
{
qDebug
()
<<
"... STOPP "
;
}
else
if
(
state
()
==
InferiorStopRequested
)
{
qDebug
()
<<
"... AN INFERIOR STOPPED EXPECTEDLY"
;
notifyInferiorStopOk
();
}
else
{
qDebug
()
<<
"... AN INFERIOR STOPPED UNEXPECTEDLY"
;
notifyInferiorSpontaneousStop
();
}
}
break
;
case
EngineRunFailed
:
case
EngineSetupFailed
:
case
EngineShutdownFailed
:
case
InferiorSetupFailed
:
case
InferiorRunFailed
:
case
InferiorUnrunnable
:
case
InferiorStopFailed
:
case
InferiorShutdownFailed
:
if
(
d
->
m_errorState
==
InferiorRunOk
)
{
d
->
m_errorState
=
newState
;
case
InferiorExitOk
:
slaveEngine
->
setSilentState
(
InferiorShutdownOk
);
if
(
otherEngine
->
state
()
==
InferiorShutdownOk
)
{
notifyInferiorExited
();
}
else
{
if
(
state
()
==
InferiorRunOk
)
notifyInferiorSpontaneousStop
();
otherEngine
->
notifyInferiorExited
();
}
break
;
case
InferiorShutdownRequested
:
break
;
case
InferiorShutdownFailed
:
notifyInferiorShutdownFailed
();
break
;
case
InferiorShutdownOk
:
if
(
otherEngine
->
state
()
==
InferiorShutdownOk
)
notifyInferiorShutdownOk
();
else
if
(
otherEngine
->
state
()
==
InferiorRunOk
)
otherEngine
->
quitDebugger
();
else
if
(
otherEngine
->
state
()
==
InferiorStopOk
)
otherEngine
->
quitDebugger
();
break
;
case
EngineShutdownRequested
:
// we have to abort the setup before the sub-engines die
// because we depend on an active runcontrol that will be shut down by the dying engine
if
(
state
()
==
EngineSetupRequested
)