- edited description
Socket fd was inexplicable to delete
event.php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($socket, "192.168.6.20", 9090);
socket_listen($socket, 1024);
$base = new EventBase();
$event = new Event($base, $socket, Event::READ|Event::PERSIST, function ($socket) use($base){
$client = socket_accept($socket);
$event = new Event($base, $client, Event::READ|Event::PERSIST, function ($socket){
var_dump($socket);
});
$event->add();
});
$event->add();
$base->loop( EventBase::EPOLL_USE_CHANGELIST )
server : strace php event.php
client : nc 192.168.6.20 9090
socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 3
setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
bind(3, {sa_family=AF_INET, sin_port=htons(9090), sin_addr=inet_addr("192.168.6.20")}, 16) = 0
listen(3, 1024) = 0
........................
........................
epoll_ctl(4, EPOLL_CTL_ADD, 3, {EPOLLIN, {u32=3, u64=3}}) = 0
epoll_wait(4, {{EPOLLIN, {u32=3, u64=3}}}, 32, -1) = 1
gettimeofday({1502611043, 724745}, NULL) = 0
accept(3, {sa_family=AF_INET, sin_port=htons(18060), sin_addr=inet_addr("192.168.6.20")}, [16]) = 7
epoll_ctl(4, EPOLL_CTL_ADD, 7, {EPOLLIN, {u32=7, u64=7}}) = 0
//is closed
close(7) = 0
//is removed
epoll_ctl(4, EPOLL_CTL_DEL, 7, {EPOLLIN, {u32=7, u64=7}}) = -1 EBADF (Bad file descriptor)
event Extension version 2.3.0
libevent2 headers version 2.1.8-stable
php -v
PHP 7.0.7 (cli) (built: Aug 11 2017 12:30:13) ( ZTS ) Copyright (c) 1997-2016 The PHP Group Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
Comments (6)
-
reporter -
reporter - edited description
-
repo owner - changed status to invalid
If you mean that the client connection should not be closed, then this is not a bug.
The problem with your code is that the
$client
variable is destroyed when the scope of the anonymous function ends (as any other local variable). Hence, the underlying file descriptor is closed. You should keep references to the client sockets (file descriptors) until one of the following events occurs:- the event loop finishes its work;
- the client closes connection;
- you intentionally close the client's connection.
The
$event
variable's lifetime is not different from any other PHP variable. It is destroyed at the end of the scope by garbage collector, since there are no more references to this variable. WhenEvent
object is destroyed, the object is removed from the event loop as well.Here is a simple example for clarity:
class ClientConnections { private $sockets = [], $events = []; function push($socket, Event $event) { $this->sockets[] = $socket; $this->events[] = $event; } } $connections = new ClientConnections; $event = new Event($base, $socket, Event::READ|Event::PERSIST, function ($socket) use($base, $connections) { $client = socket_accept($socket); $event = new Event($base, $client, Event::READ|Event::PERSIST, function ($socket) { var_dump($socket); }); $event->add(); $connections->push($client, $event); }
-
repo owner - changed status to closed
-
repo owner - changed status to invalid
-
reporter I thought about the problem before, so I tried to store the event. But the event is still deleted, your method is right. Fd and event need to be stored.
thank you very much
- Log in to comment