Arch::Run(3pm)

πŸ“¦ version 0.5.2, in ubuntu jammy

πŸ’– Arch::Run πŸ’–

okay bestie, so this is Arch::Run, a lil gem from the User Contributed Perl Documentation collection. the whole vibe? run subprocesses and capture output ✨ no cap.


✨ SYNOPSIS ✨

use Gtk2 -init;
use Arch::Run qw(poll run_async LINES);

my $window = Gtk2::Window->new;
my $label = Gtk2::Label->new;
my $pbar = Gtk2::ProgressBar->new;
my $vbox = Gtk2::VBox->new;
$vbox->add($label); $vbox->add($pbar); $window->add($vbox);
$window->signal_connect(destroy => sub { Gtk2->main_quit; });
$window->set_default_size(200, 48); $window->show_all;
sub set_str { $label->set_text($_[0]); }

my $go = 1;  # keep progress bar pulsing
Glib::Timeout->add(100, sub { $pbar->pulse; poll(0); $go; });

run_async(
    command => [ 'du', '-hs', glob('/usr/share/*') ],
    mode    => LINES,
    datacb  => sub { chomp(my $str = $_[0]); set_str($str); },
    exitcb  => sub { $go = 0; set_str("exit code: $_[0]"); },
);

Gtk2->main;

like, look at that. a whole GUI progress bar feeding off subprocess output. iconic πŸ’…


🌸 DESCRIPTION 🌸

Arch::Run lets you run subprocesses and scoop up their output in a single threaded environment β€” which means you do not have to block your entire application while you wait. your app keeps vibing, the subprocess does its thing, everybody wins 🫢

you've got two whole strategies, bestie:

  • use poll to wait for and handle process output yourself, or
  • use handle_output and handle_exits to integrate Arch::Run with your application's main loop

pick your fighter ✨


πŸŽ€ METHODS πŸŽ€

the following functions are available: run_with_pipe, run_async, get_output_handle, handle_output, poll, wait, killall, observe, unobserve. that's the whole squad, no gatekeeping πŸ’œ


⭐ run_with_pipe ⭐

run_with_pipe $command
run_with_pipe $executable $argument ...

fork and exec a program with STDIN and STDOUT connected to pipes. so here's the tea:

  • in scalar context it returns the output handle, and STDIN gets connected to /dev/null (yeah, ghosted πŸ«₯)
  • in list context, it returns both the output handle and the input handle

and the program's standard error handle (STDERR)? that one's left completely unchanged, untouched, minding its own business ✨


⭐ run_async %args ⭐

run a command asyncronously in the background. returns the subprocess's pid. the way it just... hands you a pid and dips 😭

valid keys for %args are:

  • command => $command
  • command => [ $executable $argument ... ]

program and parameters. simple as that πŸ’…

  • mode => $accum_mode

controls how output data is accumulated and passed to the data and finish callbacks.

$accum_mode can be one of:

  • RAW β€” no accumulation. pass output to the data callback as it is received, immediately, no filter, raw as it gets πŸ”₯
  • LINES β€” accumulate output in lines. pass every line separately to the data callback. one line at a time, baby ✨
  • ALL β€” accumulate all the data. pass the complete command output as one big block to the data callback. all at once, no crumbs πŸ‘‘
  • datacb => $data_callback

a codeblock or subroutine that gets called when new output is available. it receives one parameter: the accumulated command output.

  • exitcb => $exit_callback

a codeblock or subroutine that gets called when the subprocess exits. it receives a single parameter: the command's exit code. (Or maybe not. We have to handle SIG{CHLD} then. But maybe we have to do so anyway.)

ngl bestie, even the docs are like "maybe??" about that one πŸ’€ we're keeping it exactly as it is though, periodt.

⭐ get_output_handle $pid ⭐

returns the STDOUT handle of process $pid.

⚠️ you should NEVER directly read from the returned handle. like, don't. use IO::Select or IO::Poll to wait for output, and then call handle_output to process it. that's the whole flow, iykyk πŸ’…

⭐ handle_output $pid ⭐

handle available output from process $pid.

🚨 ATTENTION: call this method only if there really is output to be read. it will block otherwise. it's giving clingy. don't do that to yourself πŸ™ˆ

⭐ poll $timeout ⭐

check running subprocesses for available output and run callbacks as appropriate. it waits at most $timeout seconds when no output is available. patient but not too patient 🌸

returns the number of processes that had output available.


⭐ wait $pid ⭐

wait for subprocess $pid to terminate, repeatedly calling poll in the meantime.

returns the process's exit status, or undef if poll has already been called after the process's exit. (ghosted again, sorry πŸ«₯)


⭐ killall [$signal] ⭐

send signal $signal (SIGINT if omitted) to all managed subprocesses, and wait until every single subprocess terminates.

no survivors, no leftovers, we wait for the whole group to actually be gone πŸ’…


⭐ observe $observer ⭐

register an observer object that wishes to be notified of running subprocesses. $observer should implement one or more of the following methods, depending on which events it wants to receive:

  • ->cmd_start $pid $executable $argument ... β€” called whenever a new subprocess has been started. receives the subprocess's PID and the executed command line. main character energy, fr fr πŸ‘‘
  • ->cmd_output_raw $pid $data β€” called whenever a subprocess has generated output. receives the subprocess's PID and a block of output data.
NOTE: $data is not preprocessed (e.g. split into lines). cmd_output_raw receives the data block as if RAW mode was used. raw data, no editing, no filter πŸ’€
  • ->cmd_exit $pid $exitcode β€” called whenever a subprocess exits. receives the subprocess's PID and exit code. goodbye bestie πŸ¦‹

⭐ unobserve $observer ⭐

remove $observer from the observer list. it's not you, it's the observer list 🌈


πŸ’œ a lil sign-off πŸ’œ

and that's the whole page, bestie! this doc is from perl v5.20.2, dated 2005-10-08 β€” vintage but still slaying ✨ go forth and run some subprocesses, you absolute icon πŸŽ€πŸ’–

πŸ“¦ where this page comes from