# Signaux

>sources à compléter dans le repertoire [src](./src)

#### Ex1
1. Complétez le programme [rebours.c](./src/ex1/rebours.c) qui compte à
   rebours seconde après seconde à partir d'un nombre passé en arguments. Sur
   chaque ligne, rebours affiche son pid et le nombre de secondes restantes.
   ```bash
   [denis@portabledenis SYS-TP1]$ ./rebours 5
	2576552: debut
	2576552: 5
	2576552: 4
	2576552: 3
	2576552: 2
	2576552: 1
	2576552: fin
	```
	On utilisera `getpid` et `sleep`.

#### Ex2
Pour calculer le nombre $\pi$, on utilise la méthode de Monte-Carlo.
On tire aléatoirement des couples $(x,y)$ de nombres de
$[0,1]\times[0,1]$. La probabilité qu'il tombe dans le disque de
rayon 1 est exactement de $\frac{\pi}{4}$. On procède à plusieurs
tirages pour estimer la probabilité correspondante.

```c
uint64_t shots_in=0,shots=0;
double x,y;

int main(int argc, char **argv)
{
	shots_in = 0;
	shots = 0;
	for (;;){
		x = rand()/(RAND_MAX*1.0);
		y = rand()/(RAND_MAX*1.0);
		shots ++;
		if ((x*x+y*y)<=1){
			shots_in ++;
		}    
	}
	/* la probabilité vaut tirsIn/tirs, 
	   Elle converge lentement vers pi/4*/	
}        
```

En utilisant les signaux, mettre en place :

 - avec `SIGALRM`, toutes les 5 secondes, l'affichage de la valeur
 de pi en cours et le nombre de tirs effectués.
 - avec `SIGINT` l'arrêt du programme (après la demande d'une
	confirmation), avec l'affichage du temps écoulé depuis son
 lancement, quand on fait `ctrl+C` au terminal.
 - avec `SIGQUIT` la réinitialisation du calcul avec `ctrl+\`
 depuis le terminal. (faites en sorte que toutes les valeurs restent cohérentes) 

Dans chaque handler, les 2 autres signaux seront bloqués.


#### Ex3

Le but est de protéger un morceau de code  (**section critique**) d'un éventuellement
déroutement à cause de la prise en compte d'un signal.

```c
int x=2,y=3;
int swap(int *x,int *y){
	int tmp=*x;
	*x=*y;
	*y=tmp;
}

void sig_handler(int signo){
	switch(signo){
		case SIGQUIT : 
			printf("x=%d y=%d\n",x,y);
			break;
	}
}

int main(int argc,char * argv[]){

	assert(set_signal_handler(SIGQUIT,sig_handler)==0);
	while(1){
		swap(&x,&y);
	}
}
```

1. Lancez le programme, et envoyez (depuis le terminal) le signal SIGQUIT souvent. La fonction
 `swap` est-elle interrompue ? comment le voyez-vous ?
2. Ajoutez le code nécessaire pour assurer que `swap` ne soit jamais interrompue par `SIGQUIT`.

## Pour ceux/celles qui ont **tout** fait
#### Ex4
On va simuler un match de **ping-pong** entre un père et son fils, en utilisant le signal `SIGUSR1`.
 - Le père commence à jouer. 
 - On simule 10 échanges. À chaque coup, le père affiche Ping, le fils Pong. L'envoie de la balle 
	consiste à envoyer le signal `SIGUSR1` à son adversaire.

La difficulté consiste à synchroniser correctement les échanges.

Voici un premier code naïf :
```c
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/types.h>
#include <errno.h>
#include <assert.h>

#define N 10
void sig_hand(int sig) {}

sigset_t saveMask, blockMask;

void player_wait(){
	pause();
}
void child_process()
{
	int x = 0;
	while(x < N)
	{
		player_wait();
		printf("\tPong %d!\n", ++x);
		kill(getppid(), SIGUSR1);
	}
	return ;
}

void parent_process(pid_t pid)
{
	int y = 0;
	while (y < N)
	{
		printf("Ping %d!\n", ++y);
		kill(pid, SIGUSR1);
		player_wait();
	}
	return ;
}

int main(int argc, char* argv[])
{
	//set up signal handler for parent & child
	struct sigaction sa;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = 0;
	sa.sa_handler = sig_hand;

	assert (sigaction(SIGUSR1, &sa, NULL) != -1);

	pid_t pid = fork();

	if (pid == 0)
		child_process();
	else
		parent_process(pid);
	return 0;
}
```

1. Expliquez pourquoi ce code n'est pas correct (Faites varier `N`).
2. Proposez une solution. 
