Developer-Dashboard

 view release on metacpan or  search on metacpan

lib/Developer/Dashboard/ActionRunner.pm  view on Meta::CPAN

# Output: normalized exit status integer.
sub _wait_status_exit_code {
    my ( $self, $raw_status ) = @_;
    my $status = $raw_status >> 8;
    $status = 128 + ( $raw_status & 127 ) if !$status && ( $raw_status & 127 );
    return $status;
}

# _background_child_exit_status($command_pid)
# Polls one detached background command child and returns the supervisor exit
# code when that child has already exited.
# Input: direct child process id integer.
# Output: normalized exit status integer when reaped, otherwise undef.
sub _background_child_exit_status {
    my ( $self, $command_pid ) = @_;
    my $reaped = waitpid( $command_pid, WNOHANG );
    return if $reaped != $command_pid;
    return $self->_wait_status_exit_code($?);
}

# _reap_child_process($pid)
# Reaps one direct background action child when it has already exited so
# callers do not observe wrapper zombies during lifecycle checks.
# Input: process id integer.
# Output: boolean true when waitpid reaped the child.
sub _reap_child_process {
    my ( $self, $pid ) = @_;
    return 0 if !defined $pid || $pid !~ /^\d+$/ || $pid < 1;
    my $waited = waitpid( $pid, WNOHANG );
    return $waited == $pid ? 1 : 0;
}

# _read_process_state($pid)
# Reads the current process state so zombie background action wrappers can be
# treated as stopped even when signal 0 still succeeds.
# Input: process id integer.
# Output: one-letter process state string or undef.
sub _read_process_state {
    my ( $self, $pid ) = @_;
    my $proc = "/proc/$pid/stat";
    if ( -r $proc ) {
        open my $fh, '<', $proc or return;    # uncoverable branch true
        local $/;
        my $stat = scalar <$fh>;
        if ( defined $stat ) {    # uncoverable branch false
            return $1 if $stat =~ /^\d+\s+\(.*\)\s+(\S)/s;    # uncoverable branch false
        }
    }

    my ( $stdout, undef, $exit_code ) = capture {
        system 'ps', '-o', 'stat=', '-p', $pid;
        return $? >> 8;
    };
    return if $exit_code != 0;
    $stdout =~ s/^\s+|\s+$//g if defined $stdout;
    return if !defined $stdout || $stdout eq '';
    return substr( $stdout, 0, 1 );
}

# _pid_is_running($pid)
# Determines whether one background action pid is still alive after
# opportunistic reaping and zombie-state checks.
# Input: process id integer.
# Output: boolean true when the process still appears to be running.
sub _pid_is_running {
    my ( $self, $pid ) = @_;
    return 0 if !defined $pid || $pid !~ /^\d+$/ || $pid < 1;
    return 0 if $self->_reap_child_process($pid);
    return 0 if ( $self->_read_process_state($pid) || '' ) eq 'Z';
    return kill( 0, $pid ) ? 1 : 0;
}

# _run_builtin_action(%args)
# Executes one of the built-in safe dashboard actions.
# Input: action hash, page document, and optional params hash.
# Output: structured result hash reference.
sub _run_builtin_action {
    my ( $self, %args ) = @_;
    my $action = $args{action};
    my $page   = $args{page};
    my $id     = $action->{builtin} || $action->{id} || '';

    if ( $id eq 'page.source' ) {
        return {
            kind         => 'builtin',
            content_type => 'text/plain; charset=utf-8',
            body         => $page->canonical_instruction,
        };
    }

    if ( $id eq 'page.state' ) {
        return {
            kind         => 'builtin',
            content_type => 'application/json; charset=utf-8',
            body         => json_encode( $page->as_hash->{state} || {} ),
        };
    }

    if ( $id eq 'paths.list' ) {
        return {
            kind         => 'builtin',
            content_type => 'application/json; charset=utf-8',
            body         => json_encode(
                {
                    home       => $self->{paths}->home,
                    runtime    => $self->{paths}->runtime_root,
                    dashboards => $self->{paths}->dashboards_root,
                    config     => $self->{paths}->config_root,
                    cli        => $self->{paths}->cli_root,
                }
            ),
        };
    }

    die "Unsupported builtin action '$id'\n";
}

# _is_action_trusted(%args)
# Determines whether a page action may execute for the given source.
# Input: page document, action hash, and source string.
# Output: boolean trust flag.



( run in 1.120 second using v1.01-cache-2.11-cpan-14f38c9f855 )