3

I am maintaining some existing code

I see this fragment:

msgsnd( $mQueue, pack("l! a*", length($msg), $msg), 0) 
                                   || ... error handling ...

I would like to understand the call to pack() as the second argument to msgsnd.

I find the following documentation for msgsend

Calls the System V IPC function msgsnd to send the message MSG to the message queue ID. MSG must begin with the native long integer message type, be followed by the length of the actual message, and then finally the message itself. This kind of packing can be achieved with pack("l! a*", $type, $message) . Returns true if successful, false on error. See also SysV IPC in perlipc and the documentation for IPC::SysV and IPC::Msg .

This gives the second parameter to pack as $type, but does not explain what $type is. The code I'm trying to understand instead passes the message length.

What's going on? So far as I can tell the existing code is working reliably.

melpomene
  • 84,125
  • 8
  • 85
  • 148
djna
  • 54,992
  • 14
  • 74
  • 117
  • 2
    See also: http://ods.com.ua/win/eng/program/Perl5Unleashed/ch13.phtml. From that example (Listing 13.2 in the link) it seems like the documentation is correct and your code example is incorrect – Håkon Hægland Jul 08 '18 at 11:10
  • 1
    You've found a bug in the documentation. "*be followed by the length of the actual message,*" is nonsense and should be deleted. On the other hand, your code doesn't make much sense either because it passes the length as the message type. – melpomene Jul 08 '18 at 11:23
  • 2
    By the way, [here's the `msgsnd` code in perl](https://perl5.git.perl.org/perl.git/blob/6cb72a3d7fbefb477b95588e2fd81e33073da8b3:/doio.c#l3009). It shows that the message size is computed automatically from the string you pass in. – melpomene Jul 08 '18 at 11:26
  • Yes, I'm pretty sure I'm in a twisty maze of broken code and doubtful documentation. What values should the $type parameter take? – djna Jul 08 '18 at 11:30
  • 1
    For that you should refer to [`man 2 msgsnd`](http://man7.org/linux/man-pages/man2/msgsnd.2.html) as Leonard's answer says: "*The `mtype` field must have a strictly positive integer value. This value can be used by the receiving process for message selection (see the description of `msgrcv()` below).*" The system itself doesn't care; it's only meaningful to the receiver. – melpomene Jul 08 '18 at 11:33

3 Answers3

2

The man page for msgsnd says "The mtext field is an array (or other structure) whose size is specified by msgsz, a nonnegative integer value. Messages of zero length (i.e., no mtext field) are permitted. The mtype field must have a strictly positive integer value. This value can be used by the receiving process for message selection (see the description of msgrcv() below)."

Thus type is not used by sndmsg itself and the length that appears in the type field might or might not be used on the receiving side.

Leonard
  • 13,269
  • 9
  • 45
  • 72
2

The application in question decided to use the type field to store the length of the message.

(This is rather odd, since the size of the message is already available to the reader.)


When the receiver request a message from the system, they may constrain the request to specific message types.

  • If msgtyp is 0, then the first message in the queue is read.

  • If msgtyp is greater than 0, then the first message in the queue of type msgtyp is read, unless MSG_EXCEPT was specified in msgflg, in which case the first message in the queue of type not equal to msgtyp will be read.

  • If msgtyp is less than 0, then the first message in the queue with the lowest type less than or equal to the absolute value of msgtyp will be read.

If the receiver specifies 0 for msgtyp, then the message type provided by the sender isn't used by the system, and can therefore be used to carry other information.

Community
  • 1
  • 1
ikegami
  • 367,544
  • 15
  • 269
  • 518
0

it creates a binary representation of the msg: len msg. Check it by:

perl -e '$a= "abcde"; print(pack("l! a*", length($a), $a))' | od -c

Gives:

 0000000 005  \0  \0  \0  \0  \0  \0  \0   a   b   c   d   e

0000015

hootnot
  • 1,005
  • 8
  • 13
  • Thanks, that makes perfect sense, other than it not seeming to be consistent with the documentation. Why does the doc say "pack("l! a*", $type, $message)"? I'm seeing length($msg) rather than a $type. – djna Jul 08 '18 at 11:07
  • Pls. checkout the documentation for *pack*. It will clear some things. The way *pack* is used depends on your application. See this doc: https://perldoc.perl.org/perlpacktut.html with a lot of examples – hootnot Jul 08 '18 at 11:11
  • Thanks, it's the apparent inconsistency between the perl doc I include above and the examples I see in the tut you reference. – djna Jul 08 '18 at 11:28