--- name: semctl signature: 'semctl ID, SEMNUM, CMD, ARG' since: 5.0 status: documented categories: ["SysV IPC"] --- ```{index} single: semctl; Perl built-in ``` *[SysV IPC](../perlfunc-by-category)* # semctl Perform a control operation on a System V semaphore set. `semctl` is the Perl-level binding for the `semctl(2)` system call. It reads or modifies the state of the semaphore set identified by `ID` — getting or setting a single semaphore's value, fetching or installing the full value vector, reading the associated `semid_ds` metadata, or removing the set entirely. `CMD` selects the operation; `SEMNUM` selects which semaphore within the set (ignored for set-wide commands like `IPC_STAT`, `IPC_RMID`, `GETALL`, `SETALL`); `ARG` is the command's input or output buffer. `semctl` is a thin wrapper — the semantics, the command constants, and the shape of `ARG` all come straight from the C-level call. You will almost always want: ```perl use IPC::SysV; ``` first, to pull in the `IPC_STAT`, `IPC_RMID`, `GETVAL`, `SETVAL`, `GETALL`, `SETALL`, `GETPID`, `GETNCNT`, `GETZCNT` constants. ## Synopsis ```perl semctl $id, $semnum, $cmd, $arg semctl $id, 0, IPC_RMID, 0 # destroy set semctl $id, $n, SETVAL, $value # set one semctl $id, 0, SETALL, $packed # set all ``` ## What you get back Return follows the same convention as [`ioctl`](ioctl): - [`undef`](undef) on error (with [`$!`](../perlvar) set). - The string `"0 but true"` when the underlying call returned `0` — this string is false numerically (so it prints `0` in numeric context) but true in boolean context, letting you distinguish success-with-zero from failure in one test. - The actual integer return value otherwise. The idiomatic test is therefore: ```perl my $rc = semctl($id, $n, GETVAL, 0); defined $rc or die "semctl: $!"; ``` Check `defined`, not truth — a legitimately zero semaphore value would fail a plain `if ($rc)`. For `CMD` values that read data into `ARG` (`IPC_STAT`, `GETALL`), `ARG` must be a **modifiable lvalue** (a plain variable, not a literal or expression); on success the buffer is overwritten in place with the returned bytes and you unpack it yourself. ## Global state it touches Sets [`$!`](../perlvar) on failure. No other interpreter globals involved. ## Examples Read a single semaphore's current value: ```perl use IPC::SysV qw(GETVAL); my $value = semctl($id, $semnum, GETVAL, 0); defined $value or die "GETVAL: $!"; ``` Set a single semaphore: ```perl use IPC::SysV qw(SETVAL); semctl($id, $semnum, SETVAL, 1) or die "SETVAL: $!"; ``` Read all semaphore values at once. The buffer has to be pre-allocated to the right size — `nsems` native shorts — before the call. `pack` with an unused count is the usual way: ```perl use IPC::SysV qw(GETALL); my $nsems = 4; my $buf = pack("s!*", (0) x $nsems); # allocate room semctl($id, 0, GETALL, $buf) or die $!; my @vals = unpack("s!*", $buf); ``` Install a full set of values: ```perl use IPC::SysV qw(SETALL); my $buf = pack("s!*", 1, 0, 0, 1); semctl($id, 0, SETALL, $buf) or die "SETALL: $!"; ``` Fetch the `semid_ds` structure for the set. `ARG` is written in place with the packed struct; its layout is platform-specific, so unpack with the help of `IPC::Semaphore` rather than by hand unless you have to: ```perl use IPC::SysV qw(IPC_STAT); my $ds = ""; semctl($id, 0, IPC_STAT, $ds) or die "IPC_STAT: $!"; ``` Destroy the semaphore set. `SEMNUM` and `ARG` are unused; pass `0`: ```perl use IPC::SysV qw(IPC_RMID); semctl($id, 0, IPC_RMID, 0) or die "IPC_RMID: $!"; ``` ## Edge cases - **`ARG` must be a real variable for read commands.** `GETALL` and `IPC_STAT` write into `ARG`; passing a literal (`semctl($id, 0, GETALL, "")`) or a read-only expression is a runtime error. The variable's existing contents are overwritten, not appended to. - **`ARG` must be pre-sized.** The kernel writes exactly `nsems * sizeof(short)` bytes for `GETALL`, or `sizeof(struct semid_ds)` for `IPC_STAT`. Passing a shorter buffer is undefined behaviour in the underlying C call; `pack("s!*", (0) x $nsems)` is the standard idiom for `GETALL`. - **Native `short`, not portable `short`.** Semaphore values are C `short` (signed, typically 16-bit). Use `s!` in [`pack`](pack) / [`unpack`](unpack) — the `!` picks the platform-native type. Plain `s` forces little-endian 16-bit and will produce wrong results on big-endian or LP64-short systems. - **`"0 but true"` returns.** `GETVAL` on a semaphore whose value is `0`, `GETPID`/`GETNCNT`/`GETZCNT` returning zero, and other zero-valued successes all return the literal string `"0 but true"`. Arithmetic contexts see `0`; boolean contexts see true. Use `defined` to check for failure. - **`SEMNUM` is ignored for set-wide commands.** `IPC_STAT`, `IPC_RMID`, `SETALL`, `GETALL` act on the whole set. Pass `0` by convention; passing any other value is harmless but obscures intent. - **After `IPC_RMID` the id is invalid.** Every subsequent `semctl` or [`semop`](semop) on `$id` fails with `EINVAL` / `EIDRM`. Do not cache the id past removal. - **The set is kernel-global and persists across process exits.** A set created by a crashed script remains until someone calls `IPC_RMID` (or the system reboots). Use `ipcs -s` / `ipcrm -s` from the shell to inspect or clean up leaked sets. - **Permissions come from `semget`.** The `IPC_CREAT | mode` passed at creation time controls who may issue which `semctl` commands. `EACCES` from `semctl` means the mode bits disallow the requested operation for the current effective uid. ## Differences from upstream Fully compatible with upstream Perl 5.42. ## See also - [`semget`](semget) — create or look up the semaphore set whose id you then pass to `semctl` - [`semop`](semop) — the actual wait / signal operations; `semctl` is for control and inspection, `semop` does the work - [`msgctl`](msgctl) — the analogous control call for System V message queues; same return-value convention - [`shmctl`](shmctl) — the analogous control call for System V shared memory; same return-value convention - [`pack`](pack) — how to build the `ARG` buffer with `s!` for semaphore values and the `semid_ds` struct - `IPC::Semaphore` — object wrapper that hides `semctl` behind named methods; reach for it when a script does more than one or two calls