--- name: shmctl signature: 'shmctl ID, CMD, ARG' since: 5.0 status: documented categories: ["SysV IPC"] --- ```{index} single: shmctl; Perl built-in ``` *[SysV IPC](../perlfunc-by-category)* # shmctl Control or query a System V shared memory segment. `shmctl` is the management primitive for shared memory segments created with [`shmget`](shmget). It performs one of a small set of operations named by `CMD` — reading the segment's metadata, changing its permissions, or marking it for removal. `ID` is the segment identifier returned by [`shmget`](shmget). `ARG` is a buffer scalar that either supplies an input `shmid_ds` structure (for `IPC_SET`) or receives the returned one (for `IPC_STAT`); for `IPC_RMID` it is ignored. ## Synopsis ```perl use IPC::SysV qw(IPC_STAT IPC_SET IPC_RMID); shmctl $id, IPC_STAT, $buf or die "shmctl STAT: $!"; shmctl $id, IPC_SET, $buf or die "shmctl SET: $!"; shmctl $id, IPC_RMID, 0 or die "shmctl RMID: $!"; ``` ## What you get back Return value follows the [`ioctl`](ioctl) convention, not the usual `0`-on-success Unix pattern: - [`undef`](undef) on error, with [`$!`](../perlvar) set to the errno. - The string `"0 but true"` when the underlying call returned zero. This compares numerically equal to `0` but is boolean-true, so `shmctl(...) or die` still works. - Any other non-zero value otherwise. The practical rule: test for falsehood with `shmctl(...) or die "...: $!"` and never compare the return value to literal `0` with `==`. The `IPC_STAT` form writes a packed `shmid_ds` structure into `ARG`. Unpack it with `IPC::SysV`'s helper or with a manual [`unpack`](unpack) template; the structure layout is platform-dependent so relying on a fixed template is not portable. ## Global state it touches - [`$!`](../perlvar) is set on failure to the errno from the underlying `shmctl(2)` call. Typical values: `EINVAL` (bad `ID` or `CMD`), `EACCES` (insufficient permissions for the operation), `EPERM` (non-owner attempting `IPC_SET` or `IPC_RMID`), `EFAULT` (bad `ARG` buffer for `IPC_STAT`/`IPC_SET`). ## Examples Read a segment's metadata. `IPC::SysV` provides the `shmid_ds` unpacker; without it, the structure is an opaque byte string: ```perl use IPC::SysV qw(IPC_STAT); my $buf = ""; shmctl($id, IPC_STAT, $buf) or die "stat failed: $!"; # $buf now holds the packed shmid_ds structure ``` Change the permissions on an existing segment. The pattern is read-modify-write on the packed structure: ```perl use IPC::SysV qw(IPC_STAT IPC_SET); my $buf = ""; shmctl($id, IPC_STAT, $buf) or die $!; # ... modify the mode bits inside $buf ... shmctl($id, IPC_SET, $buf) or die $!; ``` Mark a segment for removal. The segment is destroyed once the last process detaches from it; `IPC_RMID` only flags it: ```perl use IPC::SysV qw(IPC_RMID); shmctl($id, IPC_RMID, 0) or die "rmid failed: $!"; ``` Guarding on the `"0 but true"` return. Because the zero case is a string that is boolean-true, the idiomatic check is the `or die` form, not a numeric comparison: ```perl my $rv = shmctl($id, IPC_STAT, $buf); defined $rv or die "error: $!"; # do NOT write: $rv == 0 and ... # misses the "0 but true" case ``` ## Edge cases - **Missing constants**: `IPC_STAT`, `IPC_SET`, `IPC_RMID` are not built-in. Without `use IPC::SysV` they are bareword function calls and the code either fails to compile under `use strict` or silently passes the wrong integer. Always `use IPC::SysV qw(...)`. - **Owner-only operations**: `IPC_SET` and `IPC_RMID` require the effective uid to match the segment's creator or owner, or the process to have `CAP_SYS_ADMIN`. Otherwise [`$!`](../perlvar) becomes `EPERM`. - **`IPC_RMID` semantics**: marking for removal does not detach the caller and does not invalidate existing attachments. The segment stays usable until every process has called `shmdt` on it; only then is it actually destroyed. A process that attaches after `IPC_RMID` gets `EIDRM` or `EINVAL` depending on timing. - **Structure layout is not portable**: `shmid_ds` fields and offsets vary between kernels and libc versions. Do not hand-code [`unpack`](unpack) templates for scripts that need to run on multiple platforms; use `IPC::SysV::ShmId` or a similar wrapper. - **Buffer sizing for `IPC_STAT`**: `ARG` must be a scalar of at least `sizeof(shmid_ds)` bytes on output. Perl grows it as needed; pre-sizing with `$buf = "\0" x 256` is common but not required. - **Unconfigured kernels**: on Linux built without `CONFIG_SYSVIPC`, the call fails with `ENOSYS`. Container images that drop SysV IPC exhibit the same behaviour. ## Differences from upstream Fully compatible with upstream Perl 5.42. ## See also - [`shmget`](shmget) — create or look up the segment whose `ID` `shmctl` operates on - [`shmread`](shmread) — copy bytes out of an attached segment; uses the `ID` returned by [`shmget`](shmget), not an `shmctl` result - [`shmwrite`](shmwrite) — copy bytes into an attached segment - [`msgctl`](msgctl) — same control pattern for System V message queues; same `"0 but true"` return convention - [`semctl`](semctl) — same control pattern for System V semaphore sets; richer `CMD` set but identical return-value rules - `IPC::SysV` — provides the `IPC_STAT` / `IPC_SET` / `IPC_RMID` constants and the `shmid_ds` packers