Преглед на файлове

Merge pull request #3 from walkor/master

merge update
Leonardo преди 8 години
родител
ревизия
a82763c208
променени са 11 файла, в които са добавени 400 реда и са изтрити 293 реда
  1. 13 2
      Events/Ev.php
  2. 13 2
      Events/Event.php
  3. 7 0
      Events/EventInterface.php
  4. 12 0
      Events/Libevent.php
  5. 0 265
      Events/React.php
  6. 97 0
      Events/React/ExtEventLoop.php
  7. 97 0
      Events/React/LibEventLoop.php
  8. 95 0
      Events/React/StreamSelectLoop.php
  9. 10 0
      Events/Select.php
  10. 11 3
      Protocols/Http.php
  11. 45 21
      Worker.php

+ 13 - 2
Events/Ev.php

@@ -65,7 +65,6 @@ class Ev implements EventInterface
                 exit(250);
             }
         };
-
         switch ($flag) {
             case self::EV_SIGNAL:
                 $event                   = new \EvSignal($fd, $callback);
@@ -109,7 +108,7 @@ class Ev implements EventInterface
             case  self::EV_SIGNAL:
                 $fd_key = (int)$fd;
                 if (isset($this->_eventSignal[$fd_key])) {
-                    $this->_allEvents[$fd_key][$flag]->stop();
+                    $this->_eventSignal[$fd_key]->stop();
                     unset($this->_eventSignal[$fd_key]);
                 }
                 break;
@@ -170,4 +169,16 @@ class Ev implements EventInterface
     {
         \Ev::run();
     }
+
+    /**
+     * Destroy loop.
+     *
+     * @return void
+     */
+    public function destroy()
+    {
+        foreach ($this->_allEvents as $event) {
+            $event->stop();
+        }
+    }
 }

+ 13 - 2
Events/Event.php

@@ -120,10 +120,9 @@ class Event implements EventInterface
                 break;
 
             case  self::EV_SIGNAL:
-
                 $fd_key = (int)$fd;
                 if (isset($this->_eventSignal[$fd_key])) {
-                    $this->_allEvents[$fd_key][$flag]->del();
+                    $this->_eventSignal[$fd_key]->del();
                     unset($this->_eventSignal[$fd_key]);
                 }
                 break;
@@ -185,4 +184,16 @@ class Event implements EventInterface
     {
         $this->_eventBase->loop();
     }
+
+    /**
+     * Destroy loop.
+     *
+     * @return void
+     */
+    public function destroy()
+    {
+        foreach ($this->_eventSignal as $event) {
+            $event->del();
+        }
+    }
 }

+ 7 - 0
Events/EventInterface.php

@@ -83,4 +83,11 @@ interface EventInterface
      * @return void
      */
     public function loop();
+
+    /**
+     * Destroy loop.
+     *
+     * @return mixed
+     */
+    public function destroy();
 }

+ 12 - 0
Events/Libevent.php

@@ -201,5 +201,17 @@ class Libevent implements EventInterface
     {
         event_base_loop($this->_eventBase);
     }
+
+    /**
+     * Destroy loop.
+     *
+     * @return void
+     */
+    public function destroy()
+    {
+        foreach ($this->_eventSignal as $event) {
+            event_del($event);
+        }
+    }
 }
 

+ 0 - 265
Events/React.php

