NAME

Linux::Event::Fork - Asynchronous child process management for Linux::Event

SYNOPSIS

use v5.36;
use Linux::Event;
use Linux::Event::Fork;

my $loop = Linux::Event->new;

# Configure at runtime (Option A)
my $fork = $loop->fork_helper(
  max_children => 4,
);

$loop->fork(
  cmd => [ $^X, '-we', 'print "hello\n"; exit 0' ],

  on_stdout => sub ($child, $chunk) {
    # Runs in the parent, inside the event loop.
    print $chunk;
  },

  on_exit => sub ($child, $exit) {
    # Runs in the parent when the child has fully exited.
    $loop->stop;
  },
);

$loop->run;

DESCRIPTION

Linux::Event::Fork provides event-loop-integrated child process management with:

  • Nonblocking stdout/stderr capture

  • Streaming stdin (parent -> child)

  • Timeout support with optional TERM escalation

  • Bounded parallelism (max_children)

  • Queueing and drain semantics

  • Cancel queued requests

  • Introspection (running, queued)

EXECUTION MODEL

All on_* callbacks run in the parent process, inside the Linux::Event event loop thread.

Only the child = sub { ... }> callback runs in the child process.

Execution boundary:

parent process
----------------------------
    $loop->fork(...)
        |
        | fork()
        v
child process
----------------------------
    child => sub { ... }
    or
    exec(@cmd)

Callbacks:

child stdout/stderr  --->  parent (on_stdout / on_stderr)
child exit           --->  parent (on_exit)
timeout event        --->  parent (on_timeout)

STREAM DIRECTIONS

Stream direction is explicit:

stdin   : parent ---> child
stdout  : child  ---> parent
stderr  : child  ---> parent

There is no "on_stdin" for receiving data. Use on_stdout or on_stderr to receive child output.

LIFECYCLE

Normal execution:

fork()
  |
  +--> running
          |
          +--> stdout/stderr events
          |
          +--> exit
                  |
                  +--> on_exit callback

Queueing:

running < max_children
    |
    +--> start immediately

running >= max_children
    |
    +--> return Request object
    +--> queued
    +--> auto-start when capacity frees

Drain fires when:

running == 0
AND
queue is empty

TIMEOUT AND ESCALATION

If timeout is set:

timeout expires
    |
    +--> on_timeout (parent)
    +--> SIGTERM sent to child

If timeout_kill is also set:

timeout expires
    |
    +--> SIGTERM
    |
    +--> wait timeout_kill seconds
    |
    +--> if still alive -> SIGKILL

Timeline:

|---- timeout ----|---- timeout_kill ----|
fork              TERM                  KILL

CONSTRUCTOR

new

my $fork = Linux::Event::Fork->new(
  loop         => $loop,        # required
  max_children => 4,            # optional
);

Low-level constructor.

Users should normally call:

$loop->fork_helper(...)

instead.

LOOP METHODS

$loop->fork_helper(%opts)

Installs or returns the per-loop helper.

Options:

max_children => $non_negative_integer

Configuration is runtime-only.

Import-time options are not supported.

$loop->fork(%args)

Spawn a child or queue a request.

Returns:

Linux::Event::Fork::Child   (started immediately)
Linux::Event::Fork::Request (queued)

fork() OPTIONS

Exactly one of:

cmd   => [ @argv ]
child => sub { ... }

Optional keys:

tag        => $string
data       => $any_scalar

on_stdout  => sub ($child, $chunk) { ... }
    Runs in parent when child writes to stdout.

on_stderr  => sub ($child, $chunk) { ... }
    Runs in parent when child writes to stderr.

on_exit    => sub ($child, $exit) { ... }
    Runs in parent after child has fully exited.

timeout        => $seconds
    Soft timeout in seconds.

on_timeout     => sub ($child) { ... }
    Runs in parent when timeout fires.

timeout_kill   => $seconds
    Escalation delay before SIGKILL.

INTROSPECTION

$fork->running
$fork->queued
$fork->max_children

WHAT THIS MODULE IS NOT

This is not a supervisor, scheduler, or promise framework.

It is a deterministic process management layer built directly on Linux::Event.

AUTHOR

Joshua S. Day

LICENSE

Same terms as Perl itself.