cyph cyph - 24 days ago 5
C Question

How do I find waiting readers/writers for Linux System V Msg Queues?

I'm tasked with porting some C/C++ code that uses System V queues from HP-UX to Red Hat Linux (SVr4).

Most of the calls have translated over fine, but I'm having difficulty with one specific issue as it relates to discovering waiting readers and writers on a given queue.

On HP, one can use

to obtain a msqid_ds struct with details about a given queue.

Among the details in this structure is a short value
, which uses the low 9 bits to specify the r/w permissions for user/group/others.

However, on HP, the higher 7 bits store other state information which includes the flags following two flags:

#define MSG_QWAIT 00001 /* a writer is waiting on qp->msg_cbytes */
#define MSG_FWAIT 00002 /* a writer is waiting on msgfp */

This allows one to test, for example,
(msqid.msg_perm.mode & (MSG_RWAIT | MSG_WWAIT))
to see if there are either readers or writers blocked on a queue.

As I'm porting to Linux, it's evident that this capability is not the same. The definitions for those flags are non-existent and the value of
is clearly absent of the higher bit information.

But surely there are kernel operations where the readers and writers of these queues are maintained. My hope is that some operation can be called to discover this information.


As far as I can determine, Linux has no user-facing facility by which to obtain the information you are after. Nor does POSIX define any such facility (not even for POSIX message queues). Of course you're right that the kernel has to maintain message queue state, but I see no existing mechanism by which that information can be queried from userland. Unless you fancy writing a driver for the kernel, I think your port is going to need to involve deeper changes than you had hoped.

But that's not necessarily a bad thing in the long run. Adapting your code so that it relies only on standard facilities, not vendor extensions, can be expected to make it more robust, more maintainable, and more portable. Depending on what the legacy code is trying to do, you may even end up with an altogether better design in the affected area.

Consider, for example, why the program wants the information in question, and what it will do with it. I see only one good reason: the test is performed by a process / thread as part of a pressure-release mechanism, wherein some messages get discarded if the queue gets choked with too many / too large messages. Every other reason I've considered is either ill-conceived or better served by using non-blocking sends and / or receives. If your program's reason is in that latter group, then there is a better way for it to do what it's trying to do.

Even if the purpose is the aforementioned pressure relief, do be aware that any information you obtain about the transient state of a message queue may be stale before the program even gets it. All blocked senders may have successfully proceeded before your program acts on the information it has gleaned, and new message sending attempts may have blocked. That is perhaps an understood constraint, but it should inform your pressure-relief strategy. In that case, you have at least these alternatives:

  • Instead of trying to determine whether any senders are blocked, determine whether the queue is at its capacity. You can determine from a standard struct msqid_ds both the current and the maximum number of enqueued messages. You can also determine the maximum number of bytes the queue can accommodate, though there is no standard way to determine the current number of bytes enqueued. (However, there is a Linux-specific way if you remain enamoured of vendor extensions.)

  • Check whether the queue is blocked by trying to send a message to it (using a non-blocking send). Upon success, immediately remove the message again. You can use the message type to distinguish these messages from the application's other ones. With some cooperation from the other receivers, you may be able to use the message type to ensure that no other receiver receives these probe messages.