Por alguna razón desconocida, cuando ejecuto comandos canalizados en mi programa de shell, solo se generan una vez que salgo del programa, ¿alguien ve por qué?

Código:

int execCmdsPiped(char **cmds, char **pipedCmds){

  // 0 is read end, 1 is write end 
  int pipefd[2]; 

  pid_t pid1, pid2; 

  if (pipe(pipefd) == -1) {
    fprintf(stderr,"Pipe failed");
    return 1;
  } 
  pid1 = fork(); 
  if (pid1 < 0) { 
    fprintf(stderr, "Fork Failure");
  } 

  if (pid1 == 0) { 
  // Child 1 executing.. 
  // It only needs to write at the write end 
    close(pipefd[0]); 
    dup2(pipefd[1], STDOUT_FILENO); 
    close(pipefd[1]); 

    if (execvp(pipedCmds[0], pipedCmds) < 0) { 
      printf("\nCouldn't execute command 1: %s\n", *pipedCmds); 
      exit(0); 
    }
  } else { 
    // Parent executing 
    pid2 = fork(); 

    if (pid2 < 0) { 
      fprintf(stderr, "Fork Failure");
      exit(0);
    }

    // Child 2 executing.. 
    // It only needs to read at the read end 
    if (pid2 == 0) { 
      close(pipefd[1]); 
      dup2(pipefd[0], STDIN_FILENO); 
      close(pipefd[0]); 
      if (execvp(cmds[0], cmds) < 0) { 
        //printf("\nCouldn't execute command 2...");
        printf("\nCouldn't execute command 2: %s\n", *cmds);
        exit(0);
      }
    } else {
      // parent executing, waiting for two children
      wait(NULL);
    } 
  }
}

Salida:

Output of program when I enter "ls | sort -r" for example

En este ejemplo de la salida, he usado "ls | sort -r" como ejemplo, otra nota importante es que mi programa está diseñado para manejar solo una tubería, no soy compatible con comandos de múltiples tuberías. Pero con todo eso en mente, ¿dónde me estoy equivocando y qué debo hacer para solucionarlo para que se genere dentro del shell, no fuera de él? Muchas gracias de antemano por todos y cada uno de los consejos y ayuda brindados.

1
Alex 8 oct. 2019 a las 23:40

1 respuesta

La mejor respuesta

La razón sería que los descriptores de archivo de proceso principal aún no están cerrados. Cuando espera a que termine el segundo comando, se cuelga porque el extremo de escritura no está cerrado, por lo que espera hasta que se cierre el extremo de escritura o haya nuevos datos disponibles para leer.

Intente cerrar pipefd[0] y pipefd[1] antes de esperar a que termine el proceso.

También tenga en cuenta que wait(NULL); regresará inmediatamente cuando un proceso haya terminado, necesitaría un segundo para no generar zombis si su proceso aún se ejecuta después de eso.

1
SaltyPleb 8 oct. 2019 a las 21:36