Souběh při fork()

Ladislav Vaiz spam na nagano.cz
Pátek Červenec 25 20:59:05 CEST 2008


Ahoj,
narazil jsem na zajímavý problém, který nevím jak korektně vyřešit. V 
aplikaci spouštím child proces klasicky pipe(), fork(), execlp(). Rodič 
čte stdout a stderr od dítěte. Někdy se child ukončí hodně rychle a 
souběh u rodiče je takový, že se vyvolá SIGCHLD ještě před přiřazením 
pid do proměnné (zřejme ještě v knihovní funkci fork). Obsluha sigchld 
pak neví, které dítě skončilo, protože v oné proměnné je stále nula.

Vyvolání sleep před execlp je prasečinka, protože mi nikdo nezaručí, že 
rodiči nebude trvat déle předat pid do proměnné. I když věřím, že v 
praxi by to většinou fungovalo. Jak toto zajistit korektně?

Konkrétně potřebuju pouze přečíst stdout podprocesu, ale hlavní proces 
musí mít rychlé odezvy. Nechci ho tedy číst třeba přes popen. Vytvořím 
rouru a tu přidám mezi ostatní soubory pro select. Neumím ale zjistit, 
že už jsem přečetl všechna data, že nějaká nevisí v nějakých bufferech. 
Proto si v sigchld nastavím příznak, že už proces skončil a 
předpokládám, že read z roury přečte vše a EAGAIN pak znamená EOF. Jak v 
tomto případě poznat konec roury při asynchronním čtení? Na SIGCHLD netrvám.

Pozorováno na Debianu Sarge (jádro 2.6.8, glibc 2.3.2).

Díky Láďa
main(){
    pid=fork();
    if (pid==0){
        execlp();
    }
}

void sigchld(int){
    int ret=waitpid(-1, NULL, WNOHANG);
   /* tady je někdy ret=správné číslo procesu, ale pid je stále 0 !
      patrně se sigchld vyvolá uvnitř fork() */
}





Další informace o konferenci Linux