IPC-Manager

 view release on metacpan or  search on metacpan

AI_DOCS/2026-05-13-fs-peer-cleanup-on-sigkill.md  view on Meta::CPAN

When this fix is in IPC::Manager and a release lands, the harness side
will flip `Test2::Harness2::PreloadService::restartable` to return 1
(currently `0`) so a preload that exits unexpectedly is restarted
automatically. Without this fix, the next start crashes on
`<peer-id> UNIX Socket or marker file already exists`.

## Symptom

A client that registered through any `Base::FS` driver (`ConnectionUnix`,
`AtomicPipe`, `MessageFiles`) and then died ungracefully (SIGKILL,
segfault, OOM, parent-exit cascade — anything that bypasses Perl's
`DESTROY`) leaves its on-disk artifacts behind:

- `$ROUTE/{on_disk_name}` — socket file (ConnectionUnix) or directory
  (AtomicPipe) for the peer
- `$ROUTE/{on_disk_name}.pid` — pidfile carrying the dead pid
- `$ROUTE/{on_disk_name}.name` — sidecar (for hashed names)
- `$ROUTE/{on_disk_name}.resume` — resume buffer (if any)
- `$ROUTE/{on_disk_name}.stats` — stats sidecar

The next process that tries to register with the same peer name croaks:

t/unit/sigkill_cleanup_ConnectionUnix.t  view on Meta::CPAN

use IPC::Manager::Serializer::JSON;

my $S = 'IPC::Manager::Serializer::JSON';
my $C = 'IPC::Manager::Client::ConnectionUnix';

# Fork a child, run $code->($route) in it, then SIGKILL the child while
# whatever refs the callback returned are still in scope -- so DESTROY
# does not fire on them before SIGKILL delivers (DESTROY would call
# disconnect, which runs pre_disconnect_hook and is exactly what we want
# to skip to simulate ungraceful death).  POSIX::_exit avoids the END
# / DESTROY cascade in case SIGKILL is somehow deferred.
sub kill_child_after {
    my ($route, $code) = @_;
    my $pid = fork;
    die "fork failed: $!" unless defined $pid;
    if (!$pid) {
        my @keep = $code->($route);
        kill 'KILL', $$;
        require POSIX;
        POSIX::_exit(0);
    }



( run in 1.203 second using v1.01-cache-2.11-cpan-9581c071862 )