swoole_process::kill 无法结束进程是什么原因?
xkungfu opened this issue · comments
start.php 文件内调用swoole_process::kill((int) $pid);
执行结果返回true.
但是通过swoole_process::kill($pid, 0)检查进程仍然存在。
应该可以排除环境和版本原因,因为单独写了一个测试的swoole的启动文件。\Swoole\Process::kill可以结束进程。
那么,sw-fw-less-app启动的swoole进程有什么特别之处,以致让swoole_process::kill无法结束进程呢?
可能是什么原因?
谢谢!
请问start.php文件什么位置调用swoole_process::kill代码?pid是从什么地方获取的呢?是否能提供完整可复现的代码
swoole_process::kill,执行后,进程还在。但是已经不接收信号 了,客户端的请求已经不执行了。命令行查看进程状态,显示多个CLOSE_WAIT 状态的进程。然后再启动swfwless也是启动不了,显示端口占用中。
代码如下:
$server_daemonize = 0;
//启动后存储pid到文件:
$pid_file = __DIR__ . '/server.pid';
//echo "\n ++ pid_file: " . $pid_file;
//获取命令行执行参数:
$shortopts = "s:"; // Required value
$options = getopt($shortopts);
//var_dump($options);
$opt = $options['s'] ?? 'null'; //echo "\n ++ opt: " . $opt;
if ($opt == 'k') {
echo "++try stopping! \n";
if (file_exists($pid_file)) {
$pid = file_get_contents($pid_file);
echo "swserver_stop pid: ", var_dump($pid);
//swserver_stop((int) $pid);
\Swoole\Process::kill((int) $pid);
$time = time();
$flag = false;
while (true) {
//每隔500毫秒检查一次:
usleep(500000);
if (!\Swoole\Process::kill($pid, 0)) {
echo "\n server stop at " . date("y-m-d h:i:s") . "\n";
//删除pid文件:
if (is_file($pid_file)) {
unlink($pid_file);
}
break;
} else {
//等待3秒
if (time() - $time > 3) {
echo "stop server fail. try again \n";
echo "netstat -apn | grep 9876 \n";
break;
}
}
}
exit;
} else {
echo "PID file not exists! \n netstat -apn | grep 9876 \n";
}
exit;
}
if ($opt == 'd') {
$server_daemonize = 1;
}
if ($opt == 'r') {
echo "\n ++reload!";
exit;
}
echo "start... \n";
!defined('APP_BASE_PATH') && define('APP_BASE_PATH', __DIR__ . '/');
//echo "APP_BASE_PATH: " . APP_BASE_PATH . "\n";
if (extension_loaded('jsonnet')) {
!defined('CONFIG_FORMAT') && define('CONFIG_FORMAT', 'array,jsonnet');
}
require_once __DIR__ . '/vendor/autoload.php';
echo "\n ++ server_daemonize: " . $server_daemonize . PHP_EOL;
//This app supports hot reload and shutdown triggered by SIGTERM
$server = new \SwFwLess\bootstrap\App($server_daemonize, $pid_file);
$server->run();
App.php文件的修改:
public function __construct($server_daemonize, $pid_file)
{
$this->bootstrap();
$this->swHttpServer = new \Swoole\Http\Server(
config('server.host'),
config('server.port')
);
$serverConfig = [
'reactor_num' => config('server.reactor_num'),
'worker_num' => config('server.worker_num'),
'daemonize' => $server_daemonize,
'backlog' => config('server.backlog'),
'max_request' => config('server.max_request'),
'dispatch_mode' => config('server.dispatch_mode'),
'open_http2_protocol' => config('server.open_http2_protocol'),
'task_worker_num' => config('server.task_worker_num'),
'task_enable_coroutine' => config('server.task_enable_coroutine'),
'pid_file' => $pid_file
];
命令行执行swfwless启动文件start.php时,在后面加上“ -sk”传入参数。
另外,直接在命令行输入 kill -15 进程号,也无法结束swfwless进程。swoole_process::kill调用的命令可能就是kill -15
独立的用于测试启动swoole和关闭进程的代码,存储为PHP文件即可执行:
<?php
$shortopts = "";
$shortopts .= "s:"; // Required value
//$shortopts .= "d:"; // Optional value
$options = getopt($shortopts);
//var_dump($options);
$arg = $options['s'] ?? 'null';
(new SwooleTest())->handle(array('action' => $arg));
class SwooleTest {
private $server;
private $pid_file;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'swoole {action}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'start or stop the swoole process';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct() {
$this->pid_file = __DIR__ . '/swoole_test.pid';
echo "this pid_file: " . $this->pid_file . "\n";
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle($args = array('action' => 'start')) {
//获取传递的操作
$arg = $args['action'];
switch ($arg) {
case 'start':
//检测进程是否已开启
$pid = $this->getPid();
if ($pid && \Swoole\Process::kill($pid, 0)) {
echo "process already exist!\r\n";
exit;
}
$this->server = new \swoole_http_server("0.0.0.0", 9876);
$this->server->set([
'worker_num' => 8,
'daemonize' => 1,
'max_request' => 1000,
'dispatch_mode' => 2,
'pid_file' => $this->pid_file,
]);
//绑定操作类回调函数
//$app = App::make('App\Handles\SwooleWebSocketHandle');
//$app = AppTest::testcallback();
$callback = function() {
return 'starting...';
};
//$this->server->on('open', array($app, 'onOpen'));
$this->server->on('message', $callback);
$this->server->on('request', $callback);
//$this->server->on('close', array($app, 'onClose'));
echo "process created successful!\r\n";
$this->server->start();
break;
case 'stop':
$pid = $this->getPid();
//$pid = 14319;
if (!$pid) {
echo "process not started!\r\n";
exit;
}
if (\Swoole\Process::kill((int) $pid)) {
echo "process close successful!\r\n";
exit;
}
echo "process close failed!\r\n";
break;
default:
echo "operation method does not exist!\r\n";
}
}
//获取pid
private function getPid() {
return file_exists($this->pid_file) ? file_get_contents($this->pid_file) : false;
}
}
class AppTest {
public function testcallback($value = '') {
return 'starting...';
}
}
可能是这块代码的问题,已经尝试修复,请更新composer包之后再试试
$this->hotReload();
$this->registerScheduler();
$this->pullApolloConfig();
haode.谢谢
现在正常了,可以通过上面的代码实现结束进程了。非常感谢!
不客气