我正在编写一个 ncurses 应用程序,它显示目录中的文件,并获取用户选择的文件并在 vim 中打开,问题是当我按 ctrl z 暂时关闭 vim 时,在恢复并关闭 vim 后,我的程序在很多方面都搞砸了。
这里有可运行的示例https://pastebin.com/tEdLkaPP 在 Linux 6.5.2 上运行,ncurses 版本为 6.4.2
使用 execl 分叉并打开 vim 的部分代码
def_prog_mode(); endwin();
pid_t pid = fork();
if (pid == -1) {
perror("fork");
} else if (pid == 0) {
execl("vim", "vim", <file>, NULL);
} else {
int child_return = 1;
waitpid(-1, &child_return, WUNTRACED);
}
reset_prog_mode();
redrawwin(stdscr);
// Redraws the window
删除 ncurses 窗口并调用 endwin() 的代码
exit:
delwin(win);
delwin(bottom_win);
delwin(win_border);
delwin(bottom_border);
endwin();
return 0;
我尝试在子进程因 SIGSTOP 停止时调用 def_prog_mode() ,然后在收到 SIGCONT 时调用 reset_prog_mode() ,但这不会改变任何东西。
处理信号的代码
int child_return = 1;
while(!WIFEXITED(child_return))
{
waitpid(-1, &child_return, WUNTRACED | WCONTINUED);
if(WIFSTOPPED(child_return))
def_prog_mode();
else if (WIFCONTINUED(child_return))
reset_prog_mode();
}
查看乔·布莱克爵士的回答中的https://stackoverflow.com/a/4891565/4769313后,我意识到如果我在自定义信号处理程序中处理SIGTSTP,我需要运行kill(getpid(), SIGSTOP )实际上让进程停止。 因此,使用下面的自定义处理程序,一切似乎都按预期工作。 需要注意的是,您必须在 initscr 之后注册信号处理程序,否则 ncurses 可能会覆盖您的信号处理程序。
void sig_tstp(__attribute__((unused))int signal)
{
endwin();
kill(getpid(), SIGSTOP);
}
void sig_cont(__attribute__((unused))int signal)
{
reset_prog_mode();
}
int main()
{
initscr();
signal(SIGTSTP, sig_tstp);
signal(SIGCONT, sig_cont);
// ...
}
分叉代码不再需要处理子进程,直到子进程终止,所以现在看起来像这样
def_prog_mode(); endwin();
pid_t pid = fork();
if (pid == -1) {
perror("fork");
} else if (pid == 0) {
execl(program, program, buf, NULL);
} else {
int child_return = 1;
waitpid(-1, &child_return, 0);
}
reset_prog_mode();