ID:               37998
 Updated by:       [EMAIL PROTECTED]
 Reported By:      dbs at is dot ua
-Status:           Open
+Status:           Assigned
 Bug Type:         MySQLi related
 Operating System: linux-2.4.32
 PHP Version:      5.1.4
-Assigned To:      
+Assigned To:      georg


Previous Comments:
------------------------------------------------------------------------

[2006-07-03 15:13:27] dbs at is dot ua

Description:
------------
Parent process lost MySQLi connection when his child gone by external
kill (*NIX `kill') or from self by posix_kill($pid, $sig);

Have different database users, different databases, separate
connections.

Reproduce code:
---------------
#!/usr/local/bin/php
<?php

declare(ticks = 1);

define("MYSQL_HOST", "192.168.102.10");
define("MYSQL_DB1", "db1");
define("MYSQL_DB2", 'db2');
define("MYSQL_USER1", "root1");
define("MYSQL_PASS1", 'pass1');
define("MYSQL_USER2", "root2");
define("MYSQL_PASS2", 'pass2');
define("MAX_THREADS", 3);

class WTF_child {

    var $ident; // numeric thread identifier
    var $pid;   // my PID
    var $func;  // some functions container
    var $db;    // database object container
    var $daemon = true;

    function WTF_child($ident, &$f) {
        $this->ident = $ident;
        $this->pid = posix_getpid();
        $this->func = $f;
        pcntl_signal(SIGTERM, array(&$this, "sig_Chandler"));
        $this->func->db_connect(MYSQL_USER2, MYSQL_PASS2, MYSQL_DB2,
$this->db, $this);
        $this->go();
        $this->func->db_close($this->db);
    }

    function go() {
        while ($this->daemon) {
            if ($rs = $this->db->query("select " . $this->ident)) {
                list($id) = $rs->fetch_row();
                echo "\tchild process [".$this->pid."]: ".$id."\r\n";
                $rs->close();
            }
            sleep(3);
        }
    }

    function sig_Chandler($sig) {
        switch ($sig) {
            case SIGTERM:
                echo "\tchild process [".$this->pid."]: SIGTERM
received\r\n";
                $this->daemon = false;
                break;
            default:
        }
    }
}

class WTF_parent {

    var $pid;  // my process ID
    var $func; // some functions
    var $db;   // db object
    var $childs = array();
    var $daemon = true;

    function WTF_parent() {
        $this->pid = posix_getpid();
        $this->func = new func();
        pcntl_signal(SIGTERM, array(&$this, "sig_Phandler"));
        $this->func->db_connect(MYSQL_USER1, MYSQL_PASS1, MYSQL_DB1,
$this->db, $this);
        $this->go();
        $this->func->db_close($this->db);
    }

    function go() {
        for ($thread_no = 1; $thread_no <= MAX_THREADS; $thread_no++)
{
            $pid = pcntl_fork();
            if ($pid == -1) {
                die("can't fork!");
            } elseif ($pid != 0) {
                // parent space
                $this->childs[$pid] = $thread_no;
            } else {
                // child space
                $child = new WTF_child($thread_no, $this->func);
                die();
            }
        }

        while ($this->daemon) {
            foreach ($this->childs as $cpid => $ident) {
                $rs = pcntl_waitpid($cpid, &$status, WNOHANG);
                if ($rs == $cpid || $rs == -1) {
                    echo "parent process [".$this->pid."]: who kill my
thread #".$ident." with PID = ".$cpid." ? :(\r\n";
                    unset($this->childs[$cpid]);
                }
            }
            if ($rs = $this->db->query("select 'nice job'")) {
                list($str) = $rs->fetch_row();
                echo "parent process [".$this->pid."]: ".$str."\r\n";
                $rs->close();
            }
            sleep(5);
        }
    }

    function sig_Phandler($sig) {
        switch ($sig) {
            case SIGTERM:
                echo "parent process [".$this->pid."]: SIGTERM
received\r\n";
                $this->daemon = false;
                break;
            default:
        }
    }
}

class func {

    function db_connect($user, $pass, $db, &$db_obj, &$caller) {
        $db_obj = new mysqli(MYSQL_HOST, $user, $pass, $db);
        if (mysqli_connect_errno()) {
            echo "[", get_class($caller), ", PID = ", $caller->pid, "]:
database connection failed: " , mysqli_connect_error();
            die();
        }
    }

    function db_close(&$db_obj) {
        $db_obj->close();
    }
}

$parent = new WTF_parent();

?>




------------------------------------------------------------------------


-- 
Edit this bug report at http://bugs.php.net/?id=37998&edit=1

Reply via email to