Newsgroup: it.comp.programmare
Titolo: php e wait malfunzionante

ciao
allora, mi si è presentata la necessità di sviluppare un 'applicazione
multihreaded in php, quindi tramite l'uso pcntl_fork,pcntl_wait (o
waitpid, il risultato non cambia)
Allora,a differenza dei linguaggi dove sono solito utilizzare il
meccanismo fork/wait per la generazione di processi figli(c e python
perlopiù), in php a me sembra ci sia qualcosa (anzi tanto) che non
funziona correttamente. Più precisamente ho notato che la wait non riesce
ad intercettare correttamente i segnali dei figli morti, quando questi:
1 - muoiono quasi contemporaneamente in gruppo (2,3 ..N)
2 - muoiono prima che la wait sia stata lanciata
infatti una wait in uno di questi due casi non rrestituisce il pid del
figlio morto ma "-1", cioè si accorge che uno è morto ma non sa dire
quale fosse stato il suo pid.
All'uopo ho preparato due semplici script (che riporto sotto), uno in php
ed uno in python che dovrebbero fare la stessa cosa. Quello in python
funziona come da manuale della fork, quello in php no.
Potete verificare anche voi il comportamento del php quando si fa morire 
il figlio prima della wait , agendo , o togliendo del tutto la sleep.
Stesso dicasi per python, dove va tutto bene anche senza la sleep.
Insomma, quindi mi chiedo se sbalgio qualcosa io o se davvero pcntl di php
non è adatta (ma così tanto?!) a questo tipo di funzionamento.
Grazie per le eventuali risposte
#!/usr/bin/php
<?php
$children = array(); 
function figlio($id)
{
	$p=posix_getpid();
	echo "figlio: ($id) pid ($p)\n";
	sleep(rand(1,5));
	echo "figlio:esco pid ($p)\n";
 
	exit(0);
}
$i=0;
while($i<10)
{
	$pid = pcntl_fork();
	if($pid == -1)
		die("Could not fork!");
	elseif($pid == 0)
		 figlio($i);
	else
	{
		$children[] = $pid;
		$i++;	
	}	
}
print "padre:dormo un po'...\n";
$i=10;
while($i)
{
	$pid_death = pcntl_waitpid(-1,$status);
	if ($pid_death != 0)
	{
		echo "padre:morto processo con pid ($pid_death)\n";
		if(array_search($pid_death,$children))
		{
			unset($children[$pid_death]);
			print "padre:eliminato pid ($pid_death)\n ";
			$i--;
		}
		else
		{
			$i--;
			print "padre:pid ($pid_death) non tracciato\n";
		}	
	}
}
 
echo "padre:morti tutti\n"
?>
#!/usr/bin/python
import sys
import os
import time
def figlio(i):
	print "figlio: (%d) pid (%d)" % (i,os.getpid())
	sys.exit(0);
 
 
figli=[]
i=0
while i<10:
	i+=1
	pid = os.fork()
	if not pid:
		figlio(i)
	else:
		figli.append(pid)
print "padre:dormo un po'..."
time.sleep(2)
while len(figli):
	pid_death = os.waitpid(-1,os.WNOHANG)
	if pid_death[0] != 0:
		print "padre:morto processo con pid (%d)" % pid_death[0]
		try:
			figli.index(pid_death[0])
			figli.remove(pid_death[0])
			print "padre:eliminato pid (%d) " % pid_death[0]
		except:
			print "padre:pid (%d) non presente tra i figli" % pid_death[0]
	time.sleep(0.5)			
print "padre:morti tutti"

 ?>
questo è l'output eseguito con:
PHP 5.1.2 (cli) (built: Nov 28 2007 22:33:12)
figlio: (0) pid (26170)
figlio:esco pid (26170)
figlio: (1) pid (26171)
figlio:esco pid (26171)
figlio: (2) pid (26172)
figlio:esco pid (26172)
figlio: (3) pid (26173)
figlio:esco pid (26173)
figlio: (4) pid (26174)
figlio:esco pid (26174)
figlio: (5) pid (26175)
figlio:esco pid (26175)
figlio: (6) pid (26176)
figlio:esco pid (26176)
figlio: (7) pid (26177)
figlio:esco pid (26177)
figlio: (8) pid (26178)
figlio:esco pid (26178)
padre:dormo un po'...
padre:morto processo con pid (26170)
padre:eliminato pid (26170)
  padre:morto processo con pid (26171)
padre:eliminato pid (26171)
  padre:morto processo con pid (26172)
padre:eliminato pid (26172)
  padre:morto processo con pid (26175)
padre:eliminato pid (26175)
  padre:morto processo con pid (26176)
padre:eliminato pid (26176)
  padre:morto processo con pid (26177)
padre:eliminato pid (26177)
  figlio: (9) pid (26179)
figlio:esco pid (26179)
padre:morto processo con pid (26173)
padre:eliminato pid (26173)
  padre:morto processo con pid (26174)
padre:eliminato pid (26174)
  padre:morto processo con pid (26178)
padre:eliminato pid (26178)
  padre:morto processo con pid (26179)
padre:eliminato pid (26179)
  padre:morti tutti

 questo č l'output eseguito con:

cioč te li ha presi tutti?
anche se commenti elimini la sleep nel figlio?
e che cavolo, anche ad un altro ragazzo funziona correttamente, io l'ho
provato sia su 4.4.0 che su 5.2.qualcosa ...
bah

 provato sia su 4.4.0 che su 5.2.qualcosa ...
   l'unico che non mi prendeva era dovuto all'errore di array_search per questo
te l'ho segnalato ...