Web lists-archives.com

[PHP] Segmentation fault (core dumped) when using pthreads




Hi group

I hope someone can help me with a php cli script which uses threading
(pthreads)

Some years ago I wrote a php script which fetches SNMP Data from several
hosts (about ~40 Hosts and 900 Interfaces) and inserts them into an RRD
DB. One Directory for each host and a separate RRD for each interface
(~2500 RRD Files).

The script runs every minute and takes about 70secs to finish.

Therefor I changed the script to use a thread for each host.

My Problem now is, that the PHP Script is core dumping (Segmentation
fault (core dumped))


The script is reading all Hosts from the DB, then creates a new Thread
for each hosts and starts them in a third loop. At the end the Main
script is waiting for all child's to finish


When i run the script it creates all the DataCollector Object (Threads)
and is able to start between 15 and 30 threads, then gives me the core dump.



I would appreciate it if someone has a few ideas for me as where to look
or what to try next.





tia
Philippe



The Host is a more or less up to date FreeBSD 10.1 VM, with PHP5.6.11

> php -v
PHP 5.6.11 (cli) (built: Aug 12 2015 10:10:47) (DEBUG)
Copyright (c) 1997-2015 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2015 Zend Technologies
    with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2015, by Zend
Technologies
>

> php -i | grep -i zts
Configure Command =>  './configure'  '--with-layout=GNU'
'--localstatedir=/var' '--with-config-file-scan-dir=/usr/local/etc/php'
'--disable-all' '--enable-libxml' '--enable-mysqlnd'
'--with-libxml-dir=/usr/local' '--with-pcre-regex=/usr/local'
'--with-zlib-dir=/usr' '--program-prefix=' '--disable-cgi'
'--enable-fpm' '--with-fpm-user=www' '--with-fpm-group=www'
'--with-regex=php' '--with-zend-vm=CALL' '--enable-debug'
'--enable-maintainer-zts' '--enable-dtrace' '--prefix=/usr/local'
'--mandir=/usr/local/man' '--infodir=/usr/local/info/'
'--build=amd64-portbld-freebsd10.1'
'build_alias=amd64-portbld-freebsd10.1' 'CC=cc' 'CFLAGS=-pipe '-g'
'-fstack-protector' '-fno-strict-aliasing'' 'LDFLAGS=
'-fstack-protector'' 'LIBS=-lpthread' 'CPPFLAGS=' 'CPP=cpp' 'CXX=c++'
'CXXFLAGS=-pipe '-g' '-fstack-protector' '-fno-strict-aliasing''
extension_dir => /usr/local/lib/php/20131226-zts-debug =>
/usr/local/lib/php/20131226-zts-debug


Code Snippets:

collector_threaded.php
----------------------
[Snip]
while ($row) {
    ++$a;
    $SNMPHostId = $row['snmphostId'];
    $SNMPIfId   = $row['snmpifId'];

    $data['host'][$SNMPHostId] = new SNMP_Host(
        $row['snmphostIp'], $row['snmphostName'],
        $row['snmphostCommunity'],
        $row['snmphostVersion'],
        $row['snmphostId']);

    $data[$SNMPHostId][$SNMPIfId] = new SNMP_Interface(
        $data['host'][$SNMPHostId],
        $row['snmpifIndex'],
        $row['snmpifName'],
        $SNMPIfId,
        $row['snmpifMonitor']);


$data['host'][$SNMPHostId]->addSnmpInterface($data[$SNMPHostId][$SNMPIfId]);

    // read the next record
    $row = $dbres->fetch_array();

}
echo "# processed all hosts from DB" . PHP_EOL;


if (empty($data)) {
    echo "no host to monitor!";
} else {
    $threads = array();
    echo "# looping through all data[host]'s" . PHP_EOL;
    foreach ($data['host'] as $hostId => $snmpHost) {
        $threads[$i] = new DataCollector(
            $rrd_base,
            $basedir,
            $snmpHost,
            $data[$hostId]);
    }

    echo "starting all threads (" . count($data['host']) . ")\n";
    foreach($threads as $k => $t) {
        $t->start();
    }


    foreach($threads as $k => $t) {
        $t->join();
        echo $t->getOutput();
    }
}
[/Snip]

