Merge remote-tracking branch 'upstream/mueller/master' into mueller/master

This commit is contained in:
Robin Müller 2021-05-31 17:06:07 +02:00
commit c3be4cdee6
4 changed files with 313 additions and 301 deletions

View File

@ -138,9 +138,9 @@ else()
) )
endif() endif()
foreach(INCLUDE_PATH ${FSFW_ADDITIONAL_INC_PATH}) foreach(INCLUDE_PATH ${FSFW_ADDITIONAL_INC_PATHS})
if(IS_ABSOLUTE ${INCLUDE_PATH}) if(IS_ABSOLUTE ${INCLUDE_PATH})
set(CURR_ABS_INC_PATH "${FREERTOS_PATH}") set(CURR_ABS_INC_PATH "${INCLUDE_PATH}")
else() else()
get_filename_component(CURR_ABS_INC_PATH get_filename_component(CURR_ABS_INC_PATH
${INCLUDE_PATH} REALPATH BASE_DIR ${CMAKE_SOURCE_DIR}) ${INCLUDE_PATH} REALPATH BASE_DIR ${CMAKE_SOURCE_DIR})

View File

@ -156,11 +156,11 @@ void EventManager::printUtility(sif::OutputTypes printType, EventMessage *messag
sif::info << "0x" << std::hex << std::setw(8) << std::setfill('0') << sif::info << "0x" << std::hex << std::setw(8) << std::setfill('0') <<
message->getReporter() << std::setfill(' ') << std::dec; message->getReporter() << std::setfill(' ') << std::dec;
} }
sif::info << " report event with ID " << message->getEventId() << std::endl; sif::info << " reported event with ID " << message->getEventId() << std::endl;
sif::info << std::hex << "P1 Hex: 0x" << message->getParameter1() << sif::debug << translateEvents(message->getEvent()) << " | " <<std::hex << "P1 Hex: 0x" <<
" | P1 Dec: " << std::dec << message->getParameter1() << std::hex << message->getParameter1() << " | P1 Dec: " << std::dec << message->getParameter1() <<
" | P2 Hex: 0x" << message->getParameter2() << " | P2 Dec: " << std::dec << std::hex << " | P2 Hex: 0x" << message->getParameter2() << " | P2 Dec: " <<
message->getParameter2() << std::endl; std::dec << message->getParameter2() << std::endl;
#else #else
if (string != 0) { if (string != 0) {
sif::printInfo("Event Manager: %s reported event with ID %d\n", string, sif::printInfo("Event Manager: %s reported event with ID %d\n", string,
@ -186,11 +186,11 @@ void EventManager::printUtility(sif::OutputTypes printType, EventMessage *messag
sif::debug << "0x" << std::hex << std::setw(8) << std::setfill('0') << sif::debug << "0x" << std::hex << std::setw(8) << std::setfill('0') <<
message->getReporter() << std::setfill(' ') << std::dec; message->getReporter() << std::setfill(' ') << std::dec;
} }
sif::debug << " report event with ID " << message->getEventId() << std::endl; sif::debug << " reported event with ID " << message->getEventId() << std::endl;
sif::debug << std::hex << "P1 Hex: 0x" << message->getParameter1() << sif::debug << translateEvents(message->getEvent()) << " | " <<std::hex << "P1 Hex: 0x" <<
" | P1 Dec: " << std::dec << message->getParameter1() << std::hex << message->getParameter1() << " | P1 Dec: " << std::dec << message->getParameter1() <<
" | P2 Hex: 0x" << message->getParameter2() << " | P2 Dec: " << std::dec << std::hex << " | P2 Hex: 0x" << message->getParameter2() << " | P2 Dec: " <<
message->getParameter2() << std::endl; std::dec << message->getParameter2() << std::endl;
#else #else
if (string != 0) { if (string != 0) {
sif::printDebug("Event Manager: %s reported event with ID %d\n", string, sif::printDebug("Event Manager: %s reported event with ID %d\n", string,

View File

@ -11,65 +11,64 @@
MessageQueue::MessageQueue(uint32_t messageDepth, size_t maxMessageSize): MessageQueue::MessageQueue(uint32_t messageDepth, size_t maxMessageSize):
id(MessageQueueIF::NO_QUEUE),lastPartner(MessageQueueIF::NO_QUEUE), id(MessageQueueIF::NO_QUEUE),lastPartner(MessageQueueIF::NO_QUEUE),
defaultDestination(MessageQueueIF::NO_QUEUE), defaultDestination(MessageQueueIF::NO_QUEUE), maxMessageSize(maxMessageSize) {
maxMessageSize(maxMessageSize) { //debug << "MessageQueue::MessageQueue: Creating a queue" << std::endl;
//debug << "MessageQueue::MessageQueue: Creating a queue" << std::endl; mq_attr attributes;
mq_attr attributes; this->id = 0;
this->id = 0; //Set attributes
//Set attributes attributes.mq_curmsgs = 0;
attributes.mq_curmsgs = 0; attributes.mq_maxmsg = messageDepth;
attributes.mq_maxmsg = messageDepth; attributes.mq_msgsize = maxMessageSize;
attributes.mq_msgsize = maxMessageSize; attributes.mq_flags = 0; //Flags are ignored on Linux during mq_open
attributes.mq_flags = 0; //Flags are ignored on Linux during mq_open //Set the name of the queue. The slash is mandatory!
//Set the name of the queue. The slash is mandatory! sprintf(name, "/FSFW_MQ%u\n", queueCounter++);
sprintf(name, "/FSFW_MQ%u\n", queueCounter++);
// Create a nonblocking queue if the name is available (the queue is read // Create a nonblocking queue if the name is available (the queue is read
// and writable for the owner as well as the group) // and writable for the owner as well as the group)
int oflag = O_NONBLOCK | O_RDWR | O_CREAT | O_EXCL; int oflag = O_NONBLOCK | O_RDWR | O_CREAT | O_EXCL;
mode_t mode = S_IWUSR | S_IREAD | S_IWGRP | S_IRGRP | S_IROTH | S_IWOTH; mode_t mode = S_IWUSR | S_IREAD | S_IWGRP | S_IRGRP | S_IROTH | S_IWOTH;
mqd_t tempId = mq_open(name, oflag, mode, &attributes); mqd_t tempId = mq_open(name, oflag, mode, &attributes);
if (tempId == -1) { if (tempId == -1) {
handleError(&attributes, messageDepth); handleError(&attributes, messageDepth);
} }
else { else {
//Successful mq_open call //Successful mq_open call
this->id = tempId; this->id = tempId;
} }
} }
MessageQueue::~MessageQueue() { MessageQueue::~MessageQueue() {
int status = mq_close(this->id); int status = mq_close(this->id);
if(status != 0){ if(status != 0){
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MessageQueue::Destructor: mq_close Failed with status: " sif::error << "MessageQueue::Destructor: mq_close Failed with status: "
<< strerror(errno) <<std::endl; << strerror(errno) <<std::endl;
#endif #endif
} }
status = mq_unlink(name); status = mq_unlink(name);
if(status != 0){ if(status != 0){
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MessageQueue::Destructor: mq_unlink Failed with status: " sif::error << "MessageQueue::Destructor: mq_unlink Failed with status: "
<< strerror(errno) << std::endl; << strerror(errno) << std::endl;
#endif #endif
} }
} }
ReturnValue_t MessageQueue::handleError(mq_attr* attributes, ReturnValue_t MessageQueue::handleError(mq_attr* attributes,
uint32_t messageDepth) { uint32_t messageDepth) {
switch(errno) { switch(errno) {
case(EINVAL): { case(EINVAL): {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MessageQueue::MessageQueue: Invalid name or attributes" sif::error << "MessageQueue::MessageQueue: Invalid name or attributes"
" for message size" << std::endl; " for message size" << std::endl;
#endif #endif
size_t defaultMqMaxMsg = 0; size_t defaultMqMaxMsg = 0;
// Not POSIX conformant, but should work for all UNIX systems. // Not POSIX conformant, but should work for all UNIX systems.
// Just an additional helpful printout :-) // Just an additional helpful printout :-)
if(std::ifstream("/proc/sys/fs/mqueue/msg_max",std::ios::in) >> if(std::ifstream("/proc/sys/fs/mqueue/msg_max",std::ios::in) >>
defaultMqMaxMsg and defaultMqMaxMsg < messageDepth) { defaultMqMaxMsg and defaultMqMaxMsg < messageDepth) {
/* /*
See: https://www.man7.org/linux/man-pages/man3/mq_open.3.html See: https://www.man7.org/linux/man-pages/man3/mq_open.3.html
This happens if the msg_max value is not large enough This happens if the msg_max value is not large enough
It is ignored if the executable is run in privileged mode. It is ignored if the executable is run in privileged mode.
@ -83,326 +82,338 @@ ReturnValue_t MessageQueue::handleError(mq_attr* attributes,
sudo nano /etc/sysctl.conf sudo nano /etc/sysctl.conf
Append at end: fs/mqueue/msg_max = <newMsgMaxLen> Append at end: fs/mqueue/msg_max = <newMsgMaxLen>
Apply changes with: sudo sysctl -p Apply changes with: sudo sysctl -p
*/ */
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MessageQueue::MessageQueue: Default MQ size " sif::error << "MessageQueue::MessageQueue: Default MQ size "
<< defaultMqMaxMsg << " is too small for requested size " << defaultMqMaxMsg << " is too small for requested size "
<< messageDepth << std::endl; << messageDepth << std::endl;
sif::error << "This error can be fixed by setting the maximum " sif::error << "This error can be fixed by setting the maximum "
"allowed message size higher!" << std::endl; "allowed message size higher!" << std::endl;
#endif #endif
}
} break;
break; }
} case(EEXIST): {
case(EEXIST): { // An error occured during open
// An error occured during open // We need to distinguish if it is caused by an already created queue
// We need to distinguish if it is caused by an already created queue // There's another queue with the same name
//There's another queue with the same name // We unlink the other queue
//We unlink the other queue int status = mq_unlink(name);
int status = mq_unlink(name); if (status != 0) {
if (status != 0) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "mq_unlink Failed with status: " << strerror(errno) sif::error << "mq_unlink Failed with status: " << strerror(errno)
<< std::endl; << std::endl;
#endif #endif
} }
else { else {
// Successful unlinking, try to open again // Successful unlinking, try to open again
mqd_t tempId = mq_open(name, mqd_t tempId = mq_open(name,
O_NONBLOCK | O_RDWR | O_CREAT | O_EXCL, O_NONBLOCK | O_RDWR | O_CREAT | O_EXCL,
S_IWUSR | S_IREAD | S_IWGRP | S_IRGRP, attributes); S_IWUSR | S_IREAD | S_IWGRP | S_IRGRP, attributes);
if (tempId != -1) { if (tempId != -1) {
//Successful mq_open //Successful mq_open
this->id = tempId; this->id = tempId;
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
} }
break; break;
} }
default: { default: {
// Failed either the first time or the second time // Failed either the first time or the second time
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MessageQueue::MessageQueue: Creating Queue " << name sif::error << "MessageQueue::MessageQueue: Creating Queue " << name
<< " failed with status: " << strerror(errno) << std::endl; << " failed with status: " << strerror(errno) << std::endl;
#else #else
sif::printError("MessageQueue::MessageQueue: Creating Queue %s" sif::printError("MessageQueue::MessageQueue: Creating Queue %s"
" failed with status: %s\n", name, strerror(errno)); " failed with status: %s\n", name, strerror(errno));
#endif #endif
} }
} }
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo,
MessageQueueMessageIF* message, bool ignoreFault) { MessageQueueMessageIF* message, bool ignoreFault) {
return sendMessageFrom(sendTo, message, this->getId(), false); return sendMessageFrom(sendTo, message, this->getId(), false);
} }
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) { ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) {
return sendToDefaultFrom(message, this->getId()); return sendToDefaultFrom(message, this->getId());
} }
ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) { ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) {
if (this->lastPartner != 0) { if (this->lastPartner != 0) {
return sendMessageFrom(this->lastPartner, message, this->getId()); return sendMessageFrom(this->lastPartner, message, this->getId());
} else { } else {
return NO_REPLY_PARTNER; return NO_REPLY_PARTNER;
} }
} }
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message, ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t* receivedFrom) { MessageQueueId_t* receivedFrom) {
ReturnValue_t status = this->receiveMessage(message); ReturnValue_t status = this->receiveMessage(message);
*receivedFrom = this->lastPartner; *receivedFrom = this->lastPartner;
return status; return status;
} }
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) { ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
if(message == nullptr) { if(message == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MessageQueue::receiveMessage: Message is " sif::error << "MessageQueue::receiveMessage: Message is "
"nullptr!" << std::endl; "nullptr!" << std::endl;
#endif #endif
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
if(message->getMaximumMessageSize() < maxMessageSize) { if(message->getMaximumMessageSize() < maxMessageSize) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MessageQueue::receiveMessage: Message size " sif::error << "MessageQueue::receiveMessage: Message size "
<< message->getMaximumMessageSize() << message->getMaximumMessageSize()
<< " too small to receive data!" << std::endl; << " too small to receive data!" << std::endl;
#endif #endif
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
unsigned int messagePriority = 0; unsigned int messagePriority = 0;
int status = mq_receive(id,reinterpret_cast<char*>(message->getBuffer()), int status = mq_receive(id,reinterpret_cast<char*>(message->getBuffer()),
message->getMaximumMessageSize(),&messagePriority); message->getMaximumMessageSize(),&messagePriority);
if (status > 0) { if (status > 0) {
this->lastPartner = message->getSender(); this->lastPartner = message->getSender();
//Check size of incoming message. //Check size of incoming message.
if (message->getMessageSize() < message->getMinimumMessageSize()) { if (message->getMessageSize() < message->getMinimumMessageSize()) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
else if (status==0) { else if (status==0) {
//Success but no message received //Success but no message received
return MessageQueueIF::EMPTY; return MessageQueueIF::EMPTY;
} }
else { else {
//No message was received. Keep lastPartner anyway, I might send //No message was received. Keep lastPartner anyway, I might send
//something later. But still, delete packet content. //something later. But still, delete packet content.
memset(message->getData(), 0, message->getMaximumDataSize()); memset(message->getData(), 0, message->getMaximumDataSize());
switch(errno){ switch(errno){
case EAGAIN: case EAGAIN:
//O_NONBLOCK or MQ_NONBLOCK was set and there are no messages //O_NONBLOCK or MQ_NONBLOCK was set and there are no messages
//currently on the specified queue. //currently on the specified queue.
return MessageQueueIF::EMPTY; return MessageQueueIF::EMPTY;
case EBADF: case EBADF: {
//mqdes doesn't represent a valid queue open for reading. //mqdes doesn't represent a valid queue open for reading.
#if FSFW_CPP_OSTREAM_ENABLED == 1 return handleRecvError("EBADF");
sif::error << "MessageQueue::receive: configuration error " }
<< strerror(errno) << std::endl; case EINVAL: {
#endif /*
/*NO BREAK*/ * This value indicates one of the following:
case EINVAL: * - The pointer to the buffer for storing the received message,
/* * msg_ptr, is NULL.
* This value indicates one of the following: * - The number of bytes requested, msg_len is less than zero.
* - The pointer to the buffer for storing the received message, * - msg_len is anything other than the mq_msgsize of the specified
* msg_ptr, is NULL. * queue, and the QNX extended option MQ_READBUF_DYNAMIC hasn't
* - The number of bytes requested, msg_len is less than zero. * been set in the queue's mq_flags.
* - msg_len is anything other than the mq_msgsize of the specified */
* queue, and the QNX extended option MQ_READBUF_DYNAMIC hasn't return handleRecvError("EINVAL");
* been set in the queue's mq_flags. }
*/ case EMSGSIZE: {
#if FSFW_CPP_OSTREAM_ENABLED == 1 /*
sif::error << "MessageQueue::receive: configuration error " * This value indicates one of the following:
<< strerror(errno) << std::endl; * - the QNX extended option MQ_READBUF_DYNAMIC hasn't been set,
#endif * and the given msg_len is shorter than the mq_msgsize for
/*NO BREAK*/ * the given queue.
case EMSGSIZE: * - the extended option MQ_READBUF_DYNAMIC has been set, but the
/* * given msg_len is too short for the message that would have
* This value indicates one of the following: * been received.
* - the QNX extended option MQ_READBUF_DYNAMIC hasn't been set, */
* and the given msg_len is shorter than the mq_msgsize for return handleRecvError("EMSGSIZE");
* the given queue. }
* - the extended option MQ_READBUF_DYNAMIC has been set, but the
* given msg_len is too short for the message that would have
* been received.
*/
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MessageQueue::receive: configuration error "
<< strerror(errno) << std::endl;
#endif
/*NO BREAK*/
case EINTR:
//The operation was interrupted by a signal.
default:
return HasReturnvaluesIF::RETURN_FAILED; case EINTR: {
} //The operation was interrupted by a signal.
return handleRecvError("EINTR");
}
case ETIMEDOUT: {
//The operation was interrupted by a signal.
return handleRecvError("ETIMEDOUT");
}
} default:
return HasReturnvaluesIF::RETURN_FAILED;
}
}
} }
MessageQueueId_t MessageQueue::getLastPartner() const { MessageQueueId_t MessageQueue::getLastPartner() const {
return this->lastPartner; return this->lastPartner;
} }
ReturnValue_t MessageQueue::flush(uint32_t* count) { ReturnValue_t MessageQueue::flush(uint32_t* count) {
mq_attr attrib; mq_attr attrib;
int status = mq_getattr(id,&attrib); int status = mq_getattr(id,&attrib);
if(status != 0){ if(status != 0){
switch(errno){ switch(errno){
case EBADF: case EBADF:
//mqdes doesn't represent a valid message queue. //mqdes doesn't represent a valid message queue.
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MessageQueue::flush configuration error, " sif::error << "MessageQueue::flush configuration error, "
"called flush with an invalid queue ID" << std::endl; "called flush with an invalid queue ID" << std::endl;
#endif #endif
/*NO BREAK*/ /*NO BREAK*/
case EINVAL: case EINVAL:
//mq_attr is NULL //mq_attr is NULL
default: default:
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
} }
*count = attrib.mq_curmsgs; *count = attrib.mq_curmsgs;
attrib.mq_curmsgs = 0; attrib.mq_curmsgs = 0;
status = mq_setattr(id,&attrib,NULL); status = mq_setattr(id,&attrib,NULL);
if(status != 0){ if(status != 0){
switch(errno){ switch(errno){
case EBADF: case EBADF:
//mqdes doesn't represent a valid message queue. //mqdes doesn't represent a valid message queue.
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MessageQueue::flush configuration error, " sif::error << "MessageQueue::flush configuration error, "
"called flush with an invalid queue ID" << std::endl; "called flush with an invalid queue ID" << std::endl;
#endif #endif
/*NO BREAK*/ /*NO BREAK*/
case EINVAL: case EINVAL:
/* /*
* This value indicates one of the following: * This value indicates one of the following:
* - mq_attr is NULL. * - mq_attr is NULL.
* - MQ_MULT_NOTIFY had been set for this queue, and the given * - MQ_MULT_NOTIFY had been set for this queue, and the given
* mq_flags includes a 0 in the MQ_MULT_NOTIFY bit. Once * mq_flags includes a 0 in the MQ_MULT_NOTIFY bit. Once
* MQ_MULT_NOTIFY has been turned on, it may never be turned off. * MQ_MULT_NOTIFY has been turned on, it may never be turned off.
*/ */
default: default:
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
MessageQueueId_t MessageQueue::getId() const { MessageQueueId_t MessageQueue::getId() const {
return this->id; return this->id;
} }
void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) { void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) {
this->defaultDestination = defaultDestination; this->defaultDestination = defaultDestination;
} }
ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessageIF* message, ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault) { MessageQueueId_t sentFrom, bool ignoreFault) {
return sendMessageFrom(defaultDestination, message, sentFrom, ignoreFault); return sendMessageFrom(defaultDestination, message, sentFrom, ignoreFault);
} }
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo,
MessageQueueMessageIF* message, MessageQueueId_t sentFrom, MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
bool ignoreFault) { bool ignoreFault) {
return sendMessageFromMessageQueue(sendTo,message, sentFrom,ignoreFault); return sendMessageFromMessageQueue(sendTo,message, sentFrom,ignoreFault);
} }
MessageQueueId_t MessageQueue::getDefaultDestination() const { MessageQueueId_t MessageQueue::getDefaultDestination() const {
return this->defaultDestination; return this->defaultDestination;
} }
bool MessageQueue::isDefaultDestinationSet() const { bool MessageQueue::isDefaultDestinationSet() const {
return (defaultDestination != NO_QUEUE); return (defaultDestination != NO_QUEUE);
} }
uint16_t MessageQueue::queueCounter = 0; uint16_t MessageQueue::queueCounter = 0;
ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
MessageQueueMessageIF *message, MessageQueueId_t sentFrom, MessageQueueMessageIF *message, MessageQueueId_t sentFrom,
bool ignoreFault) { bool ignoreFault) {
if(message == nullptr) { if(message == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MessageQueue::sendMessageFromMessageQueue: Message is " sif::error << "MessageQueue::sendMessageFromMessageQueue: Message is "
"nullptr!" << std::endl; "nullptr!" << std::endl;
#endif #endif
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
message->setSender(sentFrom); message->setSender(sentFrom);
int result = mq_send(sendTo, int result = mq_send(sendTo,
reinterpret_cast<const char*>(message->getBuffer()), reinterpret_cast<const char*>(message->getBuffer()),
message->getMessageSize(),0); message->getMessageSize(),0);
//TODO: Check if we're in ISR. //TODO: Check if we're in ISR.
if (result != 0) { if (result != 0) {
if(!ignoreFault){ if(!ignoreFault){
InternalErrorReporterIF* internalErrorReporter = InternalErrorReporterIF* internalErrorReporter =
objectManager->get<InternalErrorReporterIF>( objectManager->get<InternalErrorReporterIF>(
objects::INTERNAL_ERROR_REPORTER); objects::INTERNAL_ERROR_REPORTER);
if (internalErrorReporter != NULL) { if (internalErrorReporter != NULL) {
internalErrorReporter->queueMessageNotSent(); internalErrorReporter->queueMessageNotSent();
} }
} }
switch(errno){ switch(errno){
case EAGAIN: case EAGAIN:
//The O_NONBLOCK flag was set when opening the queue, or the //The O_NONBLOCK flag was set when opening the queue, or the
//MQ_NONBLOCK flag was set in its attributes, and the //MQ_NONBLOCK flag was set in its attributes, and the
//specified queue is full. //specified queue is full.
return MessageQueueIF::FULL; return MessageQueueIF::FULL;
case EBADF: { case EBADF: {
//mq_des doesn't represent a valid message queue descriptor, //mq_des doesn't represent a valid message queue descriptor,
//or mq_des wasn't opened for writing. //or mq_des wasn't opened for writing.
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MessageQueue::sendMessage: Configuration error, MQ" sif::error << "MessageQueue::sendMessage: Configuration error, MQ"
<< " destination invalid." << std::endl; << " destination invalid." << std::endl;
sif::error << strerror(errno) << " in " sif::error << strerror(errno) << " in "
<<"mq_send to: " << sendTo << " sent from " <<"mq_send to: " << sendTo << " sent from "
<< sentFrom << std::endl; << sentFrom << std::endl;
#endif #endif
return DESTINATION_INVALID; return DESTINATION_INVALID;
} }
case EINTR: case EINTR:
//The call was interrupted by a signal. //The call was interrupted by a signal.
case EINVAL: case EINVAL:
/* /*
* This value indicates one of the following: * This value indicates one of the following:
* - msg_ptr is NULL. * - msg_ptr is NULL.
* - msg_len is negative. * - msg_len is negative.
* - msg_prio is greater than MQ_PRIO_MAX. * - msg_prio is greater than MQ_PRIO_MAX.
* - msg_prio is less than 0. * - msg_prio is less than 0.
* - MQ_PRIO_RESTRICT is set in the mq_attr of mq_des, and * - MQ_PRIO_RESTRICT is set in the mq_attr of mq_des, and
* msg_prio is greater than the priority of the calling process. * msg_prio is greater than the priority of the calling process.
*/ */
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MessageQueue::sendMessage: Configuration error " sif::error << "MessageQueue::sendMessage: Configuration error "
<< strerror(errno) << " in mq_send" << std::endl; << strerror(errno) << " in mq_send" << std::endl;
#endif #endif
/*NO BREAK*/ /*NO BREAK*/
case EMSGSIZE: case EMSGSIZE:
// The msg_len is greater than the msgsize associated with // The msg_len is greater than the msgsize associated with
//the specified queue. //the specified queue.
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MessageQueue::sendMessage: Size error [" << sif::error << "MessageQueue::sendMessage: Size error [" <<
strerror(errno) << "] in mq_send" << std::endl; strerror(errno) << "] in mq_send" << std::endl;
#endif #endif
/*NO BREAK*/ /*NO BREAK*/
default: default:
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t MessageQueue::handleRecvError(const char * const failString) {
if(failString == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MessageQueue::receiveMessage: " << failString << " error "
<< strerror(errno) << std::endl;
#else
sif::printError("MessageQueue::receiveMessage: %s error %s\n", failString,
strerror(errno));
#endif
return HasReturnvaluesIF::RETURN_FAILED;
} }

View File

@ -182,6 +182,7 @@ private:
const size_t maxMessageSize; const size_t maxMessageSize;
ReturnValue_t handleError(mq_attr* attributes, uint32_t messageDepth); ReturnValue_t handleError(mq_attr* attributes, uint32_t messageDepth);
ReturnValue_t handleRecvError(const char* const failString);
}; };
#endif /* FSFW_OSAL_LINUX_MESSAGEQUEUE_H_ */ #endif /* FSFW_OSAL_LINUX_MESSAGEQUEUE_H_ */