Kernel SysV IPC defaults.

Chris Smith chris at nfluid.co.uk
Thu Mar 4 10:56:06 PST 2004


On Thursday 04 Mar 2004 13:47, Bruce M Simpson wrote:
> On Wed, Mar 03, 2004 at 05:42:43PM +0000, Chris Smith wrote:
> > Consider  MSGMAX (max bytes in a message) and MSGMNB (max bytes in a
> > queue) The defaults are MSGMAX > MSGMNB, which is clearly backwards.
>
> I see this. How about the attached patch?

Thanks for the reply, I did some research in the interim and perhaps you could 
verify my findings/assumptions below if you've got a spare moment?  This goes 
into some detail.  Sorry :o(

I don't think you can have more than (MSGSSZ*MSGSEG) bytes queued in total by 
the kernel.

I've just been trawling through sysv_msg.c and either I've lost myself, or it 
_might_ be broken.

You see, traditionally the total space available for all messages (the pool) 
is given by (MSGSSZ * MSSEG).  Looking at the code the pool is allocated with 
this value... however the msgmax parameter is explicitly being set to this 
figure as well:

msginfo.msgmax = msginfo.msgseg * msginfo.msgssz;
msgpool = malloc(msginfo.msgmax, M_MSG, M_WAITOK);

Normally you would expect to see MSGMNB  < (MSGSSZ * MSSEG), but given the 
code above, this equates to msgmnb < msgmax.... which if you're still with me 
says "max bytes in queue should be less than max bytes in a single message".
And how can that be?

The way I 'm reading it is that queued messages consume message segments from 
msgpool.  Once this pool is exhausted, then no more messages may be queued 
_system wide_.  I could be misreading the code here - put me right if I am:o)

On closer examination, msgmax is never considered in the code, only that there 
are sufficient segments available with which to store a message (in the queue 
by indirectly checking MSGMNB).  There are no checks that a single message 
does not exceed MSGMAX, and that is supposed to be trapped!

This all implies that a single message can consume all msg segments allocated 
to a single queue (the code seems to confirm this also).

The defaults may thus be incorrect as they mirror the code.... besides, it 
looks like whatever you try to default MSGMAX to be it _always_ gets set to 
(MSGSSZ*MSGSEG) by the code above.

I would suggest that msginfo.maxmsg should not be overwritten by (msgsssz * 
msseg), and that msgpool be malloced from the sum of (msgsssz * msseg) 
directly.  When queueing a message, a check should be that the msgsize does 
not exceed msgmax.  I think this will make the sysv_msg behave as documented.


Would you like me to generate a test suite for this problem and then perhaps a 
patch for sysv_msg.c should my findings above turn out to be correct?


Incidentally, the same problem appears (with no surprise) with openBSD and 
netBSD.

I'm familiar with Solaris settings, and I've just checked a couple of other 
OS's and they concur with Solaris in that:
MSGMAX = 2^n, for 6 < n < 16 and MSGMAX < MSGMNB
and MSGMNB < (MSGSSZ*MSGSEG)
Total pool size = (MSGSSZ*MSGSEG)

> I can understand people still using the SYSV IPC mechanisms for the sake of
> compatibility, but I suspect the purists are loathe to touch it.

SYSV IPC (message queues) are incredibly useful if you want to pull messages 
out of the queue with a variable priority, regardless of queue FIFO order.  
I'm working hard on an alternative so I can drop sysV requirement, but it's 
fraught with problems :o(

Regards
Chris

>
> BMS


More information about the freebsd-hackers mailing list