Skip to content

Instantly share code, notes, and snippets.

@bmichalski
Last active October 13, 2015 14:50
Show Gist options
  • Save bmichalski/1b3799b7e2128571635f to your computer and use it in GitHub Desktop.
Save bmichalski/1b3799b7e2128571635f to your computer and use it in GitHub Desktop.
PHP limitations set_time_limit workaround
<?php
$isDefunct = function ($result) {
return preg_match('/<defunct>$/', $result);
};
$getProcessInfo = function ($pid) {
return exec("ps --pid $pid | tail -n +2");
};
$isProcessDone = function ($pid) use ($getProcessInfo, $isDefunct) {
$result = $getProcessInfo($pid);
return '' === $result || $isDefunct($result);
};
$isProcessRunning = function ($pid) use ($getProcessInfo, $isDefunct) {
$result = $getProcessInfo($pid);
return '' !== $result && !$isDefunct($result);
};
$executeMaxTime = function (
$timeoutMilliSeconds,
\Closure $doWhat,
\Closure $onAfterChildKilled = null,
$checkEveryNMilliSeconds = 1000
) use ($isProcessDone, $isProcessRunning) {
$checkEveryNMicroSeconds = $checkEveryNMilliSeconds * 1000;
$pid = pcntl_fork();
if ($pid == -1) {
throw new \Exception('Cannot fork.');
} else if ($pid) {
for ($i = 0; $i < $timeoutMilliSeconds; $i += $checkEveryNMilliSeconds) {
if ($isProcessDone($pid)) {
echo 'Child ended during parent wait.'.PHP_EOL;
return;
}
usleep($checkEveryNMicroSeconds);
}
posix_kill($pid, SIGSTOP);
echo 'Parent stopped child.'.PHP_EOL;
if ($isProcessRunning($pid)) {
posix_kill($pid, SIGKILL);
if ($onAfterChildKilled !== null) {
$onAfterChildKilled();
}
} else {
echo 'Child won\'t be killed as its done.'.PHP_EOL;
}
$status = null;
pcntl_wait($status); //Protects us against zombies children
} else {
$doWhat();
}
};
$executeMaxTime(
5000,
function () {
for ($i = 0; $i < 10; $i += 1) {
echo 'Child still alive, not sleepin'.PHP_EOL;
sleep(1);
}
},
function () {
echo 'Parent killed child.'.PHP_EOL;
}
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment