Commit 9183526a authored by Alejandro Homs Puron's avatar Alejandro Homs Puron
Browse files

Fix issues resulting in dead locks and race conditions:

* Distinguish between triggered and acquired frames
* Consider that Stream isRunning when Stopped
* Wait for sequence end before returning from Stream::stop
* Abort Stream before prepareAcq if Connected, Armed and Running
* Update Camera::newFrameAcquired before newFrameReady
parent cea7d9d1
Pipeline #20903 failed with stages
in 1 minute and 7 seconds
......@@ -168,6 +168,8 @@ class LIBEIGER Camera : public HwMaxImageSizeCallbackGen, public EventCallbackGe
class InitCallback;
friend class InitCallback;
Camera::Status _getStatus();
void _synchronize(); /// Used during plug-in initialization
void _trigger_finished(bool);
void _initialization_finished(bool ok);
......@@ -175,6 +177,7 @@ class LIBEIGER Camera : public HwMaxImageSizeCallbackGen, public EventCallbackGe
void _updateImageSize();
void getNbTriggeredFrames(int& nb_trig_frames);
void newFrameAcquired();
bool allFramesAcquired();
......@@ -212,7 +215,8 @@ class LIBEIGER Camera : public HwMaxImageSizeCallbackGen, public EventCallbackGe
int m_nb_frames;
Cache<unsigned int> m_nb_images;
Cache<unsigned int> m_nb_triggers;
int m_image_number;
int m_frames_triggered;
int m_frames_acquired;
double m_latency_time;
Cache<TrigMode> m_trig_mode;
......
......@@ -95,7 +95,8 @@ private:
Camera::Camera(const std::string& detector_ip, ///< [in] Ip address of the detector server
ApiGeneration api)
: m_api(api),
m_image_number(0),
m_frames_triggered(0),
m_frames_acquired(0),
m_latency_time(0.),
m_detectorImageType(Bpp16),
m_initialize_state(IDLE),
......@@ -243,7 +244,7 @@ void Camera::prepareAcq()
m_requests->cancel(arm_cmd);
HANDLE_EIGERERROR(arm_cmd, e);
}
m_image_number = 0;
m_frames_triggered = m_frames_acquired = 0;
}
......@@ -255,16 +256,15 @@ void Camera::startAcq()
DEB_MEMBER_FUNCT();
AutoMutex lock(m_cond.mutex());
if(m_trig_mode == IntTrig ||
m_trig_mode == IntTrigMult)
if((m_trig_mode == IntTrig) || (m_trig_mode == IntTrigMult))
{
bool disarm_at_end = ((m_trig_mode == IntTrig) ||
(m_image_number == m_nb_frames - 1));
bool disarm_at_end = (m_frames_triggered + m_nb_triggers == m_nb_frames);
DEB_TRACE() << "Trigger start: " << DEB_VAR1(disarm_at_end);
CommandReq trigger = m_requests->get_command(Requests::TRIGGER);
m_trigger_state = RUNNING;
lock.unlock();
m_frames_triggered += m_nb_triggers;
AutoMutexUnlock u(lock);
CallbackPtr cbk(new TriggerCallback(*this));
trigger->register_callback(cbk, disarm_at_end);
}
......@@ -279,7 +279,11 @@ void Camera::stopAcq()
{
DEB_MEMBER_FUNCT();
AutoMutex lock(m_cond.mutex());
if (!m_armed)
return;
sendCommand(Requests::ABORT);
if (m_trigger_state == IDLE) // just armed
m_armed = false;
}
......@@ -557,7 +561,19 @@ void Camera::getNbHwAcquiredFrames(int &nb_acq_frames) ///< [out] number of acqu
{
DEB_MEMBER_FUNCT();
AutoMutex lock(m_cond.mutex());
nb_acq_frames = m_image_number;
nb_acq_frames = m_frames_acquired;
DEB_RETURN() << DEB_VAR1(nb_acq_frames);
}
//-----------------------------------------------------------------------------
/// Get the current triggered frames
//-----------------------------------------------------------------------------
void Camera::getNbTriggeredFrames(int &nb_trig_frames) ///< [out] number of triggered files
{
DEB_MEMBER_FUNCT();
AutoMutex lock(m_cond.mutex());
nb_trig_frames = m_frames_triggered;
DEB_RETURN() << DEB_VAR1(nb_trig_frames);
}
......@@ -565,11 +581,17 @@ void Camera::getNbHwAcquiredFrames(int &nb_acq_frames) ///< [out] number of acqu
/// Get the camera status
//-----------------------------------------------------------------------------
Camera::Status Camera::getStatus() ///< [out] current camera status
{
DEB_MEMBER_FUNCT();
AutoMutex lock(m_cond.mutex());
return _getStatus();
}
Camera::Status Camera::_getStatus()
{
DEB_MEMBER_FUNCT();
Camera::Status status;
AutoMutex lock(m_cond.mutex());
if(m_initialize_state == ERROR ||
m_trigger_state == ERROR)
status = Fault;
......@@ -721,14 +743,15 @@ void Camera::_trigger_finished(bool ok)
DEB_MEMBER_FUNCT();
DEB_PARAM() << DEB_VAR1(ok);
AutoMutex lock(m_cond.mutex());
DEB_TRACE() << "Trigger end";
if(!ok)
if(!ok) {
DEB_ERROR() << "Error in trigger command";
else if(allFramesAcquired())
try { disarm(); }
} else if(m_frames_triggered == m_nb_frames) {
try { _disarm(); }
catch (...) { ok = false; }
}
AutoMutex lock(m_cond.mutex());
m_trigger_state = ok ? IDLE : ERROR;
}
......@@ -736,16 +759,16 @@ void Camera::newFrameAcquired()
{
DEB_MEMBER_FUNCT();
AutoMutex lock(m_cond.mutex());
m_image_number++;
DEB_TRACE() << DEB_VAR1(m_image_number);
++m_frames_acquired;
DEB_TRACE() << DEB_VAR1(m_frames_acquired);
}
bool Camera::allFramesAcquired()
{
DEB_MEMBER_FUNCT();
AutoMutex lock(m_cond.mutex());
DEB_PARAM() << DEB_VAR2(m_image_number, m_nb_frames);
bool finished = (m_image_number == m_nb_frames);
DEB_PARAM() << DEB_VAR2(m_frames_acquired, m_nb_frames);
bool finished = (m_frames_acquired == m_nb_frames);
DEB_RETURN() << DEB_VAR1(finished);
return finished;
}
......
......@@ -166,9 +166,16 @@ void Interface::getStatus(StatusType& status)
{
case Camera::Ready:
{
bool mult_trig_in_progress = false;
TrigMode trig_mode;
m_cam.getTrigMode(trig_mode);
if ((trig_mode == IntTrigMult) && !m_cam.allFramesAcquired())
if (trig_mode == IntTrigMult) {
int tot_nb_frames, nb_trig_frames;
m_cam.getNbFrames(tot_nb_frames);
m_cam.getNbTriggeredFrames(nb_trig_frames);
mult_trig_in_progress = (nb_trig_frames != tot_nb_frames);
}
if (mult_trig_in_progress)
status.set(HwInterface::StatusType::Ready);
else if (m_saving->isActive())
{
......
......@@ -116,7 +116,7 @@ std::ostream& lima::Eiger::operator <<(std::ostream& os,
// --- Stream class ---
inline bool Stream::_isRunning() const
{
return ((m_state == Connected) || (m_state == Armed) || (m_state == Running));
return ((m_state != Idle) && (m_state != Failed));
}
inline Json::Value Stream::_get_json_header(MessagePtr &msg)
......@@ -259,6 +259,8 @@ void Stream::stop()
return;
DEB_TRACE() << "Stopped";
m_state = Stopped;
while (_isRunning())
m_cond.wait();
}
void Stream::abort()
......@@ -280,18 +282,18 @@ void Stream::_abort()
{
DEB_MEMBER_FUNCT();
if((m_state == Running) || (m_state == Stopped)) {
DEB_TRACE() << "Aborting";
m_state = Aborting;
_send_synchro();
m_cond.broadcast();
while((m_state != Idle) && (m_state != Failed))
m_cond.wait();
}
if (m_state == Failed) {
if(m_state == Failed) {
m_state = Idle;
THROW_HW_ERROR(Error) << "Stream failed";
}
} else if(!_isRunning())
return;
DEB_TRACE() << "Aborting";
m_state = Aborting;
_send_synchro();
m_cond.broadcast();
while(_isRunning())
m_cond.wait();
}
bool Stream::isRunning() const
......@@ -324,13 +326,18 @@ void Stream::setActive(bool active)
AutoMutex lock(m_cond.mutex());
DEB_TRACE() << DEB_VAR2(m_active.value(), m_state);
// wait for previous sequence to finish
while((m_state == Running) || (m_state == Stopped))
m_cond.wait();
if(!active) {
bool is_ready = ((m_state == Connected) || (m_state == Armed));
bool do_abort = (!active && is_ready);
if(!do_abort && _isRunning()) {
DEB_WARNING() << "Stream is Running: Aborting!";
do_abort = true;
}
if(do_abort) {
_abort();
} else {
is_ready = false;
}
if(active) {
std::string s;
switch(m_header_detail) {
case ALL:
......@@ -349,7 +356,7 @@ void Stream::setActive(bool active)
if(m_active.changed(active))
_setStreamMode(m_active);
if(!m_active || (m_state == Connected) || (m_state == Armed))
if(!m_active || is_ready)
return;
m_state = Starting;
......@@ -368,7 +375,7 @@ void Stream::setActive(bool active)
void Stream::waitArmed(double timeout)
{
DEB_MEMBER_FUNCT();
DEB_PARAM() << DEB_VAR1(timeout);
AutoMutex lock(m_cond.mutex());
Timestamp t0 = Timestamp::now();
DEB_TRACE() << DEB_VAR1(m_state);
......@@ -548,7 +555,8 @@ bool Stream::_read_zmq_messages(void *stream_socket)
bool is_global_header = (htype.find("dheader-") != std::string::npos);
if (is_global_header != waiting_global_header) {
DEB_WARNING() << "Global header mismatch: "
<< DEB_VAR2(is_global_header, waiting_global_header);
<< DEB_VAR2(is_global_header, waiting_global_header)
<< ": " << htype;
return true;
} else if (is_global_header) {
Json::Value header = _get_global_header(stream_header,pending_messages);
......@@ -617,8 +625,8 @@ bool Stream::_read_zmq_messages(void *stream_socket)
lock.unlock();
}
bool continue_flag = m_buffer_mgr->newFrameReady(frame_info);
m_cam.newFrameAcquired();
bool continue_flag = m_buffer_mgr->newFrameReady(frame_info);
bool do_disarm = (m_ext_trigger && m_cam.allFramesAcquired());
if (!continue_flag && !do_disarm) {
DEB_WARNING() << "Unexpected " << DEB_VAR1(continue_flag) << ": "
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment