clinuxsysv-ipc

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 msgctl(IPC_STAT) to obtain a msqid_ds struct with details about a given queue.

Among the details in this structure is a short value msqid_ds.msg_perm.mode, 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 msqid_ds.msg_perm.mode 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.


Solution

  • 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: