2012-05-27 125 views
2

我正在嘗試構建一個作業控制shell,並且當前正在處理後臺進程。在這個程序中,我分叉了一個子進程來處理每個後臺進程,並且在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。)您可以檢查讀取是否返回-1,並且由於EINTR而返回,或者嘗試將SA_RESTART設置爲信號處理程序。請注意,SA_RESTART並不總是工作(依賴於實現,在各種實現中有很多錯誤),並且最好避免IMO。

相關問題