Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- /**
- * Run this script as-is and it will segfault. My setup is Ubuntu
- * 11.10, library details:
- *
- * php5-cli : 5.3.6-13ubuntu3.6 (output from dpkg -l)
- * libevent : 0.0.5 beta (output from pecl list)
- * php-pear : 5.3.6-13ubuntu3.6 (output from dpkg -l)
- *
- * There are 2 things you can do to stop the segfault:
- *
- * 1. Comment out the given line in ELoop->checkAddEvent()
- * 2. Only add a single client to the loop
- */
- class ELoop
- {
- private $evBase;
- private $clients = array();
- function addClient ($client) {
- $this->clients[] = $client;
- }
- function loop () {
- $this->initLibevent();
- $hasWork = false;
- foreach ($this->clients as $c) {
- if ($ev = $this->checkAddEvent($c)) {
- $hasWork = true;
- }
- }
- if ($hasWork) {
- event_base_loop($this->evBase);
- }
- }
- private function checkAddEvent ($c, $ev=null) {
- $flags = 0;
- if ($c->canRead())
- $flags = $flags | EV_READ;
- if ($c->canWrite())
- $flags = $flags | EV_WRITE;
- if (! $flags) {
- if ($ev) {
- event_del($ev);
- event_free($ev); // Comment this line and the segfault doesn't happen
- }
- if (false === ($i = array_search($c, $this->clients))) {
- throw new \Exception("Failed to locate client within local collection during removal", 9062);
- } else {
- unset($this->clients[$i]);
- }
- return;
- }
- if (! $ev)
- $ev = event_new();
- event_set($ev, $c->getSocketHandle(), $flags, array($this, 'loopEventDispatch'), array($c, $ev));
- event_base_set($ev, $this->evBase);
- event_add($ev);
- return $ev;
- }
- function loopEventDispatch ($fd, $events, $params) {
- list($client, $event) = $params;
- if ($events & EV_READ)
- $client->read();
- if ($events & EV_WRITE)
- $client->write();
- $this->checkAddEvent($client, $event);
- }
- private function initLibevent () {
- $this->evBase = event_base_new();
- }
- }
- class SocketClient
- {
- private $host, $port, $sock;
- function open ($host, $port) {
- $this->host = $host;
- $this->port = $port;
- if (! ($this->sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP))) {
- throw new \Exception("Failed to create inet socket", 7895);
- } else if (! socket_connect($this->sock, $this->host, $this->port)) {
- throw new \Exception("Failed to connect inet socket ({$this->host}, {$this->port})", 7564);
- } else if (! socket_set_nonblock($this->sock)) {
- throw new \Exception("Failed to switch connection in to non-blocking mode.", 2357);
- }
- }
- function getSocketHandle () {
- return $this->sock;
- }
- function read () {
- $buff = '';
- while (@socket_recv($this->sock, $tmp, 4096, MSG_DONTWAIT)) {
- $buff .= $tmp;
- }
- return $buff;
- }
- function write ($buff='') {
- if (($tmp = socket_write($this->sock, $buff)) === false) {
- throw new \Exception(sprintf("Socket write failed: %s",
- socket_strerror(socket_last_error($this->sock))), 7854);
- }
- }
- }
- class HttpClient extends SocketClient
- {
- private $state = 0, $domain;
- function __construct ($domain) {
- $ip = gethostbyname($domain);
- if ($ip == $domain) {
- throw new \Exception("Failed to resolve HTTP host", 2351);
- }
- $this->open($ip, 80);
- $this->domain = $domain;
- }
- function canRead () {
- switch ($this->state) {
- case 1:
- return true;
- default:
- return false;
- }
- }
- function canWrite () {
- switch ($this->state) {
- case 0:
- return true;
- default:
- return false;
- }
- }
- function read () {
- $this->state = 2;
- $buff = parent::read();
- printf("[http] Reads response (%d):\n%s\n", strlen($buff), substr($buff, 0, strpos($buff, "\r\n")));
- }
- function write ($buff='') {
- if ($this->state == 0) {
- // Write HTTP header.
- parent::write("GET / HTTP/1.1\r\nHost: {$this->domain}\r\n" .
- "Connection: close\r\n" .
- "User-Agent: php libevent test\r\n" .
- "Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7\r\n" .
- "Cache-Control: no-cache\r\n" .
- "Accept-Language: de,en;q=0.7,en-us;q=0.3\r\n\r\n");
- $this->state = 1;
- }
- }
- }
- $el = new ELoop;
- $el->addClient(new HttpClient('microsoft.com'));
- $el->addClient(new HttpClient('bluelines.org'));
- $el->loop();
Add Comment
Please, Sign In to add comment