Search by

rasuvaeff / context-process

rasuvaeff

Run external processes under a rasuvaeff/context budget: the timeout follows the deadline, cancellation stops the process (SIGTERM, then SIGKILL)

Package info

github.com/rasuvaeff/context-process

pkg:composer/rasuvaeff/context-process

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.1.0 2026-10-15 20:13 UTC

This package is auto-updated.

Last update: 2026-10-15 20:17:29 UTC


README

Latest Stable Version Total Downloads Build Static analysis Psalm level PHP License

Runs external processes (ImageMagick, wkhtmltopdf, git, ffmpeg, your own scripts) under a rasuvaeff/context budget. When the deadline passes or the context is cancelled, the process is really stopped — SIGTERM, then SIGKILL after a grace period — instead of running on after the caller gave up.

Using an AI coding assistant? llms.txt contains a compact API reference you can share with the model. Projects using the llm/skills Composer plugin also get this package's agent skill synced into .agents/skills/ automatically on install.

Requirements

  • PHP 8.3+
  • rasuvaeff/context ^0.3
  • symfony/process ^7.0 or ^8.0

Installation

composer require rasuvaeff/context-process

Limitations

  • Only the process itself gets the signal. Pass the command as an argv array (new Process(['convert', $in, $out])), not a shell string: with Process::fromShellCommandline() the shell receives SIGTERM and its children may keep running.
  • The grace period is not bounded by the budget: a process that handles SIGTERM gets $gracePeriod seconds to clean up even after the deadline.
  • Termination is noticed within one poll interval ($pollInterval, 50 ms by default); a cancellation requested from a signal handler wakes the wait immediately.
  • Windows: there are no signals — symfony/process terminates the process (taskkill) instead of SIGTERM/SIGKILL.

Usage

use Rasuvaeff\Context\ContextExpiredException;
use Rasuvaeff\Context\Process\ContextProcess;
use Symfony\Component\Process\Process;

try {
    $exitCode = ContextProcess::run(
        new Process(['convert', $in, '-resize', '50%', $out]),
        $context,                                   // e.g. the request or job context
        callback: static fn(string $type, string $chunk) => $log->debug($chunk),
        gracePeriod: 2.0,                           // SIGTERM → wait → SIGKILL
    );
} catch (ContextExpiredException) {
    // the budget ran out: the process is already stopped
}
Situation What happens
The process finishes in time Its exit code is returned
The deadline passes The process is stopped (SIGTERM, SIGKILL after gracePeriod); ContextExpiredException
The context is cancelled (also via requestCancel() from a signal handler, e.g. rasuvaeff/context-cli) The process is stopped; ContextCancelledException with the reason as previous
The context is already terminated The process is never started
The process's own setTimeout() / setIdleTimeout() fires symfony/process stops it; its ProcessTimedOutException is rethrown unchanged
The callback throws The process is stopped; the callback's exception propagates
The process was already started LogicException

The budget is not turned into the process's own timeout: symfony/process kills on timeout with no grace period, while the context's deadline goes through the same SIGTERM → grace → SIGKILL path as a cancellation.

Public API

Class Description
ContextProcess run(Process $process, Context $context, ?callable $callback = null, float $gracePeriod = 2.0, float $pollInterval = 0.05): int

Security

Arguments are passed as an argv array to symfony/process, never through a shell. The package adds no input of its own to the command line.

Examples

See examples/ for runnable scripts.

Script Shows Needs server?
budget.php A 10 s command stopped by a 0.5 s budget; a command within the budget returning its exit code and output no

Development

No PHP/Composer on the host — run in Docker via the composer:2 image:

make install
make build
make cs-fix
make test
make test-coverage
make mutation
make release-check

License

BSD-3-Clause