@@ -1,265 +0,0 @@
-<?php
-/**
- * This file is part of workerman.
- *
- * Licensed under The MIT License
- * For full copyright and license information, please see the MIT-LICENSE.txt
- * Redistributions of files must retain the above copyright notice.
- *
- * @author    walkor<walkor@workerman.net>
- * @copyright walkor<walkor@workerman.net>
- * @link      http://www.workerman.net/
- * @license   http://www.opensource.org/licenses/mit-license.php MIT License
- */
-namespace Workerman\Events;
-use React\EventLoop\LoopInterface;
-use React\EventLoop\Timer\TimerInterface;
-
-/**
- * select eventloop
- */
-class React implements LoopInterface
-{
-    /**
-     * @var React\EventLoop\LoopInterface
-     */
-    protected $_loop = null;
-
-    /**
-     * @var array
-     */
-    protected $_timerIdMap = array();
-
-    /**
-     * @var int
-     */
-    protected $_timerIdIndex = 0;
-
-    /**
-     * React constructor.
-     */
-    public function __construct() {
-        if (function_exists('event_base_new')) {
-            $this->_loop = new \Workerman\Events\React\LibEventLoop();
-        } elseif (class_exists('EventBase', false)) {
-            $this->_loop = new \Workerman\Events\React\ExtEventLoop();
-        } else {
-            $this->_loop = new \Workerman\Events\React\StreamSelectLoop();
-        }
-    }
-
-    /**
-     * Add event listener to event loop.
-     *
-     * @param $fd
-     * @param $flag
-     * @param $func
-     * @param array $args
-     * @return bool
-     */
-    public function add($fd, $flag, $func, $args = array())
-    {
-        $args = (array)$args;
-        switch ($flag) {
-            case EventInterface::EV_READ:
-                return $this->_loop->addReadStream($fd, $func);
-            case EventInterface::EV_WRITE:
-                return $this->_loop->addWriteStream($fd, $func);
-            case EventInterface::EV_SIGNAL:
-                return $this->_loop->addSignal($fd, $func);
-            case EventInterface::EV_TIMER:
-                $timer_obj = $this->_loop->addPeriodicTimer($fd, function() use ($func, $args) {
-                    call_user_func_array($func, $args);
-                });
-                $this->_timerIdMap[++$this->_timerIdIndex] = $timer_obj;
-                return $this->_timerIdIndex;
-            case EventInterface::EV_TIMER_ONCE:
-                $timer_obj = $this->_loop->addTimer($fd, function() use ($func, $args) {
-                    call_user_func_array($func, $args);
-                });
-                $this->_timerIdMap[++$this->_timerIdIndex] = $timer_obj;
-                return $this->_timerIdIndex;
-        }
-        return false;
-    }
-
-    /**
-     * Remove event listener from event loop.
-     *
-     * @param mixed $fd
-     * @param int   $flag
-     * @return bool
-     */
-    public function del($fd, $flag)
-    {
-        switch ($flag) {
-            case EventInterface::EV_READ:
-                return $this->_loop->removeReadStream($fd);
-            case EventInterface::EV_WRITE:
-                return $this->_loop->removeWriteStream($fd);
-            case EventInterface::EV_SIGNAL:
-                return $this->_loop->removeSignal($fd);
-            case EventInterface::EV_TIMER:
-            case EventInterface::EV_TIMER_ONCE;
-                if (isset($this->_timerIdMap[$fd])){
-                    $timer_obj = $this->_timerIdMap[$fd];
-                    unset($this->_timerIdMap[$fd]);
-                    $this->_loop->cancelTimer($timer_obj);
-                    return true;
-                }
-        }
-        return false;
-    }
-
-
-    /**
-     * Main loop.
-     *
-     * @return void
-     */
-    public function loop()
-    {
-        $this->_loop->run();
-    }
-
-    /**
-     * Register a listener to be notified when a stream is ready to read.
-     *
-     * @param resource $stream   The PHP stream resource to check.
-     * @param callable $listener Invoked when the stream is ready.
-     */
-    public function addReadStream($stream, callable $listener) {
-        return call_user_func(array($this->_loop, 'addReadStream'), $stream, $listener);
-    }
-
-    /**
-     * Register a listener to be notified when a stream is ready to write.
-     *
-     * @param resource $stream   The PHP stream resource to check.
-     * @param callable $listener Invoked when the stream is ready.
-     */
-    public function addWriteStream($stream, callable $listener) {
-        return call_user_func(array($this->_loop, 'addWriteStream'), $stream, $listener);
-    }
-
-    /**
-     * Remove the read event listener for the given stream.
-     *
-     * @param resource $stream The PHP stream resource.
-     */
-    public function removeReadStream($stream) {
-        return call_user_func(array($this->_loop, 'removeReadStream'), $stream);
-    }
-
-    /**
-     * Remove the write event listener for the given stream.
-     *
-     * @param resource $stream The PHP stream resource.
-     */
-    public function removeWriteStream($stream) {
-        return call_user_func(array($this->_loop, 'removeWriteStream'), $stream);
-    }
-
-    /**
-     * Remove all listeners for the given stream.
-     *
-     * @param resource $stream The PHP stream resource.
-     */
-    public function removeStream($stream) {
-        return call_user_func(array($this->_loop, 'removeStream'), $stream);
-    }
-
-    /**
-     * Enqueue a callback to be invoked once after the given interval.
-     *
-     * The execution order of timers scheduled to execute at the same time is
-     * not guaranteed.
-     *
-     * @param int|float $interval The number of seconds to wait before execution.
-     * @param callable  $callback The callback to invoke.
-     *
-     * @return TimerInterface
-     */
-    public function addTimer($interval, callable $callback) {
-        return call_user_func(array($this->_loop, 'addTimer'), $interval, $callback);
-    }
-
-    /**
-     * Enqueue a callback to be invoked repeatedly after the given interval.
-     *
-     * The execution order of timers scheduled to execute at the same time is
-     * not guaranteed.
-     *
-     * @param int|float $interval The number of seconds to wait before execution.
-     * @param callable  $callback The callback to invoke.
-     *
-     * @return TimerInterface
-     */
-    public function addPeriodicTimer($interval, callable $callback) {
-        return call_user_func(array($this->_loop, 'addPeriodicTimer'), $interval, $callback);
-    }
-
-    /**
-     * Cancel a pending timer.
-     *
-     * @param TimerInterface $timer The timer to cancel.
-     */
-    public function cancelTimer(TimerInterface $timer) {
-        return call_user_func(array($this->_loop, 'cancelTimer'), $timer);
-    }
-
-    /**
-     * Check if a given timer is active.
-     *
-     * @param TimerInterface $timer The timer to check.
-     *
-     * @return boolean True if the timer is still enqueued for execution.
-     */
-    public function isTimerActive(TimerInterface $timer) {
-        return call_user_func(array($this->_loop, 'isTimerActive'), $timer);
-    }
-
-    /**
-     * Schedule a callback to be invoked on the next tick of the event loop.
-     *
-     * Callbacks are guaranteed to be executed in the order they are enqueued,
-     * before any timer or stream events.
-     *
-     * @param callable $listener The callback to invoke.
-     */
-    public function nextTick(callable $listener) {
-        return call_user_func(array($this->_loop, 'nextTick'), $listener);
-    }
-
-    /**
-     * Schedule a callback to be invoked on a future tick of the event loop.
-     *
-     * Callbacks are guaranteed to be executed in the order they are enqueued.
-     *
-     * @param callable $listener The callback to invoke.
-     */
-    public function futureTick(callable $listener) {
-        return call_user_func(array($this->_loop, 'futureTick'), $listener);
-    }
-
-    /**
-     * Perform a single iteration of the event loop.
-     */
-    public function tick() {
-        return call_user_func(array($this->_loop, 'tick'));
-    }
-
-    /**
-     * Run the event loop until there are no more tasks to perform.
-     */
-    public function run() {
-        return call_user_func(array($this->_loop, 'run'));
-    }
-
-    /**
-     * Instruct a running event loop to stop.
-     */
-    public function stop() {
-        return call_user_func(array($this->_loop, 'stop'));
-    }
-}

