Commits

Ruslan Osmanov committed 7438597

Fix: EventListener cached file descriptor for all connections

Comments (0)

Files changed (5)

classes/listener.c

 		/* Convert the socket created by libevent to PHP stream
 	 	 * and save it's resource ID in l->stream_id */
 
+		/* Always create new resource, since every new connection creates new fd.
+		 * We are in the accept-connection callback now. */
+#if 0
 		if (l->stream_id > 0) {
 			MAKE_STD_ZVAL(arg_fd);
 			ZVAL_RESOURCE(arg_fd, l->stream_id);
 				l->stream_id = -1;
 			}
 		}
+#endif
+		stream = php_stream_fopen_from_fd(fd, "r", NULL);
+		if (stream) {
+			MAKE_STD_ZVAL(arg_fd);
+			php_stream_to_zval(stream, arg_fd);
+			/*zend_list_addref(Z_LVAL_P(arg_fd));*/
+		} else {
+			ALLOC_INIT_ZVAL(arg_fd);
+		}
 		args[1] = &arg_fd;
 
 		MAKE_STD_ZVAL(arg_address);
 
 	PHP_EVENT_COPY_FCALL_INFO(l->fci, l->fcc, &fci, &fcc);
 
-	l->stream_id = -1;
-
 	l->self = zself;
 
 	TSRMLS_SET_CTX(l->thread_ctx);

examples/listener.php

  * 3) start typing. The server should repeat the input.
  */
 
+class MyListenerConnection {
+	private $bev, $base;
+
+	public function __destruct() {
+		$this->bev->free();
+	}
+
+	public function __construct($base, $fd) {
+		$this->base = $base;
+
+		$this->bev = new EventBufferEvent($base, $fd, EventBufferEvent::OPT_CLOSE_ON_FREE);
+
+		$this->bev->setCallbacks(array($this, "echoReadCallback"), NULL,
+			array($this, "echoEventCallback"), NULL);
+
+		if (!$this->bev->enable(Event::READ)) {
+			echo "Failed to enable READ\n";
+			return;
+		}
+	}
+
+	public function echoReadCallback($bev, $ctx) {
+		// Copy all the data from the input buffer to the output buffer
+		
+		// Variant #1
+		$bev->output->addBuffer($bev->input);
+
+		/* Variant #2 */
+		/*
+		$input	= $bev->getInput();
+		$output = $bev->getOutput();
+		$output->addBuffer($input);
+		*/
+	}
+
+	public function echoEventCallback($bev, $events, $ctx) {
+		if ($events & EventBufferEvent::ERROR) {
+			echo "Error from bufferevent\n";
+		}
+
+		if ($events & (EventBufferEvent::EOF | EventBufferEvent::ERROR)) {
+			//$bev->free();
+			$this->__destruct();
+		}
+	}
+}
+
 class MyListener {
 	public $base,
 		$listener,
-		$bev,
 		$socket;
+	private $conn = array();
+
+	public function __destruct() {
+		foreach ($this->conn as &$c) $c = NULL;
+	}
 
 	public function __construct($port) {
 		$this->base = new EventBase();
 			exit(1);
 		}
 		$this->listener = new EventListener($this->base,
-			array($this, "accept_conn_cb"), $this->base,
+			array($this, "acceptConnCallback"), $this->base,
 			EventListener::OPT_CLOSE_ON_FREE | EventListener::OPT_REUSEABLE,
 			-1, $this->socket);
 		 */
 
-//		Variant #2
+		// Variant #2
  		$this->listener = new EventListener($this->base,
- 			array($this, "accept_conn_cb"), $this->base,
+ 			array($this, "acceptConnCallback"), $this->base,
  			EventListener::OPT_CLOSE_ON_FREE | EventListener::OPT_REUSEABLE, -1,
  			"0.0.0.0:$port");
 
 	}
 
 	// This callback is invoked when there is data to read on $bev
-	public function echo_read_cb($bev, $ctx) {
-		// Copy all the data from the input buffer to the output buffer
-		
-		// Variant #1
-		$bev->output->addBuffer($bev->input);
-
-		/* Variant #2 */
-		/*
-		$input	= $bev->getInput();
-		$output = $bev->getOutput();
-		$output->addBuffer($input);
-		*/
-	}
-
-	public function echo_event_cb($bev, $events, $ctx) {
-		if ($events & EventBufferEvent::ERROR)
-			echo "Error from bufferevent\n";
-
-		if ($events & (EventBufferEvent::EOF | EventBufferEvent::ERROR)) {
-			$bev->free();
-		}
-	}
-
-	public function accept_conn_cb($listener, $fd, $address, $ctx) {
-		/* We got a new connection! Set up a bufferevent for it. */
-		//$base = $ctx;
-		//$base = $listener->getBase();
+	public function acceptConnCallback($listener, $fd, $address, $ctx) {
+		// We got a new connection! Set up a bufferevent for it. */
 		$base = $this->base;
-
-		$this->bev = new EventBufferEvent($base, $fd, EventBufferEvent::OPT_CLOSE_ON_FREE);
-
-		$this->bev->setCallbacks(array($this, "echo_read_cb"), NULL, array($this, "echo_event_cb"), NULL);
-
-		if (!$this->bev->enable(Event::READ | Event::WRITE)) {
-			echo "Failed to enable READ | WRITE\n";
-			exit();
-		}
+		$this->conn[] = new MyListenerConnection($base, $fd);
 	}
 
 	public function accept_error_cb($listener, $ctx) {
-		//$base = $listener->getBase();
 		$base = $this->base;
 
 		fprintf(STDERR, "Got an error %d (%s) on the listener. "
 	$port = (int) $argv[1];
 }
 if ($port <= 0 || $port > 65535) {
-	puts("Invalid port");
-	return 1;
+	exit("Invalid port");
 }
 
 $l = new MyListener($port);
     <email>osmanov@php.net</email>
     <active>yes</active>
   </lead>
-  <date>2013-02-22</date>
+  <date>2013-02-23</date>
   <!--{{{ Current version -->
   <version>
     <release>1.2.5</release>
   <notes><![CDATA[
   Fix: redundant Z_ADDREF_P() calls in EventListener, EventBufferEvent constructors and factory methods
   Change: EventBufferEvent enable/disable methods return bool now
+  Fix: EventListener cached file descriptor for all connections
   ]]></notes>
   <!--}}}-->
   <!--{{{ Contents -->
   <notes><![CDATA[
   Fix: redundant Z_ADDREF_P() calls in EventListener, EventBufferEvent constructors and factory methods
   Change: EventBufferEvent enable/disable methods return bool now
+  Fix: EventListener cached file descriptor for all connections
   ]]></notes>
   <!--}}}-->
   <!--{{{ 1.2.4-alpha -->
 
 	PHP_EVENT_ASSERT(l);
 
-	if (l->stream_id >= 0) {
-		zend_list_delete(l->stream_id);
-	}
-
 	if (l->data) {
 		zval_ptr_dtor(&l->data);
 	}
 	PHP_EVENT_OBJECT_HEAD;
 
 	struct evconnlistener *listener;
-	int                    stream_id;   /* Resource ID of the file descriptor. -1 if none */
 	zval                  *self;        /* Object itself. For callbacks              */
 	zval                  *data;        /* User custom data passed to callback       */
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.