ID: 33063
User updated by: arendjr at gmail dot com
Reported By: arendjr at gmail dot com
-Status: Feedback
+Status: Open
Bug Type: Reproducible crash
Operating System: Linux
PHP Version: 5.0.3
New Comment:
Okay, it took some effort, by I created 3 new test cases. The longest
one, the one with the crash, is 47 lines (including whitespace) and has
no includes. I got also two workarounds, the first removes the unused
references to $rootWidget after which the problem disappears. The
second one again no longer uses a function to populate the document,
after which it works again. I hope this helps.
http://www.liacs.nl/~dvbeelen/php5crash/crash.php.txt
http://www.liacs.nl/~dvbeelen/php5crash/crash-workaround1.php.txt
http://www.liacs.nl/~dvbeelen/php5crash/crash-workaround2.php.txt
Previous Comments:
------------------------------------------------------------------------
[2005-05-19 16:14:38] derick@php.net
Then you need to try a bit harder creating a shorter reproducable
script.... really.
------------------------------------------------------------------------
[2005-05-19 14:27:01] arendjr at gmail dot com
Okay, but beware that including WebPage.php will include a total of 10
files. I created a simple tarball which you can untar, enter the
directory and run 'php5 index.php'. I stripped as much as I could while
still letting my code function. I left the API docs in as it might help
you to understand the code better ;)
The most important file is base/Widgets.php. If you replace it with
base/Widgets.php.safe, the crash will no longer occur as it contains a
workaround by explicitly holding references to child widgets.
index.php contains the first testcase plus a set_include_path() to get
everything to work.
You can download the tarball from
www.liacs.nl/~dvbeelen/php5crash/aukyla2-bugreport.tar.gz
------------------------------------------------------------------------
[2005-05-19 12:31:11] derick@php.net
Thank you for this bug report. To properly diagnose the problem, we
need a short but complete example script to be able to reproduce
this bug ourselves.
A proper reproducing script starts with <?php and ends with ?>,
is max. 10-20 lines long and does not require any external
resources such as databases, etc.
If possible, make the script source available online and provide
an URL to it here. Try to avoid embedding huge scripts into the report.
we miss your WebPage class include file
------------------------------------------------------------------------
[2005-05-19 11:27:14] arend at auton dot nl
Sorry, the URL's in the testcases should all have .txt
appended, so:
http://www.liacs.nl/~dvbeelen/php5crash/works.php.txt
http://www.liacs.nl/~dvbeelen/php5crash/crash.php.txt
http://www.liacs.nl/~dvbeelen/php5crash/corruption.php.txt
http://www.liacs.nl/~dvbeelen/php5crash/works2.php.txt
------------------------------------------------------------------------
[2005-05-19 11:22:54] arendjr at gmail dot com
Description:
------------
I'm building a rather complicated framework which includes
big inheritance trees and multiple factories operating on
each other. I'm still using PHP 5.0.3 (with SUSE patches)
and I'm not able to compile PHP 5.0.4 at the moment, so I
hope I'm not reporting a problem already solved, at least
I can't find the problem in the PHP 5.0.4 Changelog. If
necessary, I can compile PHP 5.0.4 later do dig deeper
into the problem.
The problem is when I'm running some code using this
framework I'm getting some nasty crashes and memory
corruptions under certain conditions. Now my own code
might not be perfect yet either, but with a crashing PHP
is rather difficult to track where the problem is. I
created 4 test cases which show the problem.
First I have some working code which does what it should
do. Then I try to move some code to a function so it can
be re-used later, but suddenly PHP crashes when the code
is in a function. Then I strip away 2 lines of code,
causing PHP to run, but exit with a memory corruption
reported by glibc. Finally, if I strip 3 more lines, there
are no more problems again.
Now, just while I was writing this report I think I might
know where the problem is. My whole framework is built on
an advanced Widget model. This has some very important
base classes and interfaces:
interface IWidget;
class Widget extends DOMElement implements IWidget;
class TextWidget extends DOMText implements IWidget;
class RootWidget extends DOMDocument implements IWidget;
class RootWidgetContainer implements IWidget;
the objects which are created in the test cases are:
class WebPage extends RootWidgetContainer;
and under the hood (through the factories):
class XHTML_RootWidget extends RootWidget;
class XHTML_Table extends Table;
class XHTML_TableRow extends TableRow;
class XHTML_TableCell extends TableCell;
class XHTML_Label extends Label;
class XHTML_Text_Style extends XHTML_Style;
where:
class Table extends Widget;
class TableRow extends Widget;
class TableCell extends Widget;
class Label extends TextWidget;
class XHTML_Style extends Style;
So, that's basically how the whole inheritance for this
small example works. It's pretty complicated but allows me
to use the same code to create all kinds of output
documents (for example, doing a "s/WebPage/Spreadsheet/g"
on the first testcase gives creates an OpenDocument
Spreadsheet and sends it to the user's browser).
Now, where do I think the problem is? Widget inherits
DOMElement. And then I add new widgets to this DOMElement.
But I do not keep references to these objects, because
DOMElement already has the firstChild and nextSibling
properties, so I should be able to access child widgets
through this property. So somehow I guess the objects are
destroyed by the garbage collector when the function in
testcases 2 through 4 exits (even though the DOMElement
still contain references to them). In fact, adding an
array childWidgets to the classes Widget and RootWidget
where I keep references to the child widgets myself
entirely avoids the crash in all testcases. So, I think
when a child is added to a DOMNode, the garbage collector
should know there's a reference to the child in that node
so it does not get destroyed too soon.
If you want I can send you the other code of the
framework, but right now I don't think throwing in a few
thousand lines of code here would really help :)
Reproduce code:
---------------
See the 4 testcases:
http://www.liacs.nl/~dvbeelen/php5crash/works.php
http://www.liacs.nl/~dvbeelen/php5crash/crash.php
http://www.liacs.nl/~dvbeelen/php5crash/corruption.php
http://www.liacs.nl/~dvbeelen/php5crash/works2.php
Expected result:
----------------
A Widget tree with an internal DOM tree should be built
and shown.
Actual result:
--------------
Using testcase 2, PHP will crash with the following
backtrace:
#0 0x081402e3 in zend_std_object_get_class_name ()
#1 0x081570e9 in zend_init_method_call_handler ()
#2 0x08160978 in execute ()
#3 0x081577fc in zend_do_fcall_common_helper ()
#4 0x08160978 in execute ()
#5 0x08153094 in zend_include_or_eval_handler ()
#6 0x08160978 in execute ()
#7 0x0812c62c in zend_execute_scripts ()
#8 0x080f54dd in php_execute_script ()
#9 0x08161ecd in main ()
With testcase 3, PHP will run, but exit with the following
message:
*** glibc detected *** double free or corruption (out):
0x0827a260 ***
Aborted
------------------------------------------------------------------------
--
Edit this bug report at http://bugs.php.net/?id=33063&edit=1