+ 97 - 0
Events/React/ExtEventLoop.php

@@ -12,6 +12,7 @@
  * @license   http://www.opensource.org/licenses/mit-license.php MIT License
  */
 namespace Workerman\Events\React;
+use Workerman\Events\EventInterface;
 
 /**
  * Class ExtEventLoop
@@ -34,6 +35,90 @@ class ExtEventLoop extends \React\EventLoop\ExtEventLoop
     protected $_signalEvents = array();
 
     /**
+     * @var array
+     */
+    protected $_timerIdMap = array();
+
+    /**
+     * @var int
+     */
+    protected $_timerIdIndex = 0;
+
+    /**
+     * Add event listener to event loop.
+     *
+     * @param $fd
+     * @param $flag
+     * @param $func
+     * @param array $args
+     * @return bool
+     */
+    public function add($fd, $flag, $func, $args = array())
+    {
+        $args = (array)$args;
+        switch ($flag) {
+            case EventInterface::EV_READ:
+                return $this->addReadStream($fd, $func);
+            case EventInterface::EV_WRITE:
+                return $this->addWriteStream($fd, $func);
+            case EventInterface::EV_SIGNAL:
+                return $this->addSignal($fd, $func);
+            case EventInterface::EV_TIMER:
+                $timer_obj = $this->addPeriodicTimer($fd, function() use ($func, $args) {
+                    call_user_func_array($func, $args);
+                });
+                $this->_timerIdMap[++$this->_timerIdIndex] = $timer_obj;
+                return $this->_timerIdIndex;
+            case EventInterface::EV_TIMER_ONCE:
+                $timer_obj = $this->addTimer($fd, function() use ($func, $args) {
+                    call_user_func_array($func, $args);
+                });
+                $this->_timerIdMap[++$this->_timerIdIndex] = $timer_obj;
+                return $this->_timerIdIndex;
+        }
+        return false;
+    }
+
+    /**
+     * Remove event listener from event loop.
+     *
+     * @param mixed $fd
+     * @param int   $flag
+     * @return bool
+     */
+    public function del($fd, $flag)
+    {
+        switch ($flag) {
+            case EventInterface::EV_READ:
+                return $this->removeReadStream($fd);
+            case EventInterface::EV_WRITE:
+                return $this->removeWriteStream($fd);
+            case EventInterface::EV_SIGNAL:
+                return $this->removeSignal($fd);
+            case EventInterface::EV_TIMER:
+            case EventInterface::EV_TIMER_ONCE;
+                if (isset($this->_timerIdMap[$fd])){
+                    $timer_obj = $this->_timerIdMap[$fd];
+                    unset($this->_timerIdMap[$fd]);
+                    $this->cancelTimer($timer_obj);
+                    return true;
+                }
+        }
+        return false;
+    }
+
+
+    /**
+     * Main loop.
+     *
+     * @return void
+     */
+    public function loop()
+    {
+        $this->run();
+    }
+
+    /**
      * Construct
      */
     public function __construct()
