walkor / workerman

An asynchronous event driven PHP socket framework. Supports HTTP, Websocket, SSL and other custom protocols.
http://www.workerman.net
MIT License
11.03k stars 2.25k forks source link

Update worker #968

Closed twomiao closed 9 months ago

twomiao commented 9 months ago
// 问题复现代码如下:
<?php
require __DIR__ . "/vendor/autoload.php";

use Workerman\Worker;
use Workerman\Events\Swoole;

 ///////////////// 设计未避免用户错误使用
Worker::$globalEvent = new Swoole();  
$worker = new Worker("http://0.0.0.0:8888");
$worker->name = "http-worker";
$worker->count = 1;
$worker->reusePort = false;

$worker->onMessage = fn($connection) => $connection->send("hello world!");

Worker::runAll();

修复前会导致3个问题:

Workerman[start.php] start in USER mode ----------------------------------------- WORKERMAN ----------------------------------------- Workerman version:5.0.0-beta.7 PHP version:8.1.13 Event-loop:Workerman\Events\Select 1、 事件循环错误显示 ------------------------------------------ WORKERS ------------------------------------------ proto user worker listen processes state tcp root http-worker http://0.0.0.0:8888 1 [OK]

Press Ctrl+C to stop. Start success. ^CWorkerman[start.php] stopping ... Workerman[start.php] has been stopped Swoole\Event::rshutdown(): Event::wait() in shutdown function is deprecated in file Unknown on line 0 (2) 主进程无法正常退出

1、未避免用户不规范使用,导致出现意外情况。 2、错误显示Select,这时候子进程实际上Swoole Epoll运行。 3、导致主进程epoll_wait() 阻塞住,无法退出。 因为已经实例化,主进程在reusePort = false 会把mainSocket 加入eventloop 这时候用户发出sigint信号通知服务器退出,Swoole退出时检测到有FD也就是mainSocket, 退出时候自动调用Event::wait() 会底层epoll_wait() 阻塞住。(主进程无法退出)

如何证明是epoll_wait() 阻塞主进程无法退出呢? Press Ctrl+C to stop. Start success. ^CWorkerman[start.php] stopping ... Workerman[start.php] has been stopped Swoole\Event::rshutdown(): Event::wait() in shutdown function is deprecated in file Unknown on line 0 ^C^C^C^C // strace: Process 21492 attached 21:47:41.820679 --- SIGINT {si_signo=SIGINT, si_code=SI_KERNEL} --- 21:47:41.822430 rt_sigreturn({mask=[]}) = -1 EINTR (Interrupted system call) 21:47:41.823437 time(NULL) = 1697464061 (2023-10-16T21:47:41+0800) 21:47:41.824790 epoll_wait(6,