php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #33994 DB unavailable after forked child exits
Submitted: 2005-08-04 08:03 UTC Modified: 2005-08-05 04:27 UTC
From: greatwhitepine at bigfoot dot com Assigned:
Status: Wont fix Package: Ingres II related
PHP Version: 5.0.4 OS: Tru64 UNIX V5.1B (Rev. 2650)
Private report: No CVE-ID: None
 [2005-08-04 08:03 UTC] greatwhitepine at bigfoot dot com
Description:
------------
As per the manual ingres_connect connections are terminated when the process exits.  When a forked child exits the connection is terminated permanently until the parent process is restarted.

Reproduce code:
---------------
ingres_connect($str_database, $str_username, $str_password);
if (ingres_query('select count(*) from table')) {
  print 'db ok during fork'."\n\n";
}
$int_pid = pcntl_fork();
if(!$int_pid) {
  ingres_connect($str_database, $str_username, $str_password);
  if (ingres_query('select count(*) from table')) {
    print 'db ok for child'."\n\n";
  }
  exit();
} 
ingres_connect($str_database, $str_username, $str_password);
if (!ingres_query('select count(*) from table')) {
  print 'db not ok after fork'."\n\n";
}


Expected result:
----------------
db ok during fork

db ok for child

Actual result:
--------------
db ok during fork

db ok for child


Warning: ingres_query(): Ingres II:  Server or API error : Read from peer process failed; it may have exited. in /home/its/autoldg/lib/php/local/lib_autoldg_daemon.php on line 228

Warning: ingres_query(): Ingres II:  SQLSTATE : 08004 in /home/its/autoldg/lib/php/local/lib_autoldg_daemon.php on line 228
db not ok after fork


Warning: Unknown: Ingres II:  Server or API error : API function cannot be called in the current state. in Unknown on line 0

Warning: Unknown: Ingres II:  SQLSTATE : 5000R in Unknown on line 0

Warning: Unknown: Ingres II:  Unable to close statement !! in Unknown on line 0

Warning: Unknown: Ingres II:  Unable to rollback transaction !! in Unknown on line 0

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2005-08-04 08:14 UTC] greatwhitepine at bigfoot dot com
Sorry, forgot the pcntl_waitpid during my 1st edit (see below).

ingres_connect($str_database, $str_username, $str_password);
if (ingres_query('select count(*) from auto_ldg_run')) {
  print 'db ok during fork'."\n\n";
}
$int_pid = pcntl_fork();
if(!$int_pid) {
  ingres_connect($str_database, $str_username, $str_password);
  if (ingres_query('select count(*) from auto_ldg_run')) {
    print 'db ok for child'."\n\n";
  }
  exit();
} 
pcntl_waitpid ($int_pid, $str_status);
ingres_connect($str_database, $str_username, $str_password);
if (!ingres_query('select count(*) from auto_ldg_run')) {
  print 'db not ok after fork'."\n\n";
}
exit(1);
 [2005-08-04 08:45 UTC] sniper@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

Use separate connections or something else than ingres (moved to PECL, report bugs on it to pecl.php.net/bugs..)

 [2005-08-04 18:39 UTC] greatwhitepine at bigfoot dot com
Seperate connections does not work (as per the example)!
 [2005-08-05 00:15 UTC] greatwhitepine at bigfoot dot com
Just in case anyone might care I have a workaround...  the parent must not open a db connection until all children have completed.  Thus if the parent needs to use the db before forking child processes it should fork a db_child process to do so.

This code works as expected...
print 'parent before parent query'."\n\n";
$int_pid = pcntl_fork();
if(!$int_pid) {
  ingres_connect($str_database, $str_username, $str_password);
  if (ingres_query('select count(*) from auto_ldg_run')) {  
    print 'db ok for for parent query'."\n\n";
  }
  exit();
} 
pcntl_waitpid($int_pid, $int_returnCode, WUNTRACED);
print 'parent before child process is spawned'."\n\n";
$arr_pids = FALSE;
for ($i=0; $i < 3; $i++) {
  $arr_pids[] = pcntl_fork();
  if(!$arr_pids[$i]) {
    ingres_connect($str_database, $str_username, $str_password);
    if (ingres_query('select count(*) from auto_ldg_run')) {
      print 'db ok for child '.$i." \n\n";
    }
    exit();
  } 
}
for ($i=0; $i < 3; $i++) {
  pcntl_waitpid($arr_pids[$i], $int_returnCode, WUNTRACED);
}
print 'parent after children have completed'."\n\n";
ingres_connect($str_database, $str_username, $str_password);
if (ingres_query('select count(*) from auto_ldg_run')) {
  print 'db ok for parent after children have completed'."\n\n";
}

Output...
parent before parent query

db ok for for parent query

parent before child process is spawned

db ok for child 0 

db ok for child 1 

db ok for child 2 

parent after children have completed

db ok for parent after children have completed
 [2005-08-05 04:27 UTC] greatwhitepine at bigfoot dot com
The workaround is not required if the parent db connections are properly closed before spawning children.  Sorry about that Sniper.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sun Nov 10 01:01:28 2024 UTC