@@ -73,4 +158,16 @@ class ExtEventLoop extends \React\EventLoop\ExtEventLoop
             unset($this->_signalEvents[$signal]);
         }
     }
+
+    /**
+     * Destroy loop.
+     *
+     * @return void
+     */
+    public function destroy()
+    {
+        foreach ($this->_signalEvents as $event) {
+            $event->del();
+        }
+    }
 }

+ 97 - 0
Events/React/LibEventLoop.php

@@ -12,6 +12,7 @@
  * @license   http://www.opensource.org/licenses/mit-license.php MIT License
  */
 namespace Workerman\Events\React;
+use Workerman\Events\EventInterface;
 
 /**
  * Class LibEventLoop
@@ -34,6 +35,90 @@ class LibEventLoop extends \React\EventLoop\LibEventLoop
     protected $_signalEvents = array();
 
     /**
+     * @var array
+     */
+    protected $_timerIdMap = array();
+
+    /**
+     * @var int
+     */
+    protected $_timerIdIndex = 0;
+
+    /**
+     * Add event listener to event loop.
+     *
+     * @param $fd
+     * @param $flag
+     * @param $func
+     * @param array $args
+     * @return bool
+     */
+    public function add($fd, $flag, $func, $args = array())
+    {
+        $args = (array)$args;
+        switch ($flag) {
+            case EventInterface::EV_READ:
+                return $this->addReadStream($fd, $func);
+            case EventInterface::EV_WRITE:
+                return $this->addWriteStream($fd, $func);
+            case EventInterface::EV_SIGNAL:
+                return $this->addSignal($fd, $func);
+            case EventInterface::EV_TIMER:
+                $timer_obj = $this->addPeriodicTimer($fd, function() use ($func, $args) {
+                    call_user_func_array($func, $args);
+                });
+                $this->_timerIdMap[++$this->_timerIdIndex] = $timer_obj;
+                return $this->_timerIdIndex;
+            case EventInterface::EV_TIMER_ONCE:
+                $timer_obj = $this->addTimer($fd, function() use ($func, $args) {
+                    call_user_func_array($func, $args);
+                });
+                $this->_timerIdMap[++$this->_timerIdIndex] = $timer_obj;
+                return $this->_timerIdIndex;
+        }
+        return false;
+    }
+
+    /**
+     * Remove event listener from event loop.
+     *
+     * @param mixed $fd
+     * @param int   $flag
+     * @return bool
+     */
+    public function del($fd, $flag)
+    {
+        switch ($flag) {
+            case EventInterface::EV_READ:
+                return $this->removeReadStream($fd);
+            case EventInterface::EV_WRITE:
+                return $this->removeWriteStream($fd);
+            case EventInterface::EV_SIGNAL:
+                return $this->removeSignal($fd);
+            case EventInterface::EV_TIMER:
+            case EventInterface::EV_TIMER_ONCE;
+                if (isset($this->_timerIdMap[$fd])){
+                    $timer_obj = $this->_timerIdMap[$fd];
+                    unset($this->_timerIdMap[$fd]);
+                    $this->cancelTimer($timer_obj);
+                    return true;
+                }
+        }
+        return false;
+    }
+
+
+    /**
+     * Main loop.
+     *
+     * @return void
+     */
+    public function loop()
+    {
+        $this->run();
+    }
+
+    /**
      * Construct.
      */
     public function __construct()
