--- name: msgrcv signature: 'msgrcv ID, VAR, SIZE, TYPE, FLAGS' since: 5.0 status: documented categories: ["SysV IPC"] --- ```{index} single: msgrcv; Perl built-in ``` *[SysV IPC](../perlfunc-by-category)* # msgrcv Receive a message from a System V IPC message queue. `msgrcv` is the Perl binding for the `msgrcv(2)` syscall. It pulls one message off the queue identified by `ID`, stores the message type and payload into `VAR`, and returns a truthy value on success or false on error. `SIZE` is the maximum number of payload bytes the caller is willing to accept; `TYPE` selects which message to receive; `FLAGS` is the bitmask passed to the kernel (`IPC_NOWAIT`, `MSG_NOERROR`, etc.). The returned buffer is **not** just the message body — the first `sizeof(long)` bytes are the message type the sender passed to [`msgsnd`](msgsnd), followed by the payload. Use [`unpack`](unpack) with the `l! a*` template to split them apart. ## Synopsis ```perl use IPC::SysV qw(IPC_NOWAIT MSG_NOERROR); msgrcv $qid, my $buf, 1024, 0, 0 or die "msgrcv: $!"; msgrcv $qid, my $buf, 1024, 0, IPC_NOWAIT; # non-blocking my ($type, $payload) = unpack "l! a*", $buf; ``` ## What you get back True on success, false on error with [`$!`](../perlvar) set. On success, `VAR` is overwritten with the received frame: a native `long` (the message type) immediately followed by up to `SIZE` bytes of payload. The variable is marked tainted under `-T`. `VAR` is grown or shrunk to fit the actual frame length — you do not need to pre-size it. The content before the call is discarded. To get the type and payload as separate values: ```perl my ($type, $msg) = unpack "l! a*", $buf; ``` ## Arguments - `ID` — the queue id previously returned by [`msgget`](msgget). - `VAR` — a lvalue scalar that receives the raw frame. Its previous value is discarded on success. - `SIZE` — the maximum payload size in bytes. If the next matching message is larger than this, `msgrcv` fails with `E2BIG` and the message stays on the queue — **unless** `MSG_NOERROR` is set in `FLAGS`, in which case the message is truncated silently and the extra bytes are lost. - `TYPE` — selects which message to receive: - `0` — the first message on the queue, whatever its type. - positive `N` — the first message whose type is exactly `N`. - negative `-N` — the first message of the lowest type that is `<= abs(N)`, useful for priority queues. - `FLAGS` — bitmask of `IPC_NOWAIT` (return `ENOMSG` immediately instead of blocking when no matching message is available), `MSG_NOERROR` (truncate instead of failing on oversized messages), and the Linux-specific `MSG_EXCEPT` (with a positive `TYPE`, receive the first message whose type is *not* `TYPE`). The constants live in `IPC::SysV`; the bare names do not become visible until you import them. ## Global state it touches - [`$!`](../perlvar) — set on error to the underlying `errno` (`ENOMSG`, `E2BIG`, `EIDRM`, `EINVAL`, `EACCES`, `EFAULT`, `EINTR`). - Taint mode — the received `VAR` is marked tainted, since its contents came from another process. ## Examples Blocking receive of any message, then split type and payload: ```perl use IPC::SysV qw(IPC_CREAT S_IRUSR S_IWUSR); my $qid = msgget(IPC_PRIVATE, S_IRUSR | S_IWUSR) // die "msgget: $!"; msgrcv $qid, my $buf, 4096, 0, 0 or die "msgrcv: $!"; my ($type, $payload) = unpack "l! a*", $buf; print "got type=$type payload=$payload\n"; ``` Receive only messages of type `42`: ```perl msgrcv $qid, my $buf, 4096, 42, 0 or die "msgrcv: $!"; ``` Non-blocking poll — return immediately if the queue is empty: ```perl use IPC::SysV qw(IPC_NOWAIT); use Errno qw(ENOMSG); if (msgrcv $qid, my $buf, 4096, 0, IPC_NOWAIT) { my ($type, $msg) = unpack "l! a*", $buf; handle($type, $msg); } elsif ($! == ENOMSG) { # queue was empty; try again later } else { die "msgrcv: $!"; } ``` Truncate oversized messages rather than failing: ```perl use IPC::SysV qw(MSG_NOERROR); msgrcv $qid, my $buf, 64, 0, MSG_NOERROR or die "msgrcv: $!"; # payload is at most 64 bytes, excess discarded without error ``` Priority-style receive — take the lowest-numbered message whose type is `<= 3`: ```perl msgrcv $qid, my $buf, 4096, -3, 0 or die "msgrcv: $!"; ``` ## Edge cases - **`VAR` must be an lvalue**. Passing a constant or a read-only scalar (for instance an element of `@_` that was passed by reference to a literal) raises `Modification of a read-only value attempted`. - **Frame layout is native `long`, not four bytes**. On 64-bit Linux the type occupies 8 bytes; on 32-bit systems it occupies 4. The `l!` in `unpack "l! a*"` — the `!` — is mandatory; a plain `l` assumes 4 bytes and will corrupt payloads on 64-bit hosts. - **`SIZE` excludes the type header for `MSG_NOERROR` purposes**. The kernel compares `SIZE` against the payload length, not the frame length. Size the buffer for the largest payload you expect; the type header is written beyond it. - **Signal interruption**. A blocking `msgrcv` returns false with `$! == EINTR` when a signal arrives before a message is available. Retry the call unless the signal is meant to abort the receive loop. - **Queue removed while blocked**. If another process calls [`msgctl`](msgctl) with `IPC_RMID` while this process is asleep in `msgrcv`, the call returns false with `$! == EIDRM`. - **Permissions**. Receiving requires read permission on the queue. `EACCES` means the queue exists but the current uid/gid doesn't match the queue's mode bits. - **`TYPE = 0` sees FIFO order**. There is no "any" priority short of explicit negative `TYPE` — messages of all types are pulled in send order. - **Kernel support**. Linux kernels built without `CONFIG_SYSVIPC`, and container runtimes that don't expose the IPC namespace, fail every `msgrcv` with `ENOSYS`. Check during startup if your deployment target is uncertain. ## Differences from upstream Fully compatible with upstream Perl 5.42. ## See also - [`msgsnd`](msgsnd) — the counterpart that puts messages on the queue; its `pack "l! a*"` template is the inverse of what you `unpack` here - [`msgget`](msgget) — obtain the queue id `ID` you pass in - [`msgctl`](msgctl) — inspect or delete the queue, including the `IPC_RMID` that causes a blocked `msgrcv` to return `EIDRM` - [`unpack`](unpack) — split the returned frame into type and payload with `l! a*` - `IPC::SysV` — source of the `IPC_NOWAIT`, `MSG_NOERROR`, and related flag constants - `IPC::Msg` — object-oriented wrapper that hides the pack/unpack dance behind a `rcv` method