Re: libevent wrapper
| From: | Arnaud Le Blanc | Date: | Fri, 28 Nov 2008 10:07:41 +0000 |
| Subject: | Re: libevent wrapper | ||
| References: | 1 2 3 | Groups: | php.pecl.dev |
| Request: | Send a blank email to pecl-dev+get-5932@lists.php.net to get a copy of this message | ||
On Friday 28 November 2008 09:57:02 Antony Dovgal wrote:
> On 28.11.2008 09:59, Arnaud Le Blanc wrote:
> > I just found a problem when an event resource is deleted while the
callback is
> > called (event_free() allows that).
>
> Right, that's exactly why I do zend_list_addref(event->rsrc_id);
Yes, but event_free() does zend_list_destroy(event->rsrc_id).
Actually I experienced this problem with a buffer event.
Say you have something like this:
my_bufferevent_write_callback($buffev_resource, $myarg) {
if ($some_condition) {
event_buffer_free($event);
}
}
This decrements the refcount of the resource, and in my test script the
resource was then destroyed in _php_bufferevent_writecb on the line
"zval_ptr_dtor(&(args[0]));"
See [1] for a reproduce script (with USE_ZEND_ALLOC=0 valgrind shows the
problem).
[1] http://arnaud.lb.s3.amazonaws.com/reproduce1227866439.php
>
> > It is possible to change the internal
> > callback functions so that they do not need to use the the possibly freed
> > memory after the call. This also makes them simpler by not attempting to
avoid
> > freeing the resources. The same problem applies for buffer and loop
resources.
> > I made a patch for that [1]
>
> I'm afraid I don't understand a half of it.
See the patch on the "_php_bufferevent_writecb" chunk. Basically the change is
that the function will never [need to] read bevent after call_user_function().
It also removes all attempts to avoid the destruction of the resources (base
and the buffer event itself) as this is not anymore needed.
>
> >(for loops I had to add a counter of attached
> > events and to fail in event_base_free() when the counter is > 0).
>
> I don't think it's correct - each event does zend_list_addref() for the base
> when the base is set and zend_list_delete() when the event is destroyed, so
base
> should have refcount == 1 after all events are destroyed.
Except if you do event_base_free($base) ;) The refcount prevents PHP from
feeing the resource. The counter I added prevents the user from artificially
decrementing the refcount when the loop base has events attached to it.
Regards,
Arnaud