#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>}}}.

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:2>
Agavi <http://www.agavi.org/>
An MVC Framework for PHP5


_______________________________________________
Agavi Tickets Mailing List
[email protected]
http://lists.agavi.org/mailman/listinfo/tickets

Reply via email to