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
#define MSG_QWAIT 00001 /* a writer is waiting on qp->msg_cbytes */
#define MSG_FWAIT 00002 /* a writer is waiting on msgfp */
(msqid.msg_perm.mode & (MSG_RWAIT | MSG_WWAIT))
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.