From 3277d199ac166db242ff1fb7b5edfab6fa2964ec Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 10 Jun 2020 01:07:50 +0200 Subject: [PATCH] linux mq update --- osal/linux/MessageQueue.cpp | 102 +++++++++++++++++++++--------------- 1 file changed, 60 insertions(+), 42 deletions(-) diff --git a/osal/linux/MessageQueue.cpp b/osal/linux/MessageQueue.cpp index 86d1e0d9..a9c140c6 100644 --- a/osal/linux/MessageQueue.cpp +++ b/osal/linux/MessageQueue.cpp @@ -56,16 +56,23 @@ ReturnValue_t MessageQueue::handleError(mq_attr* attributes, sif::error << "MessageQueue::MessageQueue: Invalid name or attributes" " for message size" << std::endl; size_t defaultMqMaxMsg = 0; + // Not POSIX conformant, but should work for all UNIX systems. + // Just an additional helpful printout :-) if(std::ifstream("/proc/sys/fs/mqueue/msg_max",std::ios::in) >> defaultMqMaxMsg and defaultMqMaxMsg < messageDepth) { // See: https://www.man7.org/linux/man-pages/man3/mq_open.3.html // This happens if the msg_max value is not large enough // It is ignored if the executable is run in privileged mode. - // Run the unlockRealtime script or grant the mode manully by using: + // Run the unlockRealtime script or grant the mode manually by using: // sudo setcap 'CAP_SYS_RESOURCE=+ep' - // Permanent solution (EventManager has mq depth of 80): - // echo msg_max | sudo tee /proc/sys/fs/mqueue/msg_max + // Persistent solution for session: + // echo | sudo tee /proc/sys/fs/mqueue/msg_max + + // Permanent solution: + // sudo nano /etc/sysctl.conf + // Append at end: fs/mqueue/msg_max = + // Apply changes with: sudo sysctl -p sif::error << "MessageQueue::MessageQueue: Default MQ size " << defaultMqMaxMsg << " is too small for requested size " << messageDepth << std::endl; @@ -75,24 +82,22 @@ ReturnValue_t MessageQueue::handleError(mq_attr* attributes, case(EEXIST): { // An error occured during open // We need to distinguish if it is caused by an already created queue - if (errno == EEXIST) { - //There's another queue with the same name - //We unlink the other queue - int status = mq_unlink(name); - if (status != 0) { - sif::error << "mq_unlink Failed with status: " << strerror(errno) - << std::endl; - } - else { - // Successful unlinking, try to open again - mqd_t tempId = mq_open(name, - O_NONBLOCK | O_RDWR | O_CREAT | O_EXCL, - S_IWUSR | S_IREAD | S_IWGRP | S_IRGRP, attributes); - if (tempId != -1) { - //Successful mq_open - this->id = tempId; - return HasReturnvaluesIF::RETURN_OK; - } + //There's another queue with the same name + //We unlink the other queue + int status = mq_unlink(name); + if (status != 0) { + sif::error << "mq_unlink Failed with status: " << strerror(errno) + << std::endl; + } + else { + // Successful unlinking, try to open again + mqd_t tempId = mq_open(name, + O_NONBLOCK | O_RDWR | O_CREAT | O_EXCL, + S_IWUSR | S_IREAD | S_IWGRP | S_IRGRP, attributes); + if (tempId != -1) { + //Successful mq_open + this->id = tempId; + return HasReturnvaluesIF::RETURN_OK; } } break; @@ -150,12 +155,13 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message) { //Success but no message received return MessageQueueIF::EMPTY; } else { - //No message was received. Keep lastPartner anyway, I might send something later. - //But still, delete packet content. + //No message was received. Keep lastPartner anyway, I might send + //something later. But still, delete packet content. memset(message->getData(), 0, message->MAX_DATA_SIZE); switch(errno){ case EAGAIN: - //O_NONBLOCK or MQ_NONBLOCK was set and there are no messages currently on the specified queue. + //O_NONBLOCK or MQ_NONBLOCK was set and there are no messages + //currently on the specified queue. return MessageQueueIF::EMPTY; case EBADF: //mqdes doesn't represent a valid queue open for reading. @@ -165,9 +171,12 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message) { case EINVAL: /* * This value indicates one of the following: - * * The pointer to the buffer for storing the received message, msg_ptr, is NULL. - * * The number of bytes requested, msg_len is less than zero. - * * msg_len is anything other than the mq_msgsize of the specified queue, and the QNX extended option MQ_READBUF_DYNAMIC hasn't been set in the queue's mq_flags. + * - The pointer to the buffer for storing the received message, + * msg_ptr, is NULL. + * - The number of bytes requested, msg_len is less than zero. + * - msg_len is anything other than the mq_msgsize of the specified + * queue, and the QNX extended option MQ_READBUF_DYNAMIC hasn't + * been set in the queue's mq_flags. */ sif::error << "MessageQueue::receive: configuration error " << strerror(errno) << std::endl; @@ -175,8 +184,12 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message) { case EMSGSIZE: /* * This value indicates one of the following: - * * the QNX extended option MQ_READBUF_DYNAMIC hasn't been set, and the given msg_len is shorter than the mq_msgsize for 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. + * - the QNX extended option MQ_READBUF_DYNAMIC hasn't been set, + * and the given msg_len is shorter than the mq_msgsize for + * 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. */ sif::error << "MessageQueue::receive: configuration error " << strerror(errno) << std::endl; @@ -224,9 +237,10 @@ ReturnValue_t MessageQueue::flush(uint32_t* count) { case EINVAL: /* * This value indicates one of the following: - * * mq_attr is NULL. - * * 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_MULT_NOTIFY has been turned on, it may never be turned off. - * + * - mq_attr is NULL. + * - 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_MULT_NOTIFY has been turned on, it may never be turned off. */ default: return HasReturnvaluesIF::RETURN_FAILED; @@ -275,7 +289,8 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, //TODO: Check if we're in ISR. if (result != 0) { if(!ignoreFault){ - InternalErrorReporterIF* internalErrorReporter = objectManager->get( + InternalErrorReporterIF* internalErrorReporter = + objectManager->get( objects::INTERNAL_ERROR_REPORTER); if (internalErrorReporter != NULL) { internalErrorReporter->queueMessageNotSent(); @@ -283,10 +298,13 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, } switch(errno){ case EAGAIN: - //The O_NONBLOCK flag was set when opening the queue, or the MQ_NONBLOCK flag was set in its attributes, and the specified queue is full. + //The O_NONBLOCK flag was set when opening the queue, or the + //MQ_NONBLOCK flag was set in its attributes, and the + //specified queue is full. return MessageQueueIF::FULL; case EBADF: - //mq_des doesn't represent a valid message queue descriptor, or mq_des wasn't opened for writing. + //mq_des doesn't represent a valid message queue descriptor, + //or mq_des wasn't opened for writing. sif::error << "MessageQueue::sendMessage: Configuration error " << strerror(errno) << " in mq_send mqSendTo: " << sendTo << " sent from " << sentFrom << std::endl; @@ -296,13 +314,13 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, case EINVAL: /* * This value indicates one of the following: - * * msg_ptr is NULL. - * * msg_len is negative. - * * msg_prio is greater than MQ_PRIO_MAX. - * * msg_prio is less than 0. - * * 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_ptr is NULL. + * - msg_len is negative. + * - msg_prio is greater than MQ_PRIO_MAX. + * - msg_prio is less than 0. + * - MQ_PRIO_RESTRICT is set in the mq_attr of mq_des, and + * msg_prio is greater than the priority of the calling process. + */ sif::error << "MessageQueue::sendMessage: Configuration error " << strerror(errno) << " in mq_send" << std::endl; /*NO BREAK*/