Newsgroup: it.comp.os.linux.development
Titolo: Strani risultati di un test di fork

Ciao a tutti, stavo leggendo un libro (Programmazione su Linux con
Esempi, Kurt Wall) e seguendo gli esempi, e facendo il primo esempio di
fork mi trovo qualcosa di sorprendente (per me). Il codice del
programma è questo:
/*************************/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
int main(void) {
    pid_t child;
    if ((child = fork()) == -1) {
	perror("fork");
	exit(EXIT_FAILURE);
    } else if (child == 0) {
	puts ("Nel processo figlio");
	printf("\tpidson = %d\n", getpid());
	printf("\tppidson = %d\n", getppid());
	exit(EXIT_SUCCESS);
    } else {
	puts("Nel processo padre");
	printf("\tpidf = %d\n", getpid());
	printf("\tppidf = %d\n", getppid());
	/* No, we don't exit here */
	exit(EXIT_SUCCESS);
    }
    exit(EXIT_SUCCESS);
}
/*****************************/
Ora, se lo eseguo sul portatile di un mio amico (Debian unstable)
mostra i risultati "corretti". Se invece lo uso nel mio PC, noto quasi
sempre (ma non sempre) risultati sbagliati, e solo a volte il risultato
"come dovrebbe essere". Nota: parlo solo dei valori di pid e ppid.
Ecco cosa intendo per "risultati sbagliati":
[adriano@edhellond soa]$ ./child
Nel processo padre
        pidf = 5596
        ppidf = 5525
[adriano@edhellond soa]$ Nel processo figlio
        pidson = 5597
        ppidson = 1
(Non torna di nuovo alla shell se non do un enter, notate i PID e PPID
scombinati, e il PID di init...)
Risultato corretto:
[adriano@edhellond soa]$ ./child
Nel processo figlio
        pidson = 5619
        ppidson = 5618
Nel processo padre
        pidf = 5618
        ppidf = 5525
[adriano@edhellond soa]$
Il mio compilatore è gcc 4.0.3. uso mandriva cooker (quindi potrebbe
anche essere questo). Il gcc del mio amico è 4.0.2. Sapete dirmi se
questo comportamento si deve alla asincronicità di fork() o se invece
è dovuto ad altri motivi?
Grazie
Adriano

     }
A dire il vero, questo exit() dopo /* No, we don't exit here */ non è
presente nell'esempio, e l'ho messo solo dopo altri tentativi, peraltro
con lo stesso risultato.
Adriano

Adriano Varoli Piazza ha scritto:

Per fare le cose per bene, dovresti in questo ramo else attendere il 
termine del figlio prima di fare l'exit del padre; non hai garanzie di 
come la cpu andrà a schedulare i due task, se esegue prima il padre, 
allora il figlio rimarrà "orfano" e verrà ereditato da init....questa è 
la spiegazione del valore 1 ritornato dal getppid() nel figlio.
Per renderti meglio conto della cosa metti uno sleep(2) all'inizio del 
ramo if eseguito dal figlio, vedrai che l'id del suo parent sarà sempre 1.
Per gestire la terminazione dei figli ci sono tutta una serie di 
funzioni wait*, nel tuo semplice esempio un wait(NULL) messa prima 
dell'exit del padre è sufficiente; il parametro che passi alla funzione 
è un (int *), nel quale potrai trovare lo stato di terminazione del 
figlio, se ti interessa...
Ciao, Alberto
PS: scusa ma per sbaglio ti ho risposto anche in mail

 PS: scusa ma per sbaglio ti ho risposto anche in mail
Ti scuso, ti scuso :)
Niente, dopo aver letto un pò ho visto anch'io un esempio con
waitpid(), ma mi sorprendeva il fatto che nei computer di altri il
programma funzionasse quasi sempre come da esempio, e invece nel mio
andasse quasi sempre storto.
Grazie per la risposta
Adriano