Manugal
11-01-2007, 19:03
Ciao.
Ho un problema con questo ciclo che praticamente dovrebbe eseguire dei comandi in pipe (proprio come fa la shell di Linux). Posto il codice:
j=0;
for(i=0; i<res; ++i){
if((pid = fork()) < 0){
perror("fork error");
exit(FORK_ERR);
}
if(pid == 0){
if(args!=NULL){
free(args);
args=NULL;
}
args=(char **)calloc(MAX_ARGS,sizeof(char *));
if(do_I_launch_parse(commands[i]) == 1)
parse(commands[i],args); /* Riempie args (se c'è da fare qualche espansione come accade nella shell di Linux */
else{ /* altrimenti suddivido le parole della stringa in commands in modo da poter essere eseguita correttamente dalla exec (se veniva lanciata parse lo faceva automaticamente insieme all'espansione)
if(args[j]==NULL)
args[j]=(char *)calloc(strlen(commands[i])+1,sizeof(char));
args[j]=strtok(commands[i]," ");
++j;
while((s=strtok(NULL," ")) != NULL){
if(args[j]==NULL)
args[j]=(char *)calloc(strlen(commands[i])+1,sizeof(char));
strcpy(args[j],s);
++j;
}
}
if(i==0){
close(p[0]);
if(dup2(p[1],STDOUT_FILENO) == -1){
perror("dup error");
exit(DUP_ERR);
}
close(p[1]);
}
else if(i==res-1){
close(p[1]);
if(dup2(p[0],STDIN_FILENO) == -1){
perror("dup error");
exit(DUP_ERR);
}
close(p[0]);
}
else{
if(dup2(p[0],STDIN_FILENO) == -1){
perror("dup error");
exit(DUP_ERR);
}
close(p[0]);
if(dup2(p[1],STDOUT_FILENO) == -1){
perror("dup error");
exit(DUP_ERR);
}
close(p[1]);
}
((args[0]==NULL) ? execlp(commands[i],commands[i],NULL) : execvp(commands[i],args));
perror("exec failed");
exit(EXEC_ERR);
}
if(pid > 0){
if (waitpid(pid,&status,WNOHANG) == -1){
if(errno!=EINTR){
perror("waitpid error");
exit(WAIT_ERR);
}
else{
kill(pid,SIGTERM);
do{
if (waitpid(pid,&status,0) != -1)
break;
}while(errno==EINTR);
}
}
usleep(10000);
}
}
Come potete notare nella waitpid del padre ho dovuto mettere WNOHANG e poi una usleep in modo da emulare il più fedelmente possibile tale comportamento. Ho dovuto mettere queste due istruzioni, altrimenti eseguendo un comando avrei ricevuto questo output:
/home/manugal/Progetto $ ls -l | grep *.h
-rw-r--r-- 1 manugal manugal 3364 2007-01-11 13:28 functions.h
-rw-r--r-- 1 manugal manugal 3371 2007-01-11 13:10 functions.h~
Quindi non tornerebbe normalmente al prompt come io mi aspetto. Poi ho scoperto, settando la modalità O_NONBLOCK su p[0], che è proprio questo file descriptor la causa del problema infatti adesso mi da quest'altro output:
/home/manugal/Progetto $ ls -l | grep *.h
-rw-r--r-- 1 manugal manugal 3364 2007-01-11 13:28 functions.h
-rw-r--r-- 1 manugal manugal 3371 2007-01-11 13:10 functions.h~
grep: (standard input): Risorsa temporaneamente non disponibile
Questo comportamento penso significhi che su p[0] non ci sono dati e quindi si mette in stato blocked. Però non riesco a capire perché, Ci sto sbattendo la testa da 3-4 giorni :muro:
Chi mi può aiutare? Grazie.
Ho un problema con questo ciclo che praticamente dovrebbe eseguire dei comandi in pipe (proprio come fa la shell di Linux). Posto il codice:
j=0;
for(i=0; i<res; ++i){
if((pid = fork()) < 0){
perror("fork error");
exit(FORK_ERR);
}
if(pid == 0){
if(args!=NULL){
free(args);
args=NULL;
}
args=(char **)calloc(MAX_ARGS,sizeof(char *));
if(do_I_launch_parse(commands[i]) == 1)
parse(commands[i],args); /* Riempie args (se c'è da fare qualche espansione come accade nella shell di Linux */
else{ /* altrimenti suddivido le parole della stringa in commands in modo da poter essere eseguita correttamente dalla exec (se veniva lanciata parse lo faceva automaticamente insieme all'espansione)
if(args[j]==NULL)
args[j]=(char *)calloc(strlen(commands[i])+1,sizeof(char));
args[j]=strtok(commands[i]," ");
++j;
while((s=strtok(NULL," ")) != NULL){
if(args[j]==NULL)
args[j]=(char *)calloc(strlen(commands[i])+1,sizeof(char));
strcpy(args[j],s);
++j;
}
}
if(i==0){
close(p[0]);
if(dup2(p[1],STDOUT_FILENO) == -1){
perror("dup error");
exit(DUP_ERR);
}
close(p[1]);
}
else if(i==res-1){
close(p[1]);
if(dup2(p[0],STDIN_FILENO) == -1){
perror("dup error");
exit(DUP_ERR);
}
close(p[0]);
}
else{
if(dup2(p[0],STDIN_FILENO) == -1){
perror("dup error");
exit(DUP_ERR);
}
close(p[0]);
if(dup2(p[1],STDOUT_FILENO) == -1){
perror("dup error");
exit(DUP_ERR);
}
close(p[1]);
}
((args[0]==NULL) ? execlp(commands[i],commands[i],NULL) : execvp(commands[i],args));
perror("exec failed");
exit(EXEC_ERR);
}
if(pid > 0){
if (waitpid(pid,&status,WNOHANG) == -1){
if(errno!=EINTR){
perror("waitpid error");
exit(WAIT_ERR);
}
else{
kill(pid,SIGTERM);
do{
if (waitpid(pid,&status,0) != -1)
break;
}while(errno==EINTR);
}
}
usleep(10000);
}
}
Come potete notare nella waitpid del padre ho dovuto mettere WNOHANG e poi una usleep in modo da emulare il più fedelmente possibile tale comportamento. Ho dovuto mettere queste due istruzioni, altrimenti eseguendo un comando avrei ricevuto questo output:
/home/manugal/Progetto $ ls -l | grep *.h
-rw-r--r-- 1 manugal manugal 3364 2007-01-11 13:28 functions.h
-rw-r--r-- 1 manugal manugal 3371 2007-01-11 13:10 functions.h~
Quindi non tornerebbe normalmente al prompt come io mi aspetto. Poi ho scoperto, settando la modalità O_NONBLOCK su p[0], che è proprio questo file descriptor la causa del problema infatti adesso mi da quest'altro output:
/home/manugal/Progetto $ ls -l | grep *.h
-rw-r--r-- 1 manugal manugal 3364 2007-01-11 13:28 functions.h
-rw-r--r-- 1 manugal manugal 3371 2007-01-11 13:10 functions.h~
grep: (standard input): Risorsa temporaneamente non disponibile
Questo comportamento penso significhi che su p[0] non ci sono dati e quindi si mette in stato blocked. Però non riesco a capire perché, Ci sto sbattendo la testa da 3-4 giorni :muro:
Chi mi può aiutare? Grazie.