MQ_RECEIVE(2)

πŸ’Œ MQ_RECEIVE(2) β€” bestie edition πŸ’Œ

okay so bestie, you're in section 2 of the manual (system calls, the real ones) and today we're talking about mq_receive and mq_timedreceive β€” the two functions that let you receive a message from a message queue (REALTIME, periodt ✨).


πŸ“š LIBRARY πŸ“š

POSIX Real-time Library β€” link it like librt, -lrt or it's giving undefined reference πŸ’€


✨ SYNOPSIS ✨

#include <mqueue.h>

ssize_t
mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len,
    unsigned *msg_prio);

ssize_t
mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len,
    unsigned *msg_prio, const struct timespec *abs_timeout);

🫢 DESCRIPTION 🫢

So mq_receive() grabs the oldest of the highest priority message(s) from the message queue that mqdes points at. That's the whole vibe: highest priority first, and among ties, the one that's been waiting longest. Main character energy, honestly πŸ‘‘

Here's the thing though β€” if the size of the buffer in bytes, that's msg_len, is less than the mq_msgsize attribute of the message queue? It's over. The call fails and returns an error, no message for you πŸ™ˆ. Otherwise the selected message gets yanked off the queue and copied into the buffer that msg_ptr points to. Slay.

Now if msg_prio is not NULL, the priority of the selected message gets stored in the location msg_prio references. Cute, right? πŸ’…

And if the queue is empty and O_NONBLOCK is not set in the message queue description associated with mqdes, then mq_receive() will just... block. Like, sit there. Until a message gets enqueued on the queue, or until mq_receive() gets interrupted by a signal 😭.

If more than one thread is waiting to receive a message when a message arrives at an empty queue, and the Priority Scheduling option is supported, then the thread of highest priority that has been waiting the longest gets picked to receive the message. Otherwise? It is unspecified which waiting thread receives the message. No cap, nobody knows, it's a mystery 🌸.

And if the queue is empty and O_NONBLOCK is set in the message queue description associated with mqdes, then nothing gets removed from the queue and mq_receive() returns an error. Bye πŸ‘‹


⏰ the timed one ⏰

mq_timedreceive() receives the oldest of the highest priority messages from the message queue specified by mqdes, exactly as described for mq_receive() above. Same girl, different dress.

But β€” if O_NONBLOCK was not specified when the message queue was opened via the mq_open() system call, and there's no message on the queue to satisfy the receive, then the wait for such a message gets terminated when the specified timeout expires. ⏳

If O_NONBLOCK is set, then this system call is equivalent to mq_receive(). Same thing, periodt.


πŸ•°οΈ when the timeout expires πŸ•°οΈ

The timeout expires when the absolute time specified by abs_timeout passes, as measured by the clock on which timeouts are based β€” that is, when the value of that clock equals or exceeds abs_timeout β€” or if the absolute time specified by abs_timeout has already been passed at the time of the call. Like, you were already late when you called. Rude but valid πŸ“.

The timeout is based on the CLOCK_REALTIME clock. Remember that bestie, it's not the monotonic one πŸ’–

πŸŽ€ RETURN VALUES πŸŽ€

Upon successful completion, mq_receive() and mq_timedreceive() return the length of the selected message in bytes and the message is removed from the queue. Ate.

Otherwise: no message is removed from the queue, the system call returns a value of -1, and the global variable errno is set to indicate the error. Tragic but informative πŸ’€


🚨 ERRORS 🚨

The mq_receive() and mq_timedreceive() system calls will fail if:

  • [EAGAIN] β€” the O_NONBLOCK flag is set in the message queue description associated with mqdes, and the specified message queue is empty. Nothing to grab, no waiting allowed.
  • [EBADF] β€” the mqdes argument is not a valid message queue descriptor open for reading. Bestie that's not a real queue, or it's not opened for reading 😭
  • [EMSGSIZE] β€” the specified message buffer size, msg_len, is less than the message size attribute of the message queue. Your buffer is too smol, the message is not.
  • [EINTR] β€” the mq_receive() or mq_timedreceive() operation was interrupted by a signal. A signal really said "not now" πŸ™ˆ
  • [EINVAL] β€” the process or thread would have blocked, and the abs_timeout parameter specified a nanoseconds field value less than zero or greater than or equal to 1000 million. That's not a valid nanoseconds field, that's a cry for help.
  • [ETIMEDOUT] β€” the O_NONBLOCK flag was not set when the message queue was opened, but no message arrived on the queue before the specified timeout expired. You waited, and nothing came. It's giving ghosted πŸ‘»

πŸ‘€ SEE ALSO πŸ‘€

mq_open(2), mq_send(2), mq_timedsend(2)


πŸ“ STANDARDS πŸ“

The mq_receive() and mq_timedreceive() system calls conform to IEEE Std 1003.1-2004 (β€œPOSIX.1”). Certified. Iconic. πŸ“œ


πŸ¦‹ HISTORY πŸ¦‹

Support for POSIX message queues first appeared in FreeBSD 7.0. A historical moment fr fr.


Portions of this text are reprinted and reproduced in electronic form from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology -- Portable Operating System Interface (POSIX), The Open Group Base Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of Electrical and Electronics Engineers, Inc and The Open Group. In the event of any discrepancy between this version and the original IEEE and The Open Group Standard, the original IEEE and The Open Group Standard is the referee document. The original Standard can be obtained online at http://www.opengroup.org/unix/online.html.


okay that's the whole page bestie, you're officially fluent in mq_receive πŸ’– this one's from the Debian crew, dated November 29, 2005 β€” old but iconic, and yes it's still serving. go get those messages 🫢✨

πŸ“¦ where this page comes from