Newsgroup: it.comp.os.linux.development
Titolo: [Xpost] wait di php mal funzionante?

ciao, scusate l'xpost ma non sapevo bene a chi rivolgermi
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"

 quale fosse stato il suo pid.
Francamente non so che dirti, ma vedo che nessuno ti ha risposto,
quindi provo a darti qualche consiglio:
(1) Prova con gli esempi riportati qua: 
http://it.php.net/pcntl_wait
 .
Il tuo codice mi sembra giusto ma puo' darsi che ci stia sfuggendo
qualcosa.
(2) Credo che pcntl_wait faccia da wrapper a wait(2). In questo caso
strace potrebbe darti qualche indicazione sul perche' del
malfunzionamento.
(3) Nel package di sorgenti del PHP ci stanno probabilmente delle
routine di test (make test) ma, nota bene, non ho minimamente
controllato ;-)
Saluti,
The Librarian