|
|
@@ -14,6 +14,9 @@
|
|
|
|
|
|
namespace Workerman\Events;
|
|
|
|
|
|
+use Throwable;
|
|
|
+use Workerman\Worker;
|
|
|
+
|
|
|
/**
|
|
|
* select eventloop
|
|
|
*/
|
|
|
@@ -259,6 +262,7 @@ class Select implements EventInterface
|
|
|
*/
|
|
|
protected function tick()
|
|
|
{
|
|
|
+ $tasks_to_insert = [];
|
|
|
while (!$this->_scheduler->isEmpty()) {
|
|
|
$scheduler_data = $this->_scheduler->top();
|
|
|
$timer_id = $scheduler_data['data'];
|
|
|
@@ -276,13 +280,27 @@ class Select implements EventInterface
|
|
|
$task_data = $this->_eventTimer[$timer_id];
|
|
|
if (isset($task_data[2])) {
|
|
|
$next_run_time = $time_now + $task_data[2];
|
|
|
- $this->_scheduler->insert($timer_id, -$next_run_time);
|
|
|
+ $tasks_to_insert[] = [$timer_id, -$next_run_time];
|
|
|
} else {
|
|
|
unset($this->_eventTimer[$timer_id]);
|
|
|
}
|
|
|
- $task_data[0]($task_data[1]);
|
|
|
- continue;
|
|
|
+ try {
|
|
|
+ $task_data[0]($task_data[1]);
|
|
|
+ } catch (Throwable $e) {
|
|
|
+ Worker::stopAll(250, $e);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ break;
|
|
|
}
|
|
|
+ }
|
|
|
+ foreach ($tasks_to_insert as $item) {
|
|
|
+ $this->_scheduler->insert($item[0], $item[1]);
|
|
|
+ }
|
|
|
+ if (!$this->_scheduler->isEmpty()) {
|
|
|
+ $scheduler_data = $this->_scheduler->top();
|
|
|
+ $next_run_time = -$scheduler_data['priority'];
|
|
|
+ $time_now = \microtime(true);
|
|
|
+ $this->_selectTimeout = \max((int)(($next_run_time - $time_now) * 1000000), 0);
|
|
|
return;
|
|
|
}
|
|
|
$this->_selectTimeout = 100000000;
|
|
|
@@ -317,12 +335,11 @@ class Select implements EventInterface
|
|
|
// Waiting read/write/signal/timeout events.
|
|
|
try {
|
|
|
@stream_select($read, $write, $except, 0, $this->_selectTimeout);
|
|
|
- } catch (\Throwable $e) {
|
|
|
+ } catch (Throwable $e) {
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
$this->_selectTimeout >= 1 && usleep($this->_selectTimeout);
|
|
|
- $ret = false;
|
|
|
}
|
|
|
|
|
|
if (!$this->_scheduler->isEmpty()) {
|