IPC-Manager-Client-SharedMem
view release on metacpan or search on metacpan
Makefile.PL view on Meta::CPAN
}
unless (semop($sem_id, $UNLOCK)) {
$reason = "churn-probe unlock iter $iter failed: $!";
semctl($sem_id, 0, $IPC_RMID, 0);
last;
}
semctl($sem_id, 0, $IPC_RMID, 0);
}
}
# A. systemd-logind RemoveIPC probe (informational, Linux-only).
#
# When logind is configured with RemoveIPC=yes (the default on
# recent Debian/Ubuntu/RHEL) every SysV IPC object owned by a
# user is destroyed when that user's last login session ends.
# CPAN smokers that transition across session boundaries during
# a test run see their semaphores yanked by the kernel, producing
# sporadic EINVAL from semop. Linger (`loginctl enable-linger`)
# suppresses this cleanup.
#
# We can't tell from config alone whether a given run will
# actually straddle a session boundary, and on interactive
# developer machines it usually won't. So phase A is a
# diagnostic: we record the finding and, if a later gating
# phase (B or C) trips, include it in the failure reason so
# the affected user has something actionable to read.
#
# systemd-logind is Linux-only, so skip this phase on every
# other platform -- BSD / macOS / Solaris / AIX / etc. all
# support SysV IPC but do not have logind.
my $logind_hint;
if ($^O eq 'linux') {
my $remove_ipc;
my @conf_paths = ('/etc/systemd/logind.conf');
if (opendir my $dh, '/etc/systemd/logind.conf.d') {
push @conf_paths, map { "/etc/systemd/logind.conf.d/$_" }
grep { /\.conf\z/ } readdir $dh;
closedir $dh;
}
for my $path (@conf_paths) {
next unless -r $path;
open my $fh, '<', $path or next;
while (defined(my $line = <$fh>)) {
next if $line =~ /^\s*(?:#|$)/;
if ($line =~ /^\s*RemoveIPC\s*=\s*(\S+)/i) {
my $val = lc $1;
$remove_ipc = ($val eq 'yes' || $val eq 'true'
|| $val eq 'on' || $val eq '1') ? 1 : 0;
}
}
close $fh;
}
# If no config said anything but systemd-logind appears to be
# running, the compiled-in default is RemoveIPC=yes.
$remove_ipc //= -d '/run/systemd/users' ? 1 : 0;
if ($remove_ipc) {
my $uid = $<;
my $user = eval { scalar getpwuid($uid) };
my $linger = 0;
if ($user && -e "/var/lib/systemd/linger/$user") {
$linger = 1;
}
elsif (-d '/run/systemd/users') {
local $ENV{LC_ALL} = 'C';
my $out = eval { `loginctl show-user $uid --property=Linger 2>/dev/null` };
$linger = 1 if defined $out && $out =~ /Linger\s*=\s*yes/i;
}
unless ($linger) {
$logind_hint = "systemd-logind has RemoveIPC=yes and this user "
. "has no linger, so SysV IPC objects will be "
. "destroyed when the login session ends "
. "(workaround: sudo loginctl enable-linger \$USER)";
}
}
}
# B. Kernel SysV IPC limit probe (Linux-only).
#
# Hosts with absurdly tight SysV IPC limits cannot support the
# SharedMem protocol even when semop/shmop work in isolation.
# We require enough capacity for SharedMem's per-spawn pair
# (one semaphore set, one shared-memory segment, plus transient
# extras when segments are grown) and a default-sized shm
# segment (65 536 bytes).
#
# The four-integer /proc/sys/kernel/sem layout and the
# /proc/sys/kernel/shm* files are Linux-specific. *BSD,
# macOS, Solaris, AIX, and HP-UX expose comparable tunables
# via sysctl or kstat in incompatible formats and names, and
# their defaults are already sufficient for SharedMem, so we
# simply skip this phase off-Linux rather than try to parse
# every platform's flavour.
if (!$reason && $^O eq 'linux') {
my $read_first_line = sub {
my ($path) = @_;
return undef unless -r $path;
open my $fh, '<', $path or return undef;
my $line = <$fh>;
close $fh;
return undef unless defined $line;
chomp $line;
return $line;
};
# /proc/sys/kernel/sem: SEMMSL SEMMNS SEMOPM SEMMNI
if (defined(my $line = $read_first_line->('/proc/sys/kernel/sem'))) {
my ($semmsl, undef, $semopm, $semmni) = split /\s+/, $line;
if (defined $semmsl && $semmsl =~ /^\d+$/ && $semmsl < 1) {
$reason = "kernel SEMMSL=$semmsl is below 1";
}
elsif (defined $semopm && $semopm =~ /^\d+$/ && $semopm < 3) {
$reason = "kernel SEMOPM=$semopm is below required 3";
}
elsif (defined $semmni && $semmni =~ /^\d+$/ && $semmni < 8) {
$reason = "kernel SEMMNI=$semmni is too low to support concurrent SharedMem spawns";
}
( run in 0.693 second using v1.01-cache-2.11-cpan-6aa56a78535 )