@@ -74,4 +159,16 @@ class LibEventLoop extends \React\EventLoop\LibEventLoop
             unset($this->_signalEvents[$signal]);
         }
     }
+
+    /**
+     * Destroy loop.
+     *
+     * @return void
+     */
+    public function destroy()
+    {
+        foreach ($this->_signalEvents as $event) {
+            event_del($event);
+        }
+    }
 }

+ 95 - 0
Events/React/StreamSelectLoop.php

@@ -12,6 +12,7 @@
  * @license   http://www.opensource.org/licenses/mit-license.php MIT License
  */
 namespace Workerman\Events\React;
+use Workerman\Events\EventInterface;
 
 /**
  * Class StreamSelectLoop
@@ -20,6 +21,90 @@ namespace Workerman\Events\React;
 class StreamSelectLoop extends \React\EventLoop\StreamSelectLoop
 {
     /**
+     * @var array
+     */
+    protected $_timerIdMap = array();
+
+    /**
+     * @var int
+     */
+    protected $_timerIdIndex = 0;
+
+    /**
+     * Add event listener to event loop.
+     *
+     * @param $fd
+     * @param $flag
+     * @param $func
+     * @param array $args
+     * @return bool
+     */
+    public function add($fd, $flag, $func, $args = array())
+    {
+        $args = (array)$args;
+        switch ($flag) {
+            case EventInterface::EV_READ:
+                return $this->addReadStream($fd, $func);
+            case EventInterface::EV_WRITE:
+                return $this->addWriteStream($fd, $func);
+            case EventInterface::EV_SIGNAL:
+                return $this->addSignal($fd, $func);
+            case EventInterface::EV_TIMER:
+                $timer_obj = $this->addPeriodicTimer($fd, function() use ($func, $args) {
+                    call_user_func_array($func, $args);
+                });
+                $this->_timerIdMap[++$this->_timerIdIndex] = $timer_obj;
+                return $this->_timerIdIndex;
+            case EventInterface::EV_TIMER_ONCE:
+                $timer_obj = $this->addTimer($fd, function() use ($func, $args) {
+                    call_user_func_array($func, $args);
+                });
+                $this->_timerIdMap[++$this->_timerIdIndex] = $timer_obj;
+                return $this->_timerIdIndex;
+        }
+        return false;
+    }
+
+    /**
+     * Remove event listener from event loop.
+     *
+     * @param mixed $fd
+     * @param int   $flag
+     * @return bool
+     */
+    public function del($fd, $flag)
+    {
+        switch ($flag) {
+            case EventInterface::EV_READ:
+                return $this->removeReadStream($fd);
+            case EventInterface::EV_WRITE:
+                return $this->removeWriteStream($fd);
+            case EventInterface::EV_SIGNAL:
+                return $this->removeSignal($fd);
+            case EventInterface::EV_TIMER:
+            case EventInterface::EV_TIMER_ONCE;
+                if (isset($this->_timerIdMap[$fd])){
+                    $timer_obj = $this->_timerIdMap[$fd];
+                    unset($this->_timerIdMap[$fd]);
+                    $this->cancelTimer($timer_obj);
+                    return true;
+                }
+        }
+        return false;
+    }
+
+
+    /**
+     * Main loop.
+     *
+     * @return void
+     */
+    public function loop()
+    {
+        $this->run();
+    }
+
+    /**
      * Add signal handler.
      *
      * @param $signal
@@ -74,4 +159,14 @@ class StreamSelectLoop extends \React\EventLoop\StreamSelectLoop
 
         return 0;
     }
+
+    /**
+     * Destroy loop.
+     *
+     * @return void
+     */
+    public function destroy()
+    {
+
+    }
 }

