NAME

Test2::Harness::Stall::Capture - Collect evidence about a stalled run from outside the stuck processes.

DESCRIPTION

Gathers everything obtainable without the stuck process's cooperation, then asks each harness process for its Perl call stack.

The order matters. A process in an uninterruptible syscall, or in XS that retries EINTR, never runs a signal handler, so external evidence must not depend on a reply. A missing stack is itself a finding: no stack plus an uninterruptible state says the process could not run Perl at all.

Each report samples several times a few seconds apart. Frames and syscalls that move between samples mean a loop making no progress; frames that do not mean the process is stuck on one operation. That distinction is the first question any analysis asks.

strace is attempted and usually denied: Yama checks the tracer against the target's ancestry, and strace is a freshly exec'd process, so it is never an ancestor of the scheduler. It is kept for hosts that permit it, and /proc/PID/wchan and /proc/PID/syscall answer the same question when it does not. Every shell-out is bounded, because this blocks the caller.

Everything here is Linux-specific and degrades to the state dump and the stack traces elsewhere.

SYNOPSIS

use Test2::Harness::Stall::Capture;

my $capture = Test2::Harness::Stall::Capture->new(
    workdir  => $workdir,
    root_pid => $$,
);

my $bundle = $capture->collect(\%info);

ATTRIBUTES

$string = $capture->workdir()

The run's working directory.

$string = $capture->stall_dir()

Where the signalled processes leave their stack traces. Defaults to stall inside the working directory.

$int = $capture->root_pid()

Root of the process tree to describe. Defaults to the current process.

PUBLIC METHODS

$hashref = $capture->collect(\%info)

Runs the whole capture and returns the bundle. %info carries what the detector observed, and the pids to signal as harness_pids.

$bool = $capture->have_proc()

True on a platform where /proc can be read.

$hashref = $capture->proc_snapshot($pid)

State, wait channel, syscall, command line, caught signals and open files for one process.

$string = $capture->read_proc($pid, $what)

One /proc/PID file, or nothing. Some of these are gated on ptrace permission, and when it is refused the open succeeds and the read comes back empty -- so the read is what must be checked.

$hashref = $capture->list_fds($pid)

File descriptor number to what it points at.

$arrayref = $capture->process_tree($pid)

Every descendant of a pid, including it.

$arrayref = $capture->all_pids()

Every pid on the system, or nothing where there is no /proc.

$bool = $capture->kill_pid($pid)

Sends SIGUSR1 to one pid.

$arrayref = $capture->signal_pids(\@pids, \%procs)

Sends SIGUSR1 to each pid that this round's snapshot shows alive and catching that signal, and returns those actually signalled. A process that did not install the handler is never signalled, because the default action would terminate it. Where there is no /proc that check cannot be made and every positive pid in the list is signalled. Never signals a process group.

$bool = $capture->catches_usr1(\%proc)

Whether a snapshot shows the process catching SIGUSR1, read from SigCgt.

$int = $capture->usr1_number()

The local signal number for SIGUSR1.

$hashref = $capture->system_snapshot()

Load, memory and the lock table.

$string = $capture->workdir_filesystem()

Filesystem type and free space for the working directory.

$string = $capture->strace($pid)

Best-effort strace output, or its refusal.

$hashref = $capture->read_traces()

Stack traces written since the last call, keyed by filename. Consumes them.

SOURCE

The source code repository for Test2-Harness can be found at https://github.com/Test-More/Test2-Harness/.

MAINTAINERS

Chad Granum <exodist7@gmail.com>

AUTHORS

Chad Granum <exodist7@gmail.com>

COPYRIGHT

Copyright Chad Granum <exodist7@gmail.com>.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

See https://dev.perl.org/licenses/