modifs.mineures sans commentaires

This commit is contained in:
Jephté Clain 2024-09-26 19:35:24 +04:00
parent 789642ce5f
commit 1c936caf26
9 changed files with 125 additions and 69 deletions

View File

@ -1,5 +1,5 @@
<?php
# script à inclure pour implémenter _cli_simple_launcher.php
# script à inclure pour implémenter _launcher.php
# les constantes suivantes doivent être définies AVANT de chager ce script:
# - NULIB_APP_app_params : paramètres du projet
@ -7,7 +7,10 @@ use nur\sery\os\path;
use nur\sery\wip\app\app2;
if ($argc <= 1) die("invalid arguments");
app2::init(NULIB_APP_app_params);
app2::init([
"projdir" => __DIR__ . '/..',
"appcode" => \app\config\bootstrap::APPCODE,
]);
$app = $argv[1];
if (class_exists($app)) {
# la configuration est celle actuellement chargée

View File

@ -0,0 +1,19 @@
#!/usr/bin/php
<?php
require __DIR__.'/../vendor/autoload.php';
# Lancer une application en tâche de fond
# TODO Faire une copie de ce script dans un répertoire de l'application web
# (par défaut c'est le répertoire bin/) et modifier les paramètres si nécessaire
use nur\sery\tools\BgLauncherApp;
use nur\sery\wip\app\app2;
# chemin vers le lanceur PHP
const NULIB_APP_app_launcher = __DIR__.'/../_cli/_launcher.php';
app2::init([
"projdir" => __DIR__ . '/..',
"appcode" => \app\config\bootstrap::APPCODE,
]);
BgLauncherApp::run();

View File

@ -2,7 +2,7 @@
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
# s'assurer que le script PHP est lancé avec l'utilisateur www-data
# Faire une copie de ce script dans un répertoire de l'application web
# TODO Faire une copie de ce script dans un répertoire de l'application web
# (par défaut c'est le répertoire _cli/) et paramétrer les variables suivantes:
# ce sont tous des chemins relatif au répertoire qui contient ce script
@ -10,7 +10,7 @@
PROJPATH=..
# Chemin relatif vers le lanceur PHP
LAUNCHERPATH=_cli_simple_launcher.php
LAUNCHERPATH=_launcher.php
# Chemin relatif des scripts PHP wrappés
WRAPPEDPATH=

View File

@ -10,6 +10,7 @@ use nur\sery\StateException;
use nur\sery\str;
use nur\sery\wip\app\app;
#XXX sera obsolète quand cli\bg_launcher sera mis en prod
class launcher {
/**
* transformer une liste d'argument de la forme

View File

@ -36,7 +36,7 @@ class BgLauncherApp extends Application {
static function show_infos(RunFile $runfile, ?int $level=null): void {
msg::print($runfile->getDesc(), $level);
msg::print(yaml::with(["data" => $runfile->read()]), -1);
msg::print(yaml::with(["data" => $runfile->read()]), ($level ?? 0) - 1);
}
function main() {
@ -60,7 +60,7 @@ class BgLauncherApp extends Application {
switch ($this->action) {
case self::ACTION_START:
$appClass::_manage_runfile(count($args), $args, $runfile);
if ($runfile->warnIfLocked()) return;
if ($runfile->warnIfLocked()) self::exit(app2::EC_LOCKED);
array_splice($args, 0, 0, [
PHP_BINARY,
path::abspath(NULIB_APP_app_launcher),
@ -70,7 +70,7 @@ class BgLauncherApp extends Application {
break;
case self::ACTION_STOP:
bg_launcher::_stop($runfile);
self::show_infos($runfile);
self::show_infos($runfile, -1);
break;
case self::ACTION_INFOS:
self::show_infos($runfile);

View File

@ -21,14 +21,14 @@ EOT,
["-c", "--count", "args" => 1,
"help" => "spécifier le nombre d'étapes",
],
["-s", "--install-signal-handler", "value" => true,
"help" => "installer un gestionnaire de signaux",
["-n", "--no-install-signal-handler", "value" => false,
"help" => "ne pas installer le gestionnaire de signaux",
],
];
protected $count = 100;
protected bool $installSignalHandler = false;
protected bool $installSignalHandler = true;
function main() {
if ($this->installSignalHandler) app2::install_signal_handler();

View File

@ -5,6 +5,7 @@ use nur\sery\A;
use nur\sery\cl;
use nur\sery\file\SharedFile;
use nur\sery\os\path;
use nur\sery\os\sh;
use nur\sery\output\msg;
use nur\sery\php\time\DateTime;
use nur\sery\php\time\Elapsed;
@ -70,6 +71,16 @@ class RunFile {
];
}
function reset(bool $delete=false) {
$file = $this->file;
if ($delete) {
$file->close();
unlink($file->getFile());
} else {
$file->ftruncate();
}
}
function read(): array {
$data = $this->file->unserialize();
if (!is_array($data)) $data = $this->initData();
@ -274,6 +285,59 @@ class RunFile {
});
}
private static function kill(int $pid, int $signal, ?string &$reason=null): bool {
if (!posix_kill($pid, $signal)) {
switch (posix_get_last_error()) {
case PCNTL_ESRCH:
$reason = "process inexistant";
break;
case PCNTL_EPERM:
$reason = "process non accessible";
break;
case PCNTL_EINVAL:
$reason = "signal invalide";
break;
}
return false;
}
return true;
}
function wfKill(?string &$reason=null): bool {
$data = $this->read();
$pid = $this->_getCid($data);
$stopped = false;
$timeout = 10;
$delay = 300000;
while (--$timeout >= 0) {
if (!self::kill($pid, SIGTERM, $reason)) return false;
usleep($delay);
$delay = 1000000; // attendre 1 seconde à partir de la deuxième fois
if (!$this->_isRunning($data)) {
$stopped = true;
break;
}
}
if (!$stopped) {
$timeout = 3;
$delay = 300000;
while (--$timeout >= 0) {
if (!self::kill($pid, SIGKILL, $reason)) return false;
usleep($delay);
$delay = 1000000; // attendre 1 seconde à partir de la deuxième fois
if (!$this->_isRunning($data)) {
$stopped = true;
break;
}
}
}
if ($stopped) {
sh::_waitpid($pid, $exitcode);
$this->wfReaped($exitcode);
}
return $stopped;
}
/**
* vérifier si on est dans le cas la tâche devrait tourner mais en réalité
* ce n'est pas le cas

View File

@ -14,6 +14,7 @@ use nur\sery\ValueException;
use nur\sery\wip\app\app2;
use nur\sery\wip\app\RunFile;
use nur\sery\wip\web\content\v;
use nur\yaml;
/**
* Class Application: application de base
@ -82,11 +83,21 @@ abstract class Application {
/** @var bool faut-il installer le gestionnaire de signaux? */
const INSTALL_SIGNAL_HANDLER = false;
private static function _error(string $message, int $ec=1): int {
fwrite(STDERR, "ERROR: $message\n");
return $ec;
}
static function _manage_runfile(int $argc, array $argv, RunFile $runfile): void {
if ($argc <= 1 || $argv[1] !== "//") return;
array_splice($argv, 1, 1);
$ec = 0;
switch ($argv[1] ?? "infos") {
case "kill":
case "k":
if ($runfile->isRunning()) $runfile->wfKill();
else $ec = self::_error("not running");
break;
case "release-lock":
case "release":
case "rl":
@ -104,9 +115,17 @@ abstract class Application {
$ec = 1;
}
break;
case "dump":
case "d":
yaml::dump($runfile->read());
break;
case "reset":
case "z":
if (!$runfile->isRunning()) $runfile->reset();
else $ec = self::_error("cannot reset while running");
break;
default:
fwrite(STDERR, "$argv[1]: unexpected command\n");
$ec = app2::EC_BAD_COMMAND;
$ec = self::_error("$argv[1]: unexpected command", app2::EC_BAD_COMMAND);
}
exit($ec);
}

View File

@ -32,66 +32,16 @@ class bg_launcher {
}
}
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();
msg::action("stop $pid");
if ($runfile->wfKill($reason)) {
msg::asuccess();
return true;
} else {
msg::afailure($reason);
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;
}
}