2012-05-27 2 views
2

Я пытаюсь создать оболочку управления заданиями и в настоящее время работать с фоновыми процессами. В этой программе я создаю дочерний процесс для обработки каждого фонового процесса, и я получаю подсказку сразу после fork. Но проблема в том, что, когда фоновый процесс возвращается, он снова распечатывает приглашение. Может ли кто-нибудь помочь мне решить эту проблему? спасибо ##запрос пользователя для ввода снова после возврата фонового процесса

char prompt[] = "myShell"; 
set_sighandler_SIGCHLD(); //wait for background process return 
while(1){ 
     char cmd[BUFFERSIZE] = ""; 
     write(1, prompt, sizeof(prompt)); 
     if(read(0, cmd, 1024) <= 1)){ 
       //parse command 
       //and execute 
     } 
} 
//Here is the background process. 
int put_to_background(int (*func)(char** arg), char ** cmd){ 
    pid_t pid; 
    if((pid = fork()) < 0){ 
     perror("fork"); 
     return -1; 
    } 
    else if(pid == 0){ 
     func(cmd);  //call the function the execute the command 
     _exit(0); 
    } 
    else{ 
     if(setpgid(pid, 0)){ 
      perror("setpgid"); 
      return -1; 
     } 
     printf("running: %d\n", pid); 

    } 

После того как я назвал функцию, она сразу же распечатать приглашение «myShell» (это то, что я ожидал), но он печатает еще раз после того, как фоновый процесс возвратил.

Я до сих пор работает по обработке сигнала ...

JobList list; 
void sighandler(int signum, siginfo_t *sip, void *ucp){ 
    if(signum == SIGCHLD){ 
     pid_t pid; 
     while((pid = waitpid(-1, NULL, WNOHANG)) > 0){ 
      Job * job = (Job*)malloc(sizeof(Job)); 
      job->pid = pid; 
      insert(&list, job); 
     } 
    } 
    else if(signum == SIGTTOU){ 
     printf("SIGTTOU: pid = %d\n", (int) sip->si_pid); 
    } 
    else if(signum == SIGTTIN){ 
     printf("SIGTTIN: pid = %d\n", (int) sip->si_pid); 
    } 
} 

int set_sighandler_SIGCHLD(){ 

struct sigaction sa; 
sigemptyset(&sa.sa_mask); 

sigaddset(&sa.sa_mask, SIGCHLD); 
sigaddset(&sa.sa_mask, SIGTTIN); 
sigaddset(&sa.sa_mask, SIGTTOU); 
sa.sa_sigaction = sighandler; 
sa.sa_flags = SA_SIGINFO; 
//sigprocmask(SIG_BLOCK, &sa.sa_mask, NULL); 

if(sigaction(SIGCHLD, &sa, NULL)){ 
    perror("sigaction"); 
    return -1; 
} 
if(sigaction(SIGTTOU, &sa, NULL)){ 
    perror("sigaction"); 
    return -1; 
} 
if(sigaction(SIGTTIN, &sa, NULL)){ 
    perror("sigaction"); 
    return -1; 
} 
return 0; 

}

+0

Я понимаю, почему вы не загромождали свой вопрос с полным определением 'set_sighandler_SIGCHLD()', но могли бы вы разместить подходящее определение, чтобы облегчить воспроизведение вашей ошибки? – thb

+1

Насколько это возможно, было бы разумным дать вам полный, компилируемый тестовый пример? – thb

+0

# Я все еще работаю над обработчиками сигналов # – jctank

ответ

0

read цикл прерывается сигналом, поэтому распечатайте приглашение. (То есть, когда сигнал поступает, сразу возвращается read). Вы можете либо проверить, что read возвращает -1, и возвратилось из-за EINTR, либо попробуйте установить SA_RESTART обработчику сигнала. Обратите внимание, что SA_RESTART не всегда работает (зависит от реализации, многие ошибки в различных реализациях) и является, ИМО, лучше всего избегать.