We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 4018
    • 1,131 Posts
    I’m having massive problems with AjaxSearch on a client site. Seems that it is causing multiple segmentation faults whenever a search is attempted. Here’s an example of the errors:

    [Wed May 27 08:45:44 2009] [notice] child pid 16721 exit signal Segmentation fault (11)
    [Wed May 27 08:45:51 2009] [notice] child pid 16724 exit signal Segmentation fault (11)

    FYI, the problem occurs even on a normal results page. I’m at a loss as to what is causing this. Any ideas? Could it be due to an encoding issue with some of the documents?
      Jeff Whitfield

      "I like my coffee hot and strong, like I like my women, hot and strong... with a spoon in them."
      • 4018
      • 1,131 Posts
      Oh, and here is the environment I’m in:

      MODx Evolution 1.0.0 (from SVN)
      AjaxSearch 1.8.2b
      PHP 5.2.9
      Apache 2.2.10
      MySQL 5.0.67

      Note: The problem occurs even in the latest MODx 0.9.6.x release so it’s agnostic of any particular version of MODx. Seems isolated to just AjaxSearch.
        Jeff Whitfield

        "I like my coffee hot and strong, like I like my women, hot and strong... with a spoon in them."
        • 5811
        • 1,717 Posts
        I’m having massive problems with AjaxSearch on a client site
        Is it a new site ? Have you done some tests with the previous 1.8.1 version ? Have you the same issue or not ?

          • 4018
          • 1,131 Posts
          Thanks to one of my partners analysis of the segfault, I narrowed it down to a number of things. There are a number of problems in the search.class.inc.php file.

          For starters, the following function was causing the initial segfaults:

          /**
           *  validListIDs : check the validity of a value separated list of Ids
           */
            function validListIDs($IDs){
              if (preg_match('/^([0-9]+,)*[0-9]+$/',$IDs) == 0) return false;
              return true;
            }
          


          If I commented out the preg_match line then the error goes away. However, I started having some SQL errors after that. Further investigation revealed that the following function was to blame:

                    // document group allowed regarding user authentification
                    if ($this->validListIDs($this->cfg['docgrp'])) {
                      $this->main['jfilters'][] = array(
                        'tb_name' => $this->getShortTableName('document_groups'),
                        'tb_alias' => 'dg',
                        'main' => 'id',
                        'join' => 'document',
                        'field' => 'document_group',
                        'oper' => 'in',
                        'value' => $this->cfg['docgrp'],
                        'or' => array(
                          'field' => 'privateweb',
                          'oper' => '=',
                          'value' => '0'
                        )
                      );
                    }
                    else {
                      // documents should be public
                      $this->main['filters'][] = array(
                          'field' => 'privateweb',
                          'oper' => '=',
                          'value' => '0'
                      ); 
                    }
                    break;
          


          Seems that the ’docgrp’ was blank and was still being passed into the SQL query, thus causing an error. So I modified it a bit to check for an empty variable:

                    // document group allowed regarding user authentification
                    if(!empty($this->cfg['docgrp'])){
                        if ($this->validListIDs($this->cfg['docgrp'])) {
                          $this->main['jfilters'][] = array(
                            'tb_name' => $this->getShortTableName('document_groups'),
                            'tb_alias' => 'dg',
                            'main' => 'id',
                            'join' => 'document',
                            'field' => 'document_group',
                            'oper' => 'in',
                            'value' => $this->cfg['docgrp'],
                            'or' => array(
                              'field' => 'privateweb',
                              'oper' => '=',
                              'value' => '0'
                            )
                          );
                        } else {
                          // documents should be public
                          $this->main['filters'][] = array(
                              'field' => 'privateweb',
                              'oper' => '=',
                              'value' => '0'
                          ); 
                        }
                    } else {
                      // documents should be public
                      $this->main['filters'][] = array(
                          'field' => 'privateweb',
                          'oper' => '=',
                          'value' => '0'
                      ); 
                    }
                    break;
          


          I’m making changes in short order so I would presume that there is a better way to handle this. Just trying to stop the errors is all and keep it working.

          After that, I started noticing that returns on search results came up painfully slow. Error logs revealed a timeout on lines like these:

          $wordLeft = $mbStrpos($mbStrtolower($text), $mbStrtolower($searchTerm));


          Don’t know why variables are being used in place of the actual function names. I changed the two instances of these to this:

          $wordLeft = strpos(strtolower($text), strtolower($searchTerm));


          That seems to speed things up quite a bit. I’m sure there are a number of other things but these are the changes I made that made the errors go away. Will compare with an earlier version though and see if that reveals anything. smiley

            Jeff Whitfield

            "I like my coffee hot and strong, like I like my women, hot and strong... with a spoon in them."
            • 5811
            • 1,717 Posts
            Seems that the ’docgrp’ was blank and was still being passed into the SQL query, thus causing an error

            In search.class.inc.php, the initDocGroup function initialize the list of private document group. When all the document are public, $this->cfg[’docgrp’] should be empty.
            /**
             * initDocGroup : Initialize document group
             */
              function initDocGroup(){
                global $modx;
                $this->cfg['docgrp'] = '';
                if ($docgrp = $modx->getUserDocGroups()) {
                  $this->cfg['docgrp'] = implode(",", $docgrp);
                }
                $this->dcfg['docgrp'] = $this->cfg['docgrp'];
              }

            The function validList, as named, is used to valid the list. An empty list return false.
            /**
             *  validListIDs : check the validity of a value separated list of Ids
             */
              function validListIDs($IDs){
                if (preg_match('/^([0-9]+,)*[0-9]+$/',$IDs) == 0) return false;
                return true;
              }

            For instance try this simple test:
            <?php
            
              $result = validListIDs('');
              if ($result) echo "true";
              else echo "false";
            
              function validListIDs($IDs){
                if (preg_match('/^([0-9]+,)*[0-9]+$/',$IDs) == 0) return false;
                return true;
              }
            ?>


            By commenting out the preg_match line, you valid the list and then you get an sql error !!!
            In any case you should get true when you haven’t any private documents. So IMHO, the issue don’t come from a wrong usage of cfg[’docgrp’].


            After that, I started noticing that returns on search results came up painfully slow. Error logs revealed a timeout on lines like these:

            Code:

            $wordLeft = $mbStrpos($mbStrtolower($text), $mbStrtolower($searchTerm));
            All the function like $mbStrpos, $mbStrtolower, ... are used to implement multi-byte and non-multi-byte character operation. I am not sure that the speed is decreasing a lot by the use of function rather than the use of the native function, but I could do some tests and think to change the current implementation.

              • 4018
              • 1,131 Posts
              Thanks for the validListIDs test. That helped immensely. I’ve discovered that if you have a rather large list of ID’s that the preg_match function will cause a segfault. Here’s an example:

              http://dl.getdropbox.com/u/659928/validListIDs.php

              The site is rather large with lots of docs so, yeah, lots of ID’s to boot. Any way to avoid the segfaults?
                Jeff Whitfield

                "I like my coffee hot and strong, like I like my women, hot and strong... with a spoon in them."
                • 5811
                • 1,717 Posts
                Any way to avoid the segfaults?
                http://mobile-website.mobi/php-utf8-vs-iso-8859-1-59
                I will fix the validListIDs function as soon as possible. But you certainly could fix yourself with this solution.
                  • 22303 MODX Staff
                  • 10,725 Posts
                  Yeah, see the following bug report for additional information on this problem:

                  http://bugs.php.net/bug.php?id=45735
                    • 25663 MODX Staff
                    • 12,272 Posts
                    Great finds folks. Thanks!
                      Ryan Thrash, MODX Co-Founder
                      Follow me on Twitter at @rthrash or catch my occasional unofficial thoughts at thrash.me
                      • 4018
                      • 1,131 Posts
                      And here’s what I updated the validListIDs function with. Look good to you?

                      /**
                       *  validListIDs : check the validity of a value separated list of Ids
                       */
                        function validListIDs($IDs){
                          $result = true;
                          if(empty($IDs)){
                              $result = false;
                          } else {
                              $groups = $this->SplitByLength($IDs,5000);
                              foreach($groups as $group){
                                  $group = trim($group);
                                  $group = trim($group, ",");
                                  if (preg_match('/^([0-9]+,)*[0-9]+$/',$group) == 0) {
                                      $result = false;
                                  }
                              }    
                          }
                          return $result;
                        }
                      
                        function SplitByLength($string, $chunkLength=1){ 
                          $Result     = array(); 
                          $Remainder  = strlen($string) % $chunkLength;
                       
                          $cycles = ((strlen($string) - $Remainder) / $chunkLength) + (($Remainder != 0) ? 1 : 0);
                       
                          for ($x=0; $x < $cycles; $x++){
                            $Result[$x] = substr($string, ($x * $chunkLength), $chunkLength);
                          }
                       
                          return $Result;
                        }
                      

                        Jeff Whitfield

                        "I like my coffee hot and strong, like I like my women, hot and strong... with a spoon in them."