#1039: Work around random XPath result set corruption bugs in certain libxml
versions
----------------------+-----------------------------------------------------
Reporter: david | Owner: david
Type: defect | Status: assigned
Priority: normal | Milestone: 1.0
Component: config | Version: 1.0.0beta1
Severity: critical | Keywords:
Has_patch: 0 |
----------------------+-----------------------------------------------------
Description changed by david:
Old description:
> Affected libxml versions: at least up to and including 2.6.26.
>
> It is random, not really reproducible. Just happens after a bunch of
> requests.
>
> One of the affected handlers is {{{AgaviLoggingConfigHandler}}}: in
> {{{logging.xml}}}, {{{<appender>}}} elements occur directly inside
> {{{<configuration>}}}, and also inside {{{<logger>}}} elements.
>
> The code does:
> {{{
> foreach($cfg->get('loggers') as $logger) {
> }}}
> which, in turn, will run this XPath (namespace URIs omitted for brevity):
> {{{
> child::*[local-name() = "logger" and namespace-uri() = "..."] | child
> ::*[local-name() = "loggers" and namespace-uri() = "..."]/*[local-name()
> = "logger" and namespace-uri() = "..."]
> }}}
> This xpath is run on the given element, in our case, that's {{{$cfg}}},
> the {{{<configuration> element. The {{{child}}} axis retrieves only
> direct children of an element, not other descendants.
>
> Yet, sometimes (in around 1 out of 10 to 20 times),
> {{{<appender>}}} elements from inside {{{<logger>}}} will be in the
> result set:
> {{{
> #!xml
> <?xml version="1.0" encoding="UTF-8"?>
> <configurations xmlns="http://agavi.org/agavi/1.0/config">
> <configuration>
> <loggers default="debug">
> <logger name="debug" class="AgaviLogger"
> level="AgaviLogger::ALL">
> <appenders>
> <appender>DebugLogAppender</appender>
> </appenders>
> </logger>
> </loggers>
> <appenders>
> <appender name="DebugLogAppender"
> class="AgaviRotatingFileLoggerAppender" layout="DateTimeLayout">
> <parameters>
> <parameter
> name="dir">%core.app_dir%/log/</parameter>
> <parameter
> name="prefix">debug-</parameter>
> </parameters>
> </appender>
> </appenders>
> <layouts>
> <layout name="DateTimeLayout"
> class="AgaviTimestampLoggerLayout" />
> </layouts>
> </configuration>
> </configurations>
> }}}
> is then compiled to:
> {{{
> #!php
> <?php
> ${'_layout_DateTimeLayout'} = new AgaviTimestampLoggerLayout();
> ${'_layout_DateTimeLayout'}->initialize($this->context, array (
> ));
> ${'_appender_'} = new ();
> ${'_appender_'}->initialize($this->context, array (
> ));
> ${'_appender_'}->setLayout(${'_layout_'});
> ${'_appender_DebugLogAppender'} = new AgaviRotatingFileLoggerAppender();
> ${'_appender_DebugLogAppender'}->initialize($this->context, array (
> 'dir' => 'D:\\workspace\\Kauppapaikka\\app/log/',
> 'prefix' => 'debug-',
> ));
> ${'_appender_DebugLogAppender'}->setLayout(${'_layout_DateTimeLayout'});
> ${'_logger_debug'} = new AgaviLogger();
> ${'_logger_debug'}->setAppender('DebugLogAppender',
> ${'_appender_DebugLogAppender'});
> ${'_logger_debug'}->setAppender('AdtRequestLogAppender',
> ${'_appender_AdtRequestLogAppender'});
> ${'_logger_debug'}->setLevel(AgaviLogger::ALL);
> $this->setLogger('debug', ${'_logger_debug'});
> $this->setDefaultLoggerName('debug');
> }}}
>
> Some debugging clearly proved that this happens because the node set from
> the {{{$cfg->get('loggers')}}} call contains
> {{{<appender>DebugLogAppender</appender>}}} from the {{{<logger>}}}.
>
> In a similar case, {{{<parameter>}}}s sometimes get messed up:
> {{{
> #!xml
> <filter class="AdtDebugFirePhpFilter" enabled="true" >
> <ae:parameter name="datasources">
> <!-- Propel query logging -->
> <ae:parameter>
> <ae:parameter
> name="class">AdtPropelDataSource</ae:parameter>
> <ae:parameter name="parameters">
> </ae:parameter>
> </ae:parameter>
> <!-- Simple action execution timer-->
> <ae:parameter>
> <ae:parameter
> name="class">AdtActionTimerDataSource</ae:parameter>
> </ae:parameter>
> </ae:parameter>
> </filter>
> }}}
> compiles to
> {{{
> #!php
> <?php
> $filter = new AdtDebugFirePhpFilter();
> $filter->initialize($this->context, array (
> 'datasources' =>
> array (
> 0 =>
> array (
> 'class' => 'AdtPropelDataSource',
> 'parameters' => '',
> ),
> 'class' => 'AdtActionTimerDataSource',
> 'parameters' => '',
> 1 =>
> array (
> 'class' => 'AdtActionTimerDataSource',
> ),
> ),
> 0 =>
> array (
> 'class' => 'AdtPropelDataSource',
> 'parameters' => '',
> ),
> 'class' => 'AdtActionTimerDataSource',
> 'parameters' => '',
> 1 =>
> array (
> 'class' => 'AdtActionTimerDataSource',
> ),
> ));
> $filters[] = $filter;
> }}}
New description:
Affected libxml versions: at least up to and including 2.6.26.
It is random, not really reproducible. Just happens after a bunch of
requests.
One of the affected handlers is {{{AgaviLoggingConfigHandler}}}: in
{{{logging.xml}}}, {{{<appender>}}} elements occur directly inside
{{{<configuration>}}}, and also inside {{{<logger>}}} elements.
The code does:
{{{
foreach($cfg->get('loggers') as $logger) {
}}}
which, in turn, will run this XPath (namespace URIs omitted for brevity):
{{{
child::*[local-name() = "logger" and namespace-uri() = "..."] | child
::*[local-name() = "loggers" and namespace-uri() = "..."]/*[local-name() =
"logger" and namespace-uri() = "..."]
}}}
This xpath is run on the given element, in our case, that's {{{$cfg}}},
the {{{<configuration>}}} element. The {{{child}}} axis retrieves only
direct children of an element, not other descendants.
Yet, sometimes (in around 1 out of 10 to 20 times),
{{{<appender>}}} elements from inside {{{<logger>}}} will be in the result
set:
{{{
#!xml
<?xml version="1.0" encoding="UTF-8"?>
<configurations xmlns="http://agavi.org/agavi/1.0/config">
<configuration>
<loggers default="debug">
<logger name="debug" class="AgaviLogger"
level="AgaviLogger::ALL">
<appenders>
<appender>DebugLogAppender</appender>
</appenders>
</logger>
</loggers>
<appenders>
<appender name="DebugLogAppender"
class="AgaviRotatingFileLoggerAppender" layout="DateTimeLayout">
<parameters>
<parameter
name="dir">%core.app_dir%/log/</parameter>
<parameter
name="prefix">debug-</parameter>
</parameters>
</appender>
</appenders>
<layouts>
<layout name="DateTimeLayout"
class="AgaviTimestampLoggerLayout" />
</layouts>
</configuration>
</configurations>
}}}
is then compiled to:
{{{
#!php
<?php
${'_layout_DateTimeLayout'} = new AgaviTimestampLoggerLayout();
${'_layout_DateTimeLayout'}->initialize($this->context, array (
));
${'_appender_'} = new ();
${'_appender_'}->initialize($this->context, array (
));
${'_appender_'}->setLayout(${'_layout_'});
${'_appender_DebugLogAppender'} = new AgaviRotatingFileLoggerAppender();
${'_appender_DebugLogAppender'}->initialize($this->context, array (
'dir' => 'D:\\workspace\\Kauppapaikka\\app/log/',
'prefix' => 'debug-',
));
${'_appender_DebugLogAppender'}->setLayout(${'_layout_DateTimeLayout'});
${'_logger_debug'} = new AgaviLogger();
${'_logger_debug'}->setAppender('DebugLogAppender',
${'_appender_DebugLogAppender'});
${'_logger_debug'}->setAppender('AdtRequestLogAppender',
${'_appender_AdtRequestLogAppender'});
${'_logger_debug'}->setLevel(AgaviLogger::ALL);
$this->setLogger('debug', ${'_logger_debug'});
$this->setDefaultLoggerName('debug');
}}}
Some debugging clearly proved that this happens because the node set from
the {{{$cfg->get('loggers')}}} call contains
{{{<appender>DebugLogAppender</appender>}}} from the {{{<logger>}}}.
In a similar case, {{{<parameter>}}}s sometimes get messed up:
{{{
#!xml
<filter class="AdtDebugFirePhpFilter" enabled="true" >
<ae:parameter name="datasources">
<!-- Propel query logging -->
<ae:parameter>
<ae:parameter
name="class">AdtPropelDataSource</ae:parameter>
<ae:parameter name="parameters">
</ae:parameter>
</ae:parameter>
<!-- Simple action execution timer-->
<ae:parameter>
<ae:parameter
name="class">AdtActionTimerDataSource</ae:parameter>
</ae:parameter>
</ae:parameter>
</filter>
}}}
compiles to
{{{
#!php
<?php
$filter = new AdtDebugFirePhpFilter();
$filter->initialize($this->context, array (
'datasources' =>
array (
0 =>
array (
'class' => 'AdtPropelDataSource',
'parameters' => '',
),
'class' => 'AdtActionTimerDataSource',
'parameters' => '',
1 =>
array (
'class' => 'AdtActionTimerDataSource',
),
),
0 =>
array (
'class' => 'AdtPropelDataSource',
'parameters' => '',
),
'class' => 'AdtActionTimerDataSource',
'parameters' => '',
1 =>
array (
'class' => 'AdtActionTimerDataSource',
),
));
$filters[] = $filter;
}}}
--
--
Ticket URL: <http://trac.agavi.org/ticket/1039#comment:3>
Agavi <http://www.agavi.org/>
An MVC Framework for PHP5
_______________________________________________
Agavi Tickets Mailing List
[email protected]
http://lists.agavi.org/mailman/listinfo/tickets