запросить пользователя для ввода снова после возврата фонового процесса

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

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;

}


person jctank    schedule 27.05.2012    source источник
comment
Я понимаю, почему вы не загромождали свой вопрос полным определением set_sighandler_SIGCHLD(), но не могли бы вы опубликовать подходящее определение, чтобы упростить воспроизведение вашей ошибки?   -  person thb    schedule 28.05.2012
comment
Более того, было бы разумно, если бы вы предоставили полный, компилируемый тестовый пример?   -  person thb    schedule 28.05.2012
comment
#Я все еще работаю над обработчиками сигналов#   -  person jctank    schedule 28.05.2012
comment
Справедливо. Тем не менее, вы, очевидно, скомпилировали и запустили какой-то код или что-то еще, что, когда фоновый процесс возвращается, он снова выводит сообщение с подсказкой. Я не могу скомпилировать код, который вы перечисляете. Хотите дать (надеюсь, не слишком длинный) код, который можно скомпилировать?   -  person thb    schedule 28.05.2012
comment
Я думаю, что вы делаете все возможное, чтобы задать хороший вопрос, поэтому я надеюсь, что ваш вопрос не затеряется в большой куче старых вопросов без ответов Stackoverflow. Однако я недостаточно умен или терпелив, чтобы ответить на него в заданной форме. Я все еще вижу неполный исходный файл, без включения заголовка и тому подобного. Я выхожу из системы на сегодня, так что, надеюсь, кто-то еще ответит на вопрос. Удачи.   -  person thb    schedule 28.05.2012
comment
Небезопасно вызывать malloc внутри обработчика сигнала. Пусть ваш обработчик сигналов присваивает значение глобальному sig_atomic_t и ничего больше. Обработка всей логики вне обработчика сигнала. (Также небезопасно вызывать printf)   -  person William Pursell    schedule 28.05.2012


Ответы (1)


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

person William Pursell    schedule 28.05.2012