我想用libev
. 我想在键盘输入上有一个观察者,它将解析几个命令,如“开始”“停止”“退出”。在“开始”时,我想创建一个管道并派生应用程序以在子级中启动一些工作程序(例如ffmpeg
使用exec()
或只是一些打印某些字符的循环),并在父级的该管道上设置一个观察者以将输出打印到控制台。在“停止”命令中,我想杀死一个孩子并移除一个观察者。
我已经实现了这个程序,但是在 fork 之后,当孩子运行时,我总是在键盘输入上遇到段错误。
起初我以为是因为 ifSTDIN
可以在孩子和父母之间共享。我试图分离孩子,关闭STDIN
孩子。然后我尝试在开始时dup
STDIN
关闭 parent 中的默认值STDIN
,并在 duplicated 上设置一个观察者STDIN
。我还尝试STDOUT/ERR
在分叉之前关闭描述符并在分叉之后将它们恢复到父级中。
我停下来开始user_input
观察user_input
回调,以防万一这有帮助。
ev_default_fork()
然后我尝试ev_loop_fork()
在一个孩子中执行(这不是必需的,因为我想exec()
在 fork 之后或者在任何情况下子循环永远不会获得控制)但没有成功。
我还尝试使用不同的后端(select
而不是epoll
)。
我也试图忽略一些信号,比如SIGHUP
SIGPIPE
SIGCHILD
.
我还注意到,在fork()
原因段错误和 bash 之后我的输入将其作为命令获取,所以如果我执行这样的操作(使用“>”表示自己手写输入,使用“<”表示程序和系统输出):
> $ ./libev_example
> start
< Debug: fork data got:
< [Data got from child through pipe]
> asd
< Segmentation fault (core dumped)
< $ asd
< bash: asd: command not found...
然后我从源代码构建libev
并尝试调试。段错误发生在ev.c:1698
if (expect_false (w_->pending))
pendings [pri][w_->pending - 1].events |= revents;
else
pri
值为 4,据我所知,这是一个优先事项。pendings[4]
是0x0
这样的段错误发生。当程序不崩溃时,代码进入else
分支。
返回的 fdepoll
是 0,但无论如何我都没有使用 0 作为 fd。此外,对于 0,有一个观察者loop->anfds
对我的回调有user_input
回调。在之前的迭代中,当我输入任何字符串时,没有事件为 0。我检查了管道 fds,它们也有一个大于 0 的数字。
我无法弄清楚这里发生了什么以及我做错了什么。我可以在这里放一些代码,但那里没有什么特别的。这篇文章足够大,所以如果有人要求提供代码,我稍后会发布。
谢谢。