Test2::Harness::Stall::Capture(3)

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/>