2016-12-02 3 views
1

Я пишу программу в C на Linux, которая должна развить 2 детей.linux - программа exec'd не заканчивается

Первый ребенок отправит два случайных числа по трубе второму ребенку. Он будет прослушивать сигнал SIGUSR1 и затем прекратится.

Второй ребенок будет дублировать (dup2) вход трубы как STDIN и файл fp как STDOUT. Затем будет выполнена программа execl, которая выведет некоторые данные в соответствии с их вводом и окончанием.

Моя проблема заключается в том, что программа execl'd никогда не завершится, и я не знаю почему. Любая помощь или советы будут оценены.

main.c (родитель):

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <signal.h> 
#include <sys/wait.h> 
#include <sys/types.h> 

const int BUFFER_SIZE = 30; 

int pipefd[2] = {0,0}; 
int parent_pid = 0; 
int first_pid = 0; 
int second_pid = 0; 
int sleep_time = 5; 
int debug = 0; 
FILE *fp; 

void parent_func() { 
    int wstatus = 0; 

    sleep(sleep_time); 
    kill(first_pid, SIGUSR1); 
    wait(&wstatus); 
    waitpid(second_pid, &wstatus, 0); 
} 

static void sigusr1_handler(int sig) { 
    if (sig == SIGUSR1) { 
     fputs("TERMINATED", stderr); 
     close(pipefd[1]); 
     exit(0); 
    } 
} 

void first_func() { 
    struct sigaction act; 
    char buffer[BUFFER_SIZE]; 

    close(pipefd[0]);                                   
    memset(&act, '\0', sizeof(act)); // clear the sigaction struct                       

    act.sa_handler = &sigusr1_handler; // sets function to run on signal                      

    if (sigaction(SIGUSR1, &act, NULL) < 0) { // assign sigaction                       
     fputs("cannot assign sigaction - exiting...", stderr);                        
     exit(1);                                    
    }                                       

    while (1) {                                    
     sprintf(buffer, "%d %d\n", rand(), rand());                           
     write(pipefd[1], buffer, strlen(buffer));                            
     puts(buffer);                                   
     sleep(1);                                    
    }                                              
}                                        

void second_func() {                                   
    close(pipefd[1]);                                   
    fp = fopen("out.txt", "w");                                
    char buf[30]; 

    dup2(pipefd[0], STDIN_FILENO); 
    close(pipefd[0]); 
    //dup2(fileno(fp), STDOUT_FILENO); 

    execl("./test", "", NULL); 
    perror("Error"); 
} 

int main(int argc, char *argv[]) { 
    int fork_val = 0; 
    parent_pid = getpid(); 

    if (pipe(pipefd)) { 
     fputs("cannot create pipe - exiting...", stderr); 
     return 1; 
    } 

    if (debug) { 
     sleep_time *= 10; 
    } 

    if ((fork_val = fork()) == -1) { 
     fputs("cannot fork process - exiting...", stderr); 
     return 1; 
    } else if (fork_val == 0) { 
     first_func(); 
    } else { 
     first_pid = fork_val; 
     if ((fork_val = fork()) == -1) { 
      fputs("cannot fork process - exiting...", stderr); 
      return 1; 
     } else if (fork_val == 0) { 
      second_func(); 
     } else { 
      second_pid = fork_val; 
      parent_func(); 
     } 
    } 
    fclose(fp); 
    exit(0); 
} 

test.c (файл execl'd):

#include "nd.h" 
#include "nsd.h" 
#include <stdio.h> 
#include <stdlib.h> 

int main() { 
    int num1 = 0; 
    int num2 = 0; 
    char buffer[100]; 

    while (fgets(buffer, 100, stdin) != NULL) { 
     if (sscanf(buffer, "%d %d", &num1, &num2) == 2) { 
      (num1 < 0) ? num1 = (num1 * -1) : num1; 
      (num2 < 0) ? num2 = (num2 * -1) : num2; 
      if (num1 == 1 || num2 == 1) { 
       puts("1"); 
      } else if (num1 == num2) { 
       if (nd(num1) == 1) { 
        puts("prime"); 
       } else { 
        printf("%d\n", num1); 
       } 
      } else if (nd(num1) == 1 && nd(num2) == 1) { 
       puts("prime"); 
      } else { 
       printf("%d\n", nsd(num1, num2)); 
      } 
     } else { 
      fputs("error\n", stderr); 
     } 
    } 
    fputs("DONE", stderr); 
    exit(0); 
} 
+0

Вы должны изучить [правильное форматирование С] (// prohackr112.tk/r/proper-c-formatting). Или узнайте, как [полностью обфускать свой код] (// prohackr112.tk/r/proper-c-obfuscation). –

+0

Извините, я редактировал форматирование. Теперь все будет в порядке. – dotSK

+0

Родительский процесс должен закрыть 'pipefd [0]'. – Barmar

ответ

0

Чтобы быть в состоянии обнаружить конец файла из трубу, которую нужно читать из пустой трубы без записи (без процесса с открытым для записи дескриптора).

Поскольку ваш писатель (first_func()) никогда не закрывает свой дескриптор и всегда пишет что-то в бесконечном цикле, читатель будет либо ждать некоторых данных, либо читать некоторые данные.

Будьте также осторожно о закрытии не являющиеся полезные дескрипторов, если вы не можете столкнуться с некоторыми проблемами с трубами, такой есть единственный процесс, который является читателем и писателем, поэтому будучи не в состоянии определить конец файла ...

+0

Спасибо, я забыл закрыть трубку в родительском процессе. Но канал в first_func() закрывается sigusr1_handler(), который вызывается путем отправки сигнала из родительского процесса. – dotSK

Смежные вопросы