Installation:
composer require kriswallsmith/spork
Add to composer.json under require-dev if using for testing.
Basic Usage:
use Kris\Spork\Spork;
$spork = new Spork();
$pid = $spork->fork();
if ($pid === 0) {
// Child process logic
exit(0);
} else {
// Parent process logic
$spork->wait();
}
First Use Case:
$spork = new Spork();
$handles = [];
for ($i = 0; $i < 5; $i++) {
$pid = $spork->fork();
if ($pid === 0) {
// Child process
processLargeFile("file_$i");
exit(0);
}
$handles[] = $pid;
}
$spork->waitAll($handles);
Resource-Intensive Tasks:
$spork = new Spork();
$pid = $spork->fork();
if ($pid === 0) {
$result = runComplexCalculation();
file_put_contents('/tmp/result', $result);
exit(0);
}
Concurrent HTTP Requests:
$urls = ['url1', 'url2', 'url3'];
$spork = new Spork();
$handles = [];
foreach ($urls as $url) {
$pid = $spork->fork();
if ($pid === 0) {
$response = file_get_contents($url);
file_put_contents("/tmp/{$url}.html", $response);
exit(0);
}
$handles[] = $pid;
}
$spork->waitAll($handles);
Process Isolation:
$spork = new Spork();
$pid = $spork->fork();
if ($pid === 0) {
// Untrusted code here
eval($_POST['code']); // Hypothetical risky operation
exit(0);
}
Laravel Service Providers:
AppServiceProvider:
$this->app->singleton(Spork::class, function () {
return new Spork();
});
public function __construct(private Spork $spork) {}
Queue Workers:
public function handle() {
$spork = app(Spork::class);
$pid = $spork->fork();
if ($pid === 0) {
// Heavy processing
$this->processData();
exit(0);
}
}
Signal Handling:
SIGTERM).$spork = new Spork();
$pid = $spork->fork();
if ($pid > 0) {
pcntl_signal(SIGTERM, function () use ($spork, $pid) {
$spork->kill($pid);
});
}
Zombie Processes:
wait() or waitAll() to avoid orphaned processes.$spork->fork(); // Forgetting to wait!
Shared Memory Issues:
ignore_user_abort(true) if needed for long-running children.Signal Conflicts:
$this->app['events']->listen('terminating', function () {
// Custom cleanup
});
Resource Limits:
memory_limit and max_execution_time.ini_set() in the child:
if ($pid === 0) {
ini_set('memory_limit', '512M');
// ...
}
Logging:
$pid) for debugging:
error_log("Forked child with PID: $pid");
Process Inspection:
ps aux | grep php to check for rogue processes.kill -9 <PID>
Error Handling:
try-catch to prevent silent failures:
if ($pid === 0) {
try {
// Risky operations
} catch (\Throwable $e) {
file_put_contents('/tmp/error.log', $e->getMessage());
exit(1);
}
}
Custom Process Management:
class TimeoutSpork extends Spork {
public function forkWithTimeout(callable $callback, int $timeout) {
$pid = $this->fork();
if ($pid === 0) {
$callback();
exit(0);
}
$this->waitFor($pid, $timeout);
return $pid;
}
private function waitFor(int $pid, int $timeout) {
$start = time();
while (time() - $start < $timeout && pcntl_waitpid($pid, $status, WNOHANG) === 0) {
usleep(100000);
}
if (time() - $start >= $timeout) {
$this->kill($pid);
}
}
}
Inter-Process Communication (IPC):
if ($pid === 0) {
file_put_contents('/tmp/child_data', serialize($data));
exit(0);
} else {
$spork->wait();
$data = unserialize(file_get_contents('/tmp/child_data'));
}
Laravel Artisan Commands:
php artisan spork:run --task=process --args="file1,file2"
class SporkRunCommand extends Command {
protected $signature = 'spork:run {task} {args*}';
public function handle() {
$spork = app(Spork::class);
$pid = $spork->fork();
if ($pid === 0) {
$this->call("task:{$this->argument('task')}", ['args' => $this->argument('args')]);
exit(0);
}
$spork->wait();
}
}
How can I help you explore Laravel packages today?