Statemachine crashes with SIGBUS while stopping
-
Hi guys,
I have a problem with crashing again :)
The statemachine crashes as soon as i exit it.
I am using Qt 5.7, cross compiled for a Raspberry Pi 3 with GCC 4.8.I have an interface to program two different flows:
class IintervalMeasurement : public QObject { Q_OBJECT protected: /* * State Machine */ QStateMachine m_stateMachine; QState *m_mainState{nullptr}; QState *m_stateTakeMeasurement{nullptr}; QState *m_stateZeroing{nullptr}; QState *m_stateStandby{nullptr}; QFinalState *m_abortIntervalMeasurement; QSharedPointer<StandardDeviceFunctions> m_deviceSpecialFunktions; QPointer<QTimer> m_timerUpdateGraphik; int m_count{0}; IntervalMeasurementParameter m_parameter; IintervalMeasurement::statusMeasurement m_lastState; QList<QObject*> m_listContext; public: virtual void start(); ~IintervalMeasurement(); IintervalMeasurement::statusMeasurement lastState() const; void stopMeasurement(); protected: explicit IintervalMeasurement(QSharedPointer<StandardDeviceFunctions> deviceFunctions, QObject *parent = nullptr); IintervalMeasurement(QSharedPointer<StandardDeviceFunctions> deviceFunctions, IntervalMeasurementParameter ¶meter, QObject *parent = nullptr); // builder functions virtual void setZeroing(); virtual void setStandby(); virtual void setState(statusMeasurement state); virtual void setCyclesLeft(); signals: virtual void sig_zeroingReady() = 0; virtual void sig_measurementReady() = 0; virtual void performNullpkt(); virtual void sig_stopMeasurement(); virtual void sig_measurementBreakReady(); virtual void sig_MeasurementWithoutZeroing(); protected slots: virtual void zeroing() = 0; virtual void takeMeasurement() = 0; virtual void standby() = 0; virtual void updateTime(); virtual void finished(); private: virtual void initStateMachine() = 0; void init(); void setTimeDisplay(); };
.cpp
IintervalMeasurement::IintervalMeasurement(QSharedPointer<StandardDeviceFunctions> deviceFunctions, QObject *parent) : QObject(parent) , m_mainState(new QState) , m_stateTakeMeasurement(new QState(m_mainState)) , m_abortIntervalMeasurement(new QFinalState) , m_deviceSpecialFunktions(deviceFunctions) , m_timerUpdateGraphik(new QTimer(this)) { init(); } IintervalMeasurement::IintervalMeasurement(QSharedPointer<StandardDeviceFunctions> deviceFunctions, IntervalMeasurementParameter ¶meter, QObject *parent) : QObject(parent) , m_parameter(parameter) , m_mainState(new QState) , m_stateTakeMeasurement(new QState(m_mainState)) , m_abortIntervalMeasurement(new QFinalState) , m_deviceSpecialFunktions(deviceFunctions) , m_timerUpdateGraphik(new QTimer(this)) { init(); } IintervalMeasurement::~IintervalMeasurement() { qDebug() << Q_FUNC_INFO; m_timerUpdateGraphik->stop(); m_timerUpdateGraphik.clear(); if(m_stateZeroing != nullptr) m_stateZeroing->deleteLater(); if(m_stateStandby != nullptr) m_stateStandby->deleteLater(); if(m_mainState != nullptr) m_mainState->deleteLater(); if(m_abortIntervalMeasurement != nullptr) m_abortIntervalMeasurement->deleteLater(); if(m_stateTakeMeasurement != nullptr) m_stateTakeMeasurement->deleteLater(); } void IintervalMeasurement::init() { m_mainState->setInitialState(m_stateTakeMeasurement); m_stateMachine.addState(m_mainState); m_mainState->addTransition(this, &IintervalMeasurement::sig_stopMeasurement, m_abortIntervalMeasurement); m_stateMachine.addState(m_abortIntervalMeasurement); m_stateMachine.setInitialState(m_mainState); connect(m_stateTakeMeasurement, &QState::entered, this, &IintervalMeasurement::takeMeasurement); connect(m_timerUpdateGraphik.data(), &QTimer::timeout, this, &IintervalMeasurement::updateTime); connect(&m_stateMachine, &QStateMachine::finished, this, &IintervalMeasurement::finished); } void IintervalMeasurement::stopMeasurement() { qDebug() << Q_FUNC_INFO << "1"; emit sig_stopMeasurement(); qDebug() << Q_FUNC_INFO << "2"; } void IintervalMeasurement::start() { m_count = 0; m_timerUpdateGraphik->start(1000); DI_Pointer::Instance().getService<VarioluxxIntervalMeasurementPropertys>()->setMeasurementActivated(true); setCyclesLeft(); // init m_stateMachine.start(); }
First implementation of the interface:
class IntervalMeasurement : public IintervalMeasurement { Q_OBJECT public: explicit IntervalMeasurement(QSharedPointer<StandardDeviceFunctions> deviceFunctions, QObject *parent = nullptr); IntervalMeasurement(QSharedPointer<StandardDeviceFunctions> deviceFunctions, IntervalMeasurementParameter & parameter, QObject *parent = nullptr); ~IntervalMeasurement() override; signals: // State machine signals for transistions void sig_standbyReady(); void sig_zeroingReady() override; void sig_measurementReady() override; protected slots: void standby() override; void takeMeasurement() override; void zeroing() override; private: void initStateMachine() override; };
.cpp
IntervalMeasurement::IntervalMeasurement(QSharedPointer<StandardDeviceFunctions> deviceFunctions, QObject *parent) : IintervalMeasurement(deviceFunctions, parent) { initStateMachine(); } IntervalMeasurement::IntervalMeasurement(QSharedPointer<StandardDeviceFunctions> deviceFunctions, IntervalMeasurementParameter ¶meter, QObject *parent) : IintervalMeasurement(deviceFunctions, parameter, parent) { initStateMachine(); } IntervalMeasurement::~IntervalMeasurement() { } void IntervalMeasurement::initStateMachine() { setStandby(); setZeroing(); // transitions m_stateTakeMeasurement->addTransition(this, &IntervalMeasurement::sig_measurementReady, m_stateStandby); m_stateStandby->addTransition(this, &IntervalMeasurement::sig_standbyReady, m_stateZeroing); m_stateZeroing->addTransition(this, &IntervalMeasurement::sig_zeroingReady, m_stateTakeMeasurement); }
Second implementation of the interface:
class IntervalMeasurementWithoutStandby : public IintervalMeasurement { Q_OBJECT QState *m_stateMeasurementBreak{nullptr}; QScopedPointer<QTimer> m_timer{new QTimer(this)}; public: explicit IntervalMeasurementWithoutStandby(QSharedPointer<StandardDeviceFunctions> deviceFunctions, QObject *parent = nullptr); IntervalMeasurementWithoutStandby(QSharedPointer<StandardDeviceFunctions> deviceFunctions, IntervalMeasurementParameter parameter, QObject *parent = nullptr); ~IntervalMeasurementWithoutStandby() override; signals: void sig_zeroingReady() override; void sig_measurementReady() override; protected slots: void standby() override { } // not used! void takeMeasurement() override; void zeroing() override; void measurementBreak(); private: void initStateMachine() override; };
.cpp
IntervalMeasurementWithoutStandby::IntervalMeasurementWithoutStandby(QSharedPointer<StandardDeviceFunctions> deviceFunctions, QObject *parent) : IintervalMeasurement(deviceFunctions, parent) { initStateMachine(); } IntervalMeasurementWithoutStandby::IntervalMeasurementWithoutStandby(QSharedPointer<StandardDeviceFunctions> deviceFunctions, IntervalMeasurementParameter parameter, QObject *parent) : IintervalMeasurement(deviceFunctions, parameter, parent) { initStateMachine(); } IntervalMeasurementWithoutStandby::~IntervalMeasurementWithoutStandby() { if(m_stateMeasurementBreak != nullptr) m_stateMeasurementBreak->deleteLater(); m_timer.reset(nullptr); } void IntervalMeasurementWithoutStandby::initStateMachine() { setZeroing(); m_stateMeasurementBreak = new QState(m_mainState); connect(m_stateMeasurementBreak, &QState::entered, this, &IntervalMeasurementWithoutStandby::measurementBreak); // set transitions m_stateTakeMeasurement->addTransition(this, &IntervalMeasurementWithoutStandby::sig_measurementReady, m_stateMeasurementBreak); m_stateMeasurementBreak->addTransition(this, &IntervalMeasurementWithoutStandby::sig_measurementBreakReady, m_stateZeroing); m_stateMeasurementBreak->addTransition(this, &IntervalMeasurementWithoutStandby::sig_MeasurementWithoutZeroing, m_stateTakeMeasurement); m_stateZeroing->addTransition(this, &IntervalMeasurementWithoutStandby::sig_zeroingReady, m_stateTakeMeasurement); m_timer->setSingleShot(true); }
Then I use a model which takes the signals from the gui:
class IntervalMeasurementModel : public QObject { Q_OBJECT QSharedPointer<StandardDeviceFunctions> m_deviceSpecialFunktions; QScopedPointer<IintervalMeasurement> m_intervalMeasurement; IntervalMeasurementParameter m_parameter{ IntervalMeasurementParameter(true) }; bool m_withStandby{true}; public: explicit IntervalMeasurementModel(QObject *parent = nullptr); ~IntervalMeasurementModel(); Q_INVOKABLE void startMeasurement(); Q_INVOKABLE void stopMeasurement(); [....] };
IntervalMeasurementModel::IntervalMeasurementModel(QObject *parent) : QObject(parent) , m_deviceSpecialFunktions(new StandardDeviceFunctions(new IntervalMeasurementStrategy)) { QSettings sett; sett.beginGroup("IntervalMeasurement"); m_withStandby = sett.value("standbyAfterBreak", true).toBool(); } IntervalMeasurementModel::~IntervalMeasurementModel() { m_deviceSpecialFunktions.clear(); } void IntervalMeasurementModel::startMeasurement() { if(m_withStandby) m_intervalMeasurement.reset(new IntervalMeasurement(m_deviceSpecialFunktions, m_parameter, this)); else m_intervalMeasurement.reset(new IntervalMeasurementWithoutStandby(m_deviceSpecialFunktions, m_parameter, this)); m_intervalMeasurement->start(); } void IntervalMeasurementModel::stopMeasurement() { qDebug() << Q_FUNC_INFO; m_intervalMeasurement->stopMeasurement(); qDebug() << "test"; QTimer::singleShot(1000, [this] { m_intervalMeasurement->disconnect(); qDebug() << "delete pointer"; m_intervalMeasurement.reset(); qDebug() << m_intervalMeasurement; }); }
The Statemachine runs through without problems.
Only when I want to stop the machine while runtime, the machine crashes with the error SIGBUS.
The exact position is in void IintervalMeasurement::stopMeasurement() {} while the signal emit sig_stopMeasurement(); is sent. I suspect it can no longer find the return address.
The debugger crashes at the following point (moc_iintervalmeasurement.cpp):// SIGNAL 3 void IintervalMeasurement::sig_stopMeasurement() { QMetaObject::activate(this, &staticMetaObject, 3, Q_NULLPTR); }
Does anyone have an idea where the error is?
I almost suspect that it has to do with the interface class but cannot find an error
Thank you very much! -
@Krulle said in Statemachine crashes with SIGBUS while stopping:
signals:
// State machine signals for transistions
void sig_standbyReady();
void sig_zeroingReady() override;virtual signals are a big red
NONO
because the function implementation is done bymoc
-
@Krulle said in Statemachine crashes with SIGBUS while stopping:
signals:
// State machine signals for transistions
void sig_standbyReady();
void sig_zeroingReady() override;virtual signals are a big red
NONO
because the function implementation is done bymoc
@J-Hilk said in Statemachine crashes with SIGBUS while stopping:
virtual signals are a big red
NONO
because the function implementation is done bymoc
Shame on me.
Of course you are right.
I stumbled across the same problem a year ago, but was able to solve it relatively quickly. But I forgot about it. It's quite tricky at this point. I'll remember it and it won't happen again.
The problem only took me 3 evenings.
Thanks for your quick help :)