[英]How can I enable ctrl-c / ctrl+break after calling system?
我編寫了一個從內部調用系統命令的程序:
#include <stdlib.h>
int main(void)
{
while(1)
{
system("ls 2>&1 1>/dev/null"); // comment this line out to enable ctrl+break
}
return 0;
}
但是,當它運行時,CTRL + C和CTRL + BREAK不再起作用,似乎被忽略。
我正在嘗試編寫一個程序,在后台執行一些涉及shell的操作,但我也希望能夠在用戶想要破解時突破程序。
有沒有辦法讓它按我想要的方式工作? 我應該改變架構來執行某種fork / exec嗎?
system()函數忽略SIGINT和SIGQUIT信號,並在等待命令終止時阻塞SIGCHLD信號。 如果這可能導致應用程序錯過可能已將其殺死的信號,則應用程序應檢查system()的返回值,並在命令因接收到信號而終止時采取適合應用程序的任何操作。
因此,為了正確響應信號,您需要檢查system()
的返回值。
system()以waitpid()指定的格式返回命令語言解釋器的終止狀態
waitpid()
的文檔引用了wait()
的文檔,它指示您使用以下宏來查找進程退出的原因:
- WIFEXITED(stat_val)
如果為正常終止的子進程返回狀態,則求值為非零值。- WEXITSTATUS(stat_val)
如果WIFEXITED(stat_val)的值不為零,則此宏計算為子進程傳遞給_exit()或exit()的status參數的低8位,或子進程從main返回的值()。- WIFSIGNALED(stat_val)
如果由於收到未捕獲的信號而終止的子進程返回狀態,則求值為非零值(請參閱參考資料)。- WTERMSIG(stat_val)
如果WIFSIGNALED(stat_val)的值不為零,則此宏將評估導致子進程終止的信號的編號。- WIFSTOPPED(stat_val)
如果為當前停止的子進程返回狀態,則求值為非零值。- WSTOPSIG(stat_val)
如果WIFSTOPPED(stat_val)的值不為零,則此宏將計算導致子進程停止的信號的編號。- WIFCONTINUED(stat_val)
如果從作業控制停止繼續的子進程返回狀態,則計算為非零值。
以下是如何使用此信息的示例,而無需分叉單獨的進程。 請注意,您實際上不會在父進程中收到信號,但您可以確定發送到子進程的信號:
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
while(1)
{
int result = system("ls 2>&1 1>/dev/null");
if (WIFEXITED(result)) {
printf("Exited normally with status %d\n", WEXITSTATUS(result));
} else if (WIFSIGNALED(result)) {
printf("Exited with signal %d\n", WTERMSIG(result));
exit(1);
} else {
printf("Not sure how we exited.\n");
}
}
return 0;
}
如果你運行它,你得到:
$ ./sys Exited normally with status 0 Exited normally with status 0 Exited normally with status 0 Exited normally with status 0 Exited normally with status 0 Exited normally with status 0 ^CExited with signal 2
根據IEEE Std 1003.1-2008(POSIX) :
system()
函數的行為應該像使用fork()
,...創建子進程一樣
system()
函數應忽略SIGINT
和SIGQUIT
信號 ,並在等待命令終止時阻塞SIGCHLD信號。 如果這可能導致應用程序錯過可能已將其殺死的信號,則應用程序應檢查system()
的返回值,並在命令因接收到信號而終止時采取適合應用程序的任何操作。在子進程終止之前,
system()
函數不會返回。
來自San Jacinto的評論:
system()基本上是forks,阻塞父節點,並根據POSIX規范鏈接忽略子節點中的某些信號。 您可以通過首先為system()創建另一個進程來阻止此操作。 這使得原始進程(運行shell的進程的祖父進程)可以自由接受終止信號。
#include <stdlib.h>
#include <unistd.h>
#include <wait.h>
int main(void)
{
pid_t pid;
while(1)
{
pid = fork();
if(pid > 0) // parent
{
wait(0);
}
else if(pid == 0) // child
{
system("ls 2>&1 1>/dev/null");
return 0;
}
else // could not fork
{
return 1;
}
}
return 0;
}
從表面上看,這似乎是我所需要的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.