2011/3/16 Tim Starling <tstarl...@wikimedia.org>

> This is a followup to http://bugs.php.net/bug.php?id=54157 . Johannes
> said I should post here.
>
> In the course of my MediaWiki development work, I hit a strange issue
> involving session_set_save_handler().
>
> PHP's built-in session handler is pretty much useless when you have
> more than one server serving a given site, so
> session_set_save_handler() is essential. MediaWiki has a feature
> allowing it to save sessions via its memcached client. A suitable
> client object is put in $wgMemc during setup, which is used when the
> session is closed. A minor change to the way this variable was
> initialised caused it to disappear from the global symbol table before
> the session save handler was called.
>
> This turned out to be due to a broken algorithm in
> shutdown_destructors() in zend_execute_API.c. The algorithm basically
> does this:
>
> 1. Delete all objects from the global symbol table which have a zval
> reference count of 1
> 2. If any objects were deleted, go to step 1.
>
> Obviously the intention is to first delete the references, and then to
> delete the objects which were referred to. It doesn't work that way:
> if you have a reference, both symbol table entries point to the same
> zval, so they both have a reference count of 2, so the algorithm skips
> both and leaves them intact for RSHUTDOWN. My $wgMemc initialisation
> change caused the reference count to drop from 2 to 1, so the variable
> was deleted.
>
> Fixing this function to correctly delete all objects from the global
> symbol table would be easy enough (against 5.3):
>
> http://tstarling.com/stuff/shutdown_destructors-sanity.patch
>
> But please don't apply that, because it would break all released
> versions of MediaWiki.
>
> We now come to the next strange thing about this code: why is it
> attempting to delete all objects from the global symbol table anyway?
> There are plenty of other ways to store objects: function static
> variables, class static variables, etc. Deleting them from $GLOBALS
> doesn't stop them from being accessed. And besides, we know that
> there's no problem with accessing an object after __destruct() has
> been called on it, because that was the whole point of splitting out
> shutdown_destructors() in the first place, as a comment in
> shutdown_executor() explains:
>
> /* Removed because this can not be safely done, e.g. in this situation:
>   Object 1 creates object 2
>   Object 3 holds reference to object 2.
>   Now when 1 and 2 are destroyed, 3 can still access 2 in its
> destructor, with
>   very problematic results */
> /*         zend_objects_store_call_destructors(&EG(objects_store)
> TSRMLS_CC); */
>
> Just removing the whole loop would suit me, as a 5.3.x stopgap measure:
>
> http://tstarling.com/stuff/no-global-deletion.patch
>
> But that still leaves the problem that the session save handler is
> called in the strange and scary world of half-shut-down PHP. We don't
> know what RSHUTDOWN functions have been called before the session
> RSHUTDOWN, so we don't know what userspace code will work and what
> won't. A workaround is easy enough:
>
> http://www.mediawiki.org/wiki/Special:Code/MediaWiki/83147
>
> but I thought I would be a good open source citizen and come up with a
> proper solution, against trunk. It is attached and at:
>
> http://tstarling.com/stuff/session-pre-deactivate.patch
>
> The idea is to introduce a pre-RSHUTDOWN hook, allowing modules to
> call user code in a relatively sane environment. It's implemented in a
> way that is closely analogous to the post-deactivate hook. I had
> trouble testing it because trunk was so broken that it wouldn't run
> MediaWiki, but the patch appears to work for simple CLI test cases.
>
> -- Tim Starling
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>

Hi.

Could you please also open a ticket in the bug tracker?
thanks

Tyrael

Reply via email to