// The original Script has a few more echo's in it


DataCollector.php
-----------------
class DataCollector extends Thread {
    private $rrd_base;
    private $basedir;
    private $snmpHost;
    private $rrd_dir;
    private $snmpIfList;

    private $_out;

    public function __construct(
        $rrd_base,
        $basedir,
        SNMP_Host $snmpHost,
        $snmpInterfaceList) {


        $this->rrd_base = $rrd_base;
        $this->basedir = $basedir;
        $this->snmpHost = $snmpHost;
        $this->snmpIfList = $snmpInterfaceList;
        $this->rrd_dir  = $this->rrd_base . $snmpHost->name .
DIRECTORY_SEPARATOR;
    }


    public function run() {
        # check if BaseDir is available
        if (!is_dir($this->basedir)) {
            throw new Exception("BASEDIR does not exist... abort!");
        }

        # check if RRD_BASE Dir is available
        if (!is_dir($this->rrd_base)) {
            if (!mkdir($this->rrd_base)) {
                throw new Exception("Unable to create RRD_BASE... abort!");
            }
        }


        # check if RRD DIR is available
        if (!is_dir($this->rrd_dir)) {
            if (!mkdir($this->rrd_dir)) {
                throw new Exception("Unable to create RRD_DIR... skip
host!");
            }
        }



        #
        # get SNMP Data and process host->interfaces
        #-------------------------------------------
        $snmpdata_if = @snmp2_real_walk(
            $this->snmpHost->ip,
            $this->snmpHost->community,
            "interfaces.ifTable.ifEntry",
            SNMP_TIMEOUT,
            SNMP_RETRIES);

        $snmpdata_ifX = @snmp2_real_walk(
            $this->snmpHost->ip,
            $this->snmpHost->community,
            "ifMIB.ifMIBObjects.ifXTable.ifXEntry",
            SNMP_TIMEOUT,
            SNMP_RETRIES);

        foreach ($this->snmpIfList as $k => $snmpIf) {
            $rrd_file = $this->rrd_dir . $this->snmpHost->name . '_' .
$snmpIf->ifIndex . '.rrd';
            if (!file_exists($rrd_file)) {
                try {
                    adm_createRrdDb($rrd_file);
                } catch (Exception $e) {
                    echo PHP_EOL . "!! ERROR: " . $e->getMessage() . "
....skip interface !!" . PHP_EOL;
                    continue;
                }
            }


            // ifXEntry
            $ifHCInOctets = isset($snmpdata_ifX['ifHCInOctets.' .
$snmpIf->ifIndex]) ? $snmpdata_ifX['ifHCInOctets.' . $snmpIf->ifIndex] :
"U";
            $ifHCInUcastPkts = isset($snmpdata_ifX['ifHCInUcastPkts.' .
$snmpIf->ifIndex]) ? $snmpdata_ifX['ifHCInUcastPkts.' .
$snmpIf->ifIndex] : "U";
            [...]


            try {
                $updater = new RRDUpdater($rrd_file);
                $update_values = array(
                    'ifHCInOctets' => $ifHCInOctets,
                    'ifHCInUcastPkts' => $ifHCInUcastPkts,
                    'ifHCInMcastPkts' => $ifHCInMulticastPkts,
                    'ifHCInBcastPkts' => $ifHCInBroadcastPkts,
                    [more data]
                    'ifOutErrors' => $ifOutErrors,
                    'ifOutUnknownProtos' => $ifOutUnknownProtos,
                );
                $updater->update($update_values);
            } catch (Exception $e) {
                echo PHP_EOL . "!! ERROR: " . $e->getMessage() . "
....skip interface !!" . PHP_EOL;
                continue;
            }
        }
    }
}



-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php