Commit 091b2201 authored by Alejandro Homs Puron's avatar Alejandro Homs Puron Committed by operator for beamline
Browse files

ThreadUtils: add OS error code information when throwing exceptions

parent b2dd9e87
...@@ -84,7 +84,7 @@ Exception::Exception(Layer layer, ErrorType err_type, const string& err_desc, ...@@ -84,7 +84,7 @@ Exception::Exception(Layer layer, ErrorType err_type, const string& err_desc,
<< getErrDesc(); << getErrDesc();
else else
std::cerr << "********* Exception(" << getErrType() << "): " std::cerr << "********* Exception(" << getErrType() << "): "
<< getErrDesc(); << getErrDesc() << " *********" << std::endl;
} }
Layer Exception::getLayer() const Layer Exception::getLayer() const
......
...@@ -36,10 +36,20 @@ ...@@ -36,10 +36,20 @@
using namespace lima; using namespace lima;
inline void check_error(int ret, const char *desc)
{
if (ret == 0)
return;
std::ostringstream os;
os << desc << ": " << strerror(ret) << " (" << ret << ")";
throw LIMA_COM_EXC(Error, os.str());
}
MutexAttr::MutexAttr(Type type) MutexAttr::MutexAttr(Type type)
{ {
if (pthread_mutexattr_init(&m_mutex_attr) != 0) int ret = pthread_mutexattr_init(&m_mutex_attr);
throw LIMA_COM_EXC(Error, "Error initializing mutex attr"); check_error(ret, "Error initializing mutex attr");
try { try {
setType(type); setType(type);
...@@ -76,15 +86,15 @@ void MutexAttr::setType(Type type) ...@@ -76,15 +86,15 @@ void MutexAttr::setType(Type type)
throw LIMA_COM_EXC(InvalidValue, "Invalid MutexAttr type"); throw LIMA_COM_EXC(InvalidValue, "Invalid MutexAttr type");
} }
if (pthread_mutexattr_settype(&m_mutex_attr, kind) != 0) int ret = pthread_mutexattr_settype(&m_mutex_attr, kind);
throw LIMA_COM_EXC(Error, "Error setting mutex attr"); check_error(ret, "Error setting mutex attr");
} }
MutexAttr::Type MutexAttr::getType() const MutexAttr::Type MutexAttr::getType() const
{ {
int kind; int kind;
if (pthread_mutexattr_gettype(&m_mutex_attr, &kind) != 0) int ret = pthread_mutexattr_gettype(&m_mutex_attr, &kind);
throw LIMA_COM_EXC(Error, "Error getting mutex attr"); check_error(ret, "Error getting mutex attr");
switch (kind) { switch (kind) {
case PTHREAD_MUTEX_NORMAL: case PTHREAD_MUTEX_NORMAL:
...@@ -120,8 +130,8 @@ Mutex::Mutex(MutexAttr mutex_attr) ...@@ -120,8 +130,8 @@ Mutex::Mutex(MutexAttr mutex_attr)
: m_mutex_attr(mutex_attr) : m_mutex_attr(mutex_attr)
{ {
pthread_mutexattr_t& attr = m_mutex_attr.m_mutex_attr; pthread_mutexattr_t& attr = m_mutex_attr.m_mutex_attr;
if (pthread_mutex_init(&m_mutex, &attr) != 0) int ret = pthread_mutex_init(&m_mutex, &attr);
throw LIMA_COM_EXC(Error, "Error initializing mutex"); check_error(ret, "Error initializing mutex");
} }
Mutex::~Mutex() Mutex::~Mutex()
...@@ -131,14 +141,14 @@ Mutex::~Mutex() ...@@ -131,14 +141,14 @@ Mutex::~Mutex()
void Mutex::lock() void Mutex::lock()
{ {
if (pthread_mutex_lock(&m_mutex) != 0) int ret = pthread_mutex_lock(&m_mutex);
throw LIMA_COM_EXC(Error, "Error locking mutex"); check_error(ret, "Error locking mutex");
} }
void Mutex::unlock() void Mutex::unlock()
{ {
if (pthread_mutex_unlock(&m_mutex) != 0) int ret = pthread_mutex_unlock(&m_mutex);
throw LIMA_COM_EXC(Error, "Error unlocking mutex"); check_error(ret, "Error unlocking mutex");
} }
bool Mutex::tryLock() bool Mutex::tryLock()
...@@ -162,8 +172,8 @@ MutexAttr Mutex::getAttr() ...@@ -162,8 +172,8 @@ MutexAttr Mutex::getAttr()
Cond::Cond() : m_mutex(MutexAttr::Normal) Cond::Cond() : m_mutex(MutexAttr::Normal)
{ {
if (pthread_cond_init(&m_cond, NULL) != 0) int ret = pthread_cond_init(&m_cond, NULL);
throw LIMA_COM_EXC(Error, "Error initializing condition"); check_error(ret, "Error initializing condition");
} }
Cond::~Cond() Cond::~Cond()
...@@ -194,15 +204,15 @@ bool Cond::wait(double timeout) ...@@ -194,15 +204,15 @@ bool Cond::wait(double timeout)
else else
retcode = pthread_cond_wait(&m_cond, &m_mutex.m_mutex); retcode = pthread_cond_wait(&m_cond, &m_mutex.m_mutex);
if(retcode && retcode != ETIMEDOUT) if(retcode != ETIMEDOUT)
throw LIMA_COM_EXC(Error, "Error waiting for condition"); check_error(retcode, "Error waiting for condition");
return !retcode; return !retcode;
} }
void Cond::signal() void Cond::signal()
{ {
if (pthread_cond_signal(&m_cond) != 0) int ret = pthread_cond_signal(&m_cond);
throw LIMA_COM_EXC(Error, "Error signaling condition"); check_error(ret, "Error signaling condition");
} }
void Cond::acquire() void Cond::acquire()
...@@ -217,8 +227,8 @@ void Cond::release() ...@@ -217,8 +227,8 @@ void Cond::release()
void Cond::broadcast() void Cond::broadcast()
{ {
if (pthread_cond_broadcast(&m_cond) != 0) int ret = pthread_cond_broadcast(&m_cond);
throw LIMA_COM_EXC(Error, "Error broadcast condition"); check_error(ret, "Error broadcast condition");
} }
pid_t lima::GetThreadID() { pid_t lima::GetThreadID() {
...@@ -241,7 +251,9 @@ Thread::ExceptionCleanUp::~ExceptionCleanUp() ...@@ -241,7 +251,9 @@ Thread::ExceptionCleanUp::~ExceptionCleanUp()
m_thread.m_exception_handled = true; m_thread.m_exception_handled = true;
} }
Thread::Thread() : m_thread(NULL), m_started(false), m_finished(false), m_exception_handled(false), m_tid(0) Thread::Thread()
: m_thread(0), m_started(false), m_finished(false),
m_exception_handled(false), m_tid(0)
{ {
pthread_attr_init(&m_thread_attr); pthread_attr_init(&m_thread_attr);
} }
...@@ -259,8 +271,9 @@ void Thread::start() ...@@ -259,8 +271,9 @@ void Thread::start()
throw LIMA_COM_EXC(Error, "Thread already started"); throw LIMA_COM_EXC(Error, "Thread already started");
m_finished = false; m_finished = false;
if (pthread_create(&m_thread, &m_thread_attr, staticThreadFunction, this) != 0) int ret = pthread_create(&m_thread, &m_thread_attr,
throw LIMA_HW_EXC(Error, "Error creating thread"); staticThreadFunction, this);
check_error(ret, "Error creating thread");
m_started = true; m_started = true;
} }
...@@ -418,7 +431,7 @@ void CmdThread::sendCmdIf(int cmd, bool (*if_test)(int,int)) ...@@ -418,7 +431,7 @@ void CmdThread::sendCmdIf(int cmd, bool (*if_test)(int,int))
void CmdThread::doSendCmd(int cmd) void CmdThread::doSendCmd(int cmd)
{ {
if (m_status == Finished) if (m_status == Finished)
throw LIMA_HW_EXC(Error, "Thread has Finished"); throw LIMA_COM_EXC(Error, "Thread has Finished");
// Assume that we will have a call to waitStatus somewhere after the new command // Assume that we will have a call to waitStatus somewhere after the new command
m_status_history.reset(); m_status_history.reset();
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
set(test_src test_membuffer test_ordered_map) set(test_src test_membuffer test_ordered_map)
if (NOT WIN32) if (NOT WIN32)
list(APPEND test_src test_regex) list(APPEND test_src test_regex test_mutex)
endif() endif()
limatools_run_camera_tests("${test_src}" ${NAME}) limatools_run_camera_tests("${test_src}" ${NAME})
#include "lima/ThreadUtils.h"
#include "lima/Debug.h"
#include "lima/Exceptions.h"
using namespace lima;
DEB_GLOBAL(DebModTest);
class TestThread : public Thread
{
DEB_CLASS(DebModTest, "TestThread");
public:
enum Type { Tester, Locker, Releaser };
TestThread(Type type) : m_type(type), m_started(false)
{
DEB_CONSTRUCTOR();
DEB_PARAM() << DEB_VAR1(type);
}
void start()
{
DEB_MEMBER_FUNCT();
Thread::start();
AutoMutex l(m_cond.mutex());
while (!m_started)
m_cond.wait();
DEB_TRACE() << "Main: started";
}
protected:
void threadFunction()
{
DEB_MEMBER_FUNCT();
CleanUp cleanup(*this);
if (m_type == Tester)
THROW_COM_ERROR(Error) << "Testing cleanup";
if (m_type == Locker) {
AutoMutex l(m_mutex);
l.leaveLocked();
DEB_TRACE() << "Leave locked";
} else {
AutoMutex l(m_mutex, AutoMutex::PrevLocked);
DEB_TRACE() << "Previously unlocked";
}
}
private:
class CleanUp : public ExceptionCleanUp
{
public:
using ExceptionCleanUp::ExceptionCleanUp;
virtual ~CleanUp() {
static_cast<TestThread&>(m_thread).signalStarted();
}
};
void signalStarted()
{
DEB_MEMBER_FUNCT();
AutoMutex l(m_cond.mutex());
m_started = true;
m_cond.signal();
DEB_TRACE() << "Thread: started";
}
static Mutex m_mutex;
Type m_type;
Cond m_cond;
bool m_started;
};
Mutex TestThread::m_mutex;
int main(int argc, char *argv[])
{
DEB_GLOBAL_FUNCT();
DebParams::setTypeFlags(DebParams::AllFlags);
DEB_TRACE() << "Starting test";
TestThread tester(TestThread::Tester);
tester.start();
tester.join();
TestThread locker(TestThread::Locker);
TestThread releaser(TestThread::Releaser);
locker.start();
releaser.start();
locker.join();
releaser.join();
return 0;
}
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