我在C編寫一個基本的unix shell,我想在shell中捕獲Cntrl-C信號,並將它們僅傳遞給前臺進程,但不傳遞給後臺進程。 shell本身應該繼續運行(而且它會),後臺進程應該忽略一個Cntrl-C並且只能通過專門發送給它們的kill信號來殺死,可能通過命令行「kill pid」。但是,前臺和後臺進程都應該使用SIGCHLD觸發處理程序。然而,現在,外殼捕捉到Cntrl-C信號,並且似乎正確地識別出沒有前臺進程傳遞信號,但後臺進程仍然死亡。C shell,父類捕獲的信號仍然進入子進程。
我試着將後臺進程的組ID設置爲別的,並且解決了這個問題,但是它創建了一個新問題。當我這樣做時,當後臺進程完成時,我的信號處理程序不再捕獲信號。
到目前爲止,我已經看過SIGINT的手冊頁,我已經閱讀了20個左右的答案,我試着將孩子的組ID設置爲與父組不同的東西(解決問題,但現在孩子不能再發送SIGCHLD給父母了),並且我在運行後臺進程時檢查了childid!= foreground process和foregroundProcess == 0。但是後臺進程仍然被殺死。有任何想法嗎?
我想我的問題是在我的信號處理程序的地方,但不是很確定:
主:
struct sigaction sa;
sa.sa_handler = &handleSignal; /*passing function ref. to handler */
sa.sa_flags = SA_RESTART;
sigfillset(&sa.sa_mask); /*block all other signals while handling sigs */
sigaction(SIGUSR1, &sa, NULL);
sigaction(SIGINT, &sa, NULL);
sigaction(SIGCHLD, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
handleSignal看起來是這樣的:
void handleSignal(int signal){
int childid;
switch (signal) {
/*if the signal came from a child*/
case SIGCHLD:
/*get the child's id and status*/
childid = waitpid(-1,&childStatus,0);
/*No action for foreground processes that exit w/status 0 */
/*otherwise show pid & showStatus */
if ((childid != foregroundProcess)){
printf("pid %i:",childid);
showStatus(childStatus);
fflush(stdout);
}
break;
/* if signal came from somewhere else, pass it to foreground child */
/* if one exists. */
default:
printf("Caught signal: %i and passing it", signal);
printf(" to child w/pid: %i\n\n:", foregroundProcess);
fflush(stdout);
/*If there is a child, send signal to it. */
if (foregroundProcess){
printf("trying to kill foreground.\n");
fflush(stdout);
kill(foregroundProcess, signal);
}
}
}
在一個不相關的音符,如果你還沒有改變的'stdout'你不需要,只要你最終所有的輸出與換行符明確地刷新它的緩衝模式。 'stdout'默認是行緩衝的。 –
感謝Joachim。由於printf的存在是爲了調試目的,所以我對緩衝區進行了額外的細心處理。我不希望某些打印線實際上被打印到不打印,因爲另一個打印線在此期間做了一些奇怪的事情。無論如何,所有這些printf可能都會在最終產品中消失。 – Fish314