+ 10 - 0
Events/Select.php

@@ -260,4 +260,14 @@ class Select implements EventInterface
             }
         }
     }
+
+    /**
+     * Destroy loop.
+     *
+     * @return void
+     */
+    public function destroy()
+    {
+
+    }
 }

+ 11 - 3
Protocols/Http.php

@@ -108,6 +108,7 @@ class Http
             'HTTP_CONNECTION'      => '',
             'REMOTE_ADDR'          => '',
             'REMOTE_PORT'          => '0',
+            'REQUEST_TIME'         => time()
         );
 
         // Parse headers.
@@ -437,16 +438,19 @@ class Http
             list($boundary_header_buffer, $boundary_value) = explode("\r\n\r\n", $boundary_data_buffer, 2);
             // Remove \r\n from the end of buffer.
             $boundary_value = substr($boundary_value, 0, -2);
+            $key = -1;
             foreach (explode("\r\n", $boundary_header_buffer) as $item) {
                 list($header_key, $header_value) = explode(": ", $item);
                 $header_key = strtolower($header_key);
                 switch ($header_key) {
                     case "content-disposition":
+                        $key ++;
                         // Is file data.
-                        if (preg_match('/name=".*?"; filename="(.*?)"$/', $header_value, $match)) {
+                        if (preg_match('/name="(.*?)"; filename="(.*?)"$/', $header_value, $match)) {
                             // Parse $_FILES.
-                            $_FILES[] = array(
-                                'file_name' => $match[1],
+                            $_FILES[$key] = array(
+                                'name' => $match[1],
+                                'file_name' => $match[2],
                                 'file_data' => $boundary_value,
                                 'file_size' => strlen($boundary_value),
                             );
@@ -459,6 +463,10 @@ class Http
                             }
                         }
                         break;
+                    case "content-type":
+                        // add file_type
+                        $_FILES[$key]['file_type'] = trim($header_value);
+                        break;
                 }
             }
         }

+ 45 - 21
Worker.php

@@ -33,7 +33,7 @@ class Worker
      *
      * @var string
      */
