We've been having a problem with some method calls failing mysteriously on the servers, which seems worse under PHP 5 with the APC opcode cache.
Tim's filed a bug report here, which has got some feedback likening it to a known problem with mixed early binding and late binding:
http://pecl.php.net/bugs/bug.php?id=6503
Since the PHP documentation doesn't cover this early / late binding issue at all, I want to make sure we actually know what it is. :)
Poking about I found this commit notice which has some relatively clear explanations: http://news.php.net/php.pecl.cvs/4288
As I understand it, the problem is situations like this...
A.php: class A { ... }
B.php: require_once 'A.php' class B extends A { ... }
Early-binding scenario: require_once 'A.php'; require_once 'B.php'; // A is already defined when *compiling* B
Late-binding scenario: require_once 'B.php'; // A is loaded only when B is *run*
The Zend bytecode compiler emits different code depending on whether the base class was known at compile time, so APC's caching can get confused when you pop back and forth between these cases.
Our problem is that whether A or B (or C or D) gets loaded is a runtime decision, and the code that loads one or the other doesn't know about B's dependencies.
The cases where this seems to frequently come up are: * Localization handlers, where we have some classes inherit code from a similar language or variant ("LanguageZh_tw extends LanguageZh") * Skins, where some are slight variants on a base skin
One possible quickie workaround is to toss in another include which loads the depdendencies that aren't guaranteed to be preloaded, and hit it first:
LanguageZh_tw.php: require_once 'LanguageZh.php'; class LanguageZh_tw extends LanguageZh { ... }
LanguageZh_tw.deps.php: require_once 'LanguageUtf8.php'; require_once 'LanguageZh.php';
Setup.php: ... wfSuppressWarnings(); include_once("$IP/languages/$wgLangClass.deps.php"); include_once("$IP/languages/$wgLangClass.php"); wfRestoreWarnings(); ...
Still wrapping my head around this issue, but I think this makes some kind of sense...
-- brion vibber (brion @ pobox.com)
Brion Vibber wrote:
The Zend bytecode compiler emits different code depending on whether the base class was known at compile time, so APC's caching can get confused when you pop back and forth between these cases.
[snip]
One possible quickie workaround is to toss in another include which loads the depdendencies that aren't guaranteed to be preloaded, and hit it first:
I've added these for the skin and language files that have extra dependencies. Hopefully that'll be the last we see of these errors in the logs...
-- brion vibber (brion @ pobox.com)
wikitech-l@lists.wikimedia.org