Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

  1. #1
    Membre à l'essai
    Double fork et communication par tubes, terminaison précoce.
    Bonjour,
    Je rencontre une anomalie à l'éxecution d'un petit programme c sous openindiana.

    Voici le code:
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    #include <sys/types.h>
    #include <sys/time.h>
    #include <sys/wait.h>
    #include <stdio.h>
    #include <string.h>
    #include <time.h>
    #include <wait.h>
    #define BUF_SIZE 5
    #define NB 5
    extern int errno;
     
    int main(int argc, char * argv[]){
     
    	int fd[2];
    	int err = pipe(fd);
    	if(err == -1) perror(strerror(errno));
     
    	int fd3[2];
    	err = pipe(fd3);
    	if(err == -1) perror(strerror(errno));
     
    	int fd2[2];
    	err = pipe(fd2);
    	if(err == -1) perror(strerror(errno));
     
    	int second;
     
    	int child = fork();
    	if(child == -1){
    		perror("Erreur de création de processus fils.");
    		perror(strerror(errno));
    	}else if(child == 0){
    		printf("Je suis le premier fils pid: %d ppid: %d\n",getpid(),getppid());
    		close(fd[1]);
    		close(fd2[0]);
    		close(fd3[0]);
    		close(fd3[1]);
    		char nb_buf[BUF_SIZE];
    		err = read(fd[0],nb_buf,BUF_SIZE);
    		if(err == -1){
    			perror("Erreur en lecture au niveau du premier fils.");
    			perror(strerror(errno));
    		}	
    		int nb = atoi(nb_buf);
    		printf("Il en veut %d.\n",nb);
    		nb = 5;
    		printf("nb = %d",nb);
    		int rand_tab[nb];
    		//nb_random(rand_tab,nb,9);
    		rand_tab[0] = 3;
    		rand_tab[1] = 5;
    		rand_tab[2] = 1;
    		rand_tab[3] = 9;
    		rand_tab[4] = 2;
    		char buffer[nb];
    		int i;
    		for(i=0; i<nb; ++i){
    			sprintf(buffer+i,"%s",rand_tab[i]);
    		}
    		int k;
    		for(k=0; k<nb; ++k){
    			printf("tab %d = %d\n",k,rand_tab[k]);
    			printf("tab %s = %d\n",k,buffer[k]);
    		}
    		err = write(fd2[1],&nb,sizeof(int));
    		if(err == -1){
    			perror("Erreur en écriture au niveau du premier fils.");
    			perror(strerror(errno));
    		}
    		err = write(fd2[1],buffer,strlen(buffer));
    		if(err == -1){
    			perror("Erreur en écriture au niveau du premier fils.");
    			perror(strerror(errno));
    		}	
    		exit(EXIT_SUCCESS);
    	}else if(child > 0){			
    		second=fork();
    		if(second > 0){
    			close(fd[0]);
    			close(fd2[0]);
    			close(fd2[1]);
    			close(fd3[1]);
    			printf("Combien de nombres ?\n");
    			char buf[BUF_SIZE];
    			fgets(buf,BUF_SIZE,stdin);
    			printf("Vous en voulez %d.\n",atoi(buf));
    			err = write(fd[1],buf,BUF_SIZE);
    			int status2;
    			wait(&status2);
    			if(WIFEXITED(status2)) printf("terminaison fils 2\n");
    		}else if(second == 0){
    			printf("Je suis le second fils pid: %d ppid: %d\n",getpid(),getppid());
    			close(fd[0]);
    			close(fd[1]);
    			close(fd2[1]);
    			close(fd3[0]);
    			int size;
    			err = read(fd2[0],&size,sizeof(int));
    			if(err == -1){
    				perror("Erreur en lecture au niveau du deuxieme fils.");
    				perror(strerror(errno));
    			}
    			char bufo[size];
    			err = read(fd2[0],bufo,strlen(bufo));
    			if(err == -1){
    				perror("Erreur en lecture au niveau du deuxieme fils.");
    				perror(strerror(errno));
    			}
     
    			printf("size = %d\n",size);
    			int j;
    			for(j=0; j<size; ++j) printf("%s\n",bufo[j]);
    			exit(EXIT_SUCCESS);
    		}else{
    			perror("Erreur de creation du second fils.");
    			perror(strerror(errno));
    		}
    		int status;
    		wait(&status);
    		if(WIFEXITED(status)) printf("terminaison fils 1");
    	}
     
    	return EXIT_SUCCESS;
    }

    A l'éxecution j'obtiens:
    Je suis le premier fils pid: 2184 ppid: 2183
    Je suis le second fils pid: 2185 ppid: 2183
    Combien de nombres ?
    $ 6
    Vous en voulez 6.
    Il en veut 6.

    Au sein du premier fils, l'éxecution semble ne jamais dépasser la ligne 49.
    Au sein du second, on atteint jamais la ligne 113.
    J'ai d'abord pensé à une terminaison précoce du père et donc revu la manière d'utiliser les appels wait, mais sans succès. De plus le test de terminaison d'un des fils, à la ligne 93 n'affiche rien. GDB m'indique que le programme se termine normalement.
    Auriez vous une idée concernant mon erreur ?

    Merci par avance.
    Ben

  2. #2
    Membre émérite
    Il y a pas mal de problèmes. Pas sûr que ça règle ton problème, mais tu devrais déjà régler ça :

    - perror() affiche déjà strerror(errno)
    - rand_tab[i] est un int, et tu utilises %s dans ton sprintf. Don sprintf() va aller lire les addresses 3, 5, 1, etc, ce qui est évidemment incorrect et pourrait potentiellement faire segfaulter ton process. S'il n'y a pas de segfault à ce niveau là il y a toutes les chances que ça aille jardiner après ton buffer, et que ça segfault plus loin.
    - Quand tu fais un wait() tu ne peux pas savroi quel fils va finir en premier. Ton message "terminaison fils X" est donc potentiellement incorrect.
    - Tu lis strlen(bufo) alors que bufo n'a pas été initialisé. Je pense que tu veux plutôt lire size octets.

  3. #3
    Membre à l'essai
    Merci matafan, je prend bonne note de tes indications et j'effectue les modifications.
    Malgrès ça j'ai toujours le même problème qu'au départ, je reste donc attentif à toute autre réponse et je continue mes recherches.

    Ben

  4. #4
    Membre émérite
    Je te suggère de poster ton nouveau code.

  5. #5
    Membre à l'essai
    Toutes mes excuses j'ai dis une bétise lors de mon dernier post. matafan le fait d'utiliser sprintf avec le format %s semble être à l'origine de mon problème. Lorsque j'utilise spritf(buffer+i,"%d",rand_tab[i]);, le programme s'éxecute normalement. Un grand merci !

    Topic résolu.
    Bonne journée.