-    const VERSION = '3.3.9';
+    const VERSION = '3.4.0';
 
     /**
      * Status starting.
@@ -274,6 +274,13 @@ class Worker
     public static $onMasterStop = null;
 
     /**
+     * EventLoopClass
+     *
+     * @var string
+     */
+    public static $eventLoopClass = '';
+
+    /**
      * The PID of master process.
      *
      * @var int
@@ -390,19 +397,11 @@ class Worker
      * @var array
      */
     protected static $_availableEventLoops = array(
-        'libevent',
-        'event',
-        'ev'
+        'libevent' => '\Workerman\Events\Libevent',
+        'event'    => '\Workerman\Events\Event'
     );
 
     /**
-     * Current eventLoop name.
-     *
-     * @var string
-     */
-    protected static $_eventLoopName = 'select';
-
-    /**
      * PHP built-in protocols.
      *
      * @var array
@@ -468,8 +467,10 @@ class Worker
             self::$logFile = __DIR__ . '/../workerman.log';
         }
         $log_file = (string)self::$logFile;
-        touch($log_file);
-        chmod($log_file, 0622);
+        if (!is_file($log_file)) {
+            touch($log_file);
+            chmod($log_file, 0622);
+        }
 
         // State.
         self::$_status = self::STATUS_STARTING;
@@ -848,16 +849,38 @@ class Worker
      */
     protected static function getEventLoopName()
     {
-        if (interface_exists('\React\EventLoop\LoopInterface')) {
-            return 'React';
+        if (self::$eventLoopClass) {
+            return self::$eventLoopClass;
         }
-        foreach (self::$_availableEventLoops as $name) {
+
+        $loop_name = '';
+        foreach (self::$_availableEventLoops as $name=>$class) {
             if (extension_loaded($name)) {
-                self::$_eventLoopName = $name;
+                $loop_name = $name;
                 break;
             }
         }
-        return self::$_eventLoopName;
+
+        if ($loop_name) {
+            if (interface_exists('\React\EventLoop\LoopInterface')) {
+                switch ($loop_name) {
+                    case 'libevent':
+                        self::$eventLoopClass = '\Workerman\Events\React\LibEventLoop';
+                        break;
+                    case 'event':
+                        self::$eventLoopClass = '\Workerman\Events\React\ExtEventLoop';
+                        break;
+                    default :
+                        self::$eventLoopClass = '\Workerman\Events\React\StreamSelectLoop';
+                        break;
+                }
+            } else {
+                self::$eventLoopClass = self::$_availableEventLoops[$loop_name];
+            }
+        } else {
+            self::$eventLoopClass = '\Workerman\Events\Select';
+        }
+        return self::$eventLoopClass;
     }
 
     /**
@@ -1197,6 +1220,7 @@ class Worker
             foreach (self::$_workers as $worker) {
                 $worker->stop();
             }
+            self::$globalEvent->destroy();
             exit(0);
         }
     }
@@ -1210,7 +1234,7 @@ class Worker
     {
         // For master process.
         if (self::$_masterPid === posix_getpid()) {
-            $loadavg = sys_getloadavg();
+            $loadavg = function_exists('sys_getloadavg') ? array_map('round', sys_getloadavg(), array(2)) : array('-', '-', '-');
             file_put_contents(self::$_statisticsFile,
                 "---------------------------------------GLOBAL STATUS--------------------------------------------\n");
             file_put_contents(self::$_statisticsFile,
@@ -1500,8 +1524,8 @@ class Worker
 
         // Create a global event loop.
         if (!self::$globalEvent) {
-            $eventLoopClass    = "\\Workerman\\Events\\" . ucfirst(self::getEventLoopName());
-            self::$globalEvent = new $eventLoopClass;
+            $event_loop_class = self::getEventLoopName();
+            self::$globalEvent = new $event_loop_class;
             // Register a listener to be notified when server socket is ready to read.
             if ($this->_socketName) {
                 if ($this->transport !== 'udp') {