SysV IPC

shmctl#

Control or query a System V shared memory segment.

shmctl is the management primitive for shared memory segments created with 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. 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#

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 convention, not the usual 0-on-success Unix pattern:

  • undef on error, with $! 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 template; the structure layout is platform-dependent so relying on a fixed template is not portable.

Global state it touches#

  • $! 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:

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:

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:

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:

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 $! 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 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 — create or look up the segment whose ID shmctl operates on

  • shmread — copy bytes out of an attached segment; uses the ID returned by shmget, not an shmctl result

  • shmwrite — copy bytes into an attached segment

  • msgctl — same control pattern for System V message queues; same "0 but true" return convention

  • 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