98 lines
2.5 KiB
PHP
98 lines
2.5 KiB
PHP
<?php
|
|
namespace nur\sery\wip\app\cli;
|
|
|
|
use nur\sery\ExitError;
|
|
use nur\sery\os\proc\Cmd;
|
|
use nur\sery\os\sh;
|
|
use nur\sery\output\msg;
|
|
use nur\sery\wip\app\app2;
|
|
use nur\sery\wip\app\RunFile;
|
|
|
|
class bg_launcher {
|
|
static function _start(array $args, Runfile $runfile): void {
|
|
$pid = pcntl_fork();
|
|
if ($pid == -1) {
|
|
# parent, impossible de forker
|
|
throw new ExitError(app2::EC_FORK_PARENT, "Unable to fork");
|
|
} elseif (!$pid) {
|
|
# child, fork ok
|
|
$runfile->wfPrepare($pid);
|
|
$logfile = $runfile->getLogfile() ?? "/tmp/NULIB_APP_app_start.log";
|
|
$exitcode = app2::EC_FORK_CHILD;
|
|
try {
|
|
# puis lancer la commande
|
|
$cmd = new Cmd($args);
|
|
$cmd->addSource("/g/init.env");
|
|
$cmd->addRedir("both", $logfile, true);
|
|
$cmd->fork_exec($exitcode, false);
|
|
sh::_waitpid(-$pid, $exitcode);
|
|
} finally {
|
|
$runfile->wfReaped($exitcode);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static function kill(int $pid, int $signal): bool {
|
|
if (!posix_kill($pid, $signal)) {
|
|
switch (posix_get_last_error()) {
|
|
case PCNTL_ESRCH:
|
|
msg::afailure("process inexistant");
|
|
break;
|
|
case PCNTL_EPERM:
|
|
msg::afailure("process non accessible");
|
|
break;
|
|
case PCNTL_EINVAL:
|
|
msg::afailure("signal invalide");
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static function _stop(Runfile $runfile): bool {
|
|
$data = $runfile->read();
|
|
$pid = $runfile->_getCid($data);
|
|
$stopped = false;
|
|
msg::action("term $pid");
|
|
$timeout = 10;
|
|
$delay = 300000;
|
|
while (--$timeout >= 0) {
|
|
if (!self::kill($pid, SIGTERM)) {
|
|
msg::afailure();
|
|
return false;
|
|
}
|
|
usleep($delay);
|
|
$delay = 1000000; // attendre 1 seconde à partir de la deuxième fois
|
|
if (!$runfile->_isRunning($data)) {
|
|
msg::asuccess();
|
|
$stopped = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!$stopped) {
|
|
msg::action("kill $pid");
|
|
$timeout = 3;
|
|
$delay = 300000;
|
|
while (--$timeout >= 0) {
|
|
if (!self::kill($pid, SIGKILL)) {
|
|
msg::afailure();
|
|
return false;
|
|
}
|
|
usleep($delay);
|
|
$delay = 1000000; // attendre 1 seconde à partir de la deuxième fois
|
|
if (!$runfile->_isRunning($data)) {
|
|
msg::asuccess();
|
|
$stopped = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if ($stopped) {
|
|
sh::_waitpid($pid, $exitcode);
|
|
$runfile->wfReaped($exitcode);
|
|
}
|
|
return $stopped;
|
|
}
|
|
}
|