Corso di Laurea in Ing. Informatica, Universita' La Sapienza
Sistemi Operativi II
Docente Roberto Baldoni

Soluzione della domanda di programmazione (argomento: SEGNALI).

La gestione dei segnali effettuata tramite l'uso di primitive non sicure quali 'signal' e 'pause' può portare al verificarsi di un deadlock. Nel caso specifico il processo figlio, che legge la riga di testo e la scrive su file, potrebbe inviare il segnale SIGUSR1 al processo padre prima che l'esecuzione di questo raggiunga la linea in cui si mette in attesa (pause()). In questo caso il processo padre rimarrebbe in pausa per un tempo indefinito in attesa di un segnale che non giungerà mai. Il problema può essere risolto passando ad una gestione sicura dei segnali e bloccando il segnale SIGUSR1 fino all'esecuzione dell'istruzione di attesa (sigsuspend).

/* Il gestore del segnale SIGUSR1 */
void sig_handler(int signo) {
	printf("padre: ricevuto segnale di lettura conclusa.\n");
}

int main(int argc, char *argv[]) {
	int 				pid, ppid;
	char 				buffer[1000];
	FILE				*file;
	struct		sigaction	sig, osig;
	sigset_t			sigmask, oldmask, zeromask;

	sigemptyset(&zeromask);

	/* blocchiamo i segnali di tipo SIGUSR1 */
	sigemptyset(&sigmask);
	sigaddset(&sigmask, SIGUSR1);
	sigprocmask(SIG_BLOCK, &sigmask, &oldmask);

	/* installiamo il gestore del segnale */
	sig.sa_handler = sig_handler;
	sigemptyset(&sig.sa_mask);
	sig.sa_flags = 0;

	sigaction(SIGUSR1, &sig, &osig);

	if((pid=fork()) < 0) {
		perror("fork error"); 
		exit(1);
	} else if(pid == 0) {
		/* Processo figlio */
		ppid = getppid(); 
		printf("figlio: mio padre e' %d\n", ppid);
		printf("figlio: inserire la frase da scrivere su file -> ");
		fgets(buffer, 1000, stdin);
		printf("figlio: hai inserito '%s'.",buffer);
		printf("figlio: apro il file.\n");
		file = fopen(argv[1], "w");
		printf("figlio: scrivo sul file.\n");
		fputs(buffer, file);
		fclose(file);
		printf("figlio: invio SIGUSR1 al padre.\n");
		kill(ppid, SIGUSR1);
		exit(0);
	} else { 
		/* Processo padre */ 
		printf("padre: mio figlio e' %d\n", pid);
		printf("padre: attendo segnale dal figlio.\n");
		/* mettiamo il processo in attesa del segnale di completamento */
		sigsuspend(&zeromask);
		printf("padre: apro il file.\n");
		file = fopen(argv[1], "r");
		printf("padre: leggo dal file.\n");
		fgets(buffer, 1000, file);
		printf("padre: la stinga inserita e' '%s'.\n", buffer);
		fclose(file);
		exit(0);
	}
}