在多线程程序中(在ARM上运行)我有
主线程,其中包括定期检查popen( "pidof -s prog" )
是否正在运行其他程序。我使用O_CLOEXEC
标志作为文件描述符,并检查fgetc()
是否从管道接收任何内容。 设置文件描述符"非阻塞"导致无法阅读并赢得任何帮助。 shell命令中的pidof
命令运行正常。
在另一个帖子中,子进程中具有立即fork()
的{{1}}用于在发生特定事件时启动execl()
操作。父级使用信号处理程序来观察子级状态,并可以选择在另一个特定事件中杀死子级。我是否使用rsync
或exec()
调用rsync
并不重要 - 结果是相同的。
问题是主线程中的sleep
会阻塞,直到子进程终止。
我会尽早fgetc()
尝试解决这个问题(在应用程序是单线程的某个时刻,就像我开始的another post中所假设的那样)。 / em>的
但无论如何:
我想了解在从管道中读取时导致fork()
阻止的原因。
到目前为止我尝试过的一些事情:
fgetc()
使用相同的rsync
调用不会导致任何问题我查看过system()
implementation,可以看到信号在system()
之前被操纵:
我需要SIGCHLD的信号处理程序,但出于好奇,我试图像上面的代码一样(我用fork()
替换sigprocmask()
) - 没有任何成功,行为保持不变同样的。
我无法在我的BSP提供的资源中找到pthread_sigmask()
的任何实施。
该程序通过system()
打开其他文件 - 没有O_CLOEXEC(将有点cumbersome to change that)
答案 0 :(得分:0)
错误修正和意外行为的解释
确实,我错过了相关的观点。在将示例程序更多地调整到原始代码示例之后,我已经看到信号处理程序(在测试程序中工作)是问题。摘录:
void MyClass::sig_handler(int sig) {
if( m_pid < 1 ) // not the child we're waiting for
return;
pid_t pid;
int wstatus;
while ((pid = waitpid( -1, &wstatus, WNOHANG )) != -1 ) {
// error: this returns 0 as long as any children are alive
// -> check for "> 0" to ignore active child processes
if( pid != m_pid )
return;
// handle stuff here...
}
}
我必须更换以下行
while ((pid = waitpid( -1, &wstatus, WNOHANG )) != -1 )
带
while ((pid = waitpid( -1, &wstatus, WNOHANG )) > 0 )
因为该程序的其他帖子fork()
个孩子(例如popen()
)。如果这些终止,则也会调用信号处理程序(静态类函数)。
据我所知:
在我调用fork()
的主题中,我使用具有默认值和重置值m_pid
的成员-1
。需要来自fork()
的pid。如果m_pid
为-1,则sig处理程序立即返回。
该程序在popen()
fork()
处被阻止(可能是fork()
s的任何其他呼叫)。因此,popen()
返回时输入SIGCHLD的信号处理程序。调用m_pid
时会调用m_pid = fork()
。 waitpid()
不会返回-1但是popen()
子项的pid,然后继续检查返回值= 0,直到所有孩子都终止 - 我等待的那个还活着!只有这样waitpid()
才会返回-1
,主线程可以继续使用fgetc()
进行阅读。
来自waitpid
的手册页:
如果指定了WNOHANG并且由pid指定了一个或多个子(ren) 存在,但尚未改变状态,则返回0。出错,-1 被退回
因为sig处理程序检查m_pid != -1
,所以只有当我在MyClass中使用fork()
来设置m_pid
时才会出现问题。
这就是为什么使用system()
不会导致问题的原因。 m_pid
未设置为值!= -1,因此sig处理程序会立即返回,例如一个孩子在主线程中popen()
。
system()
调用的模仿失败,因为我已将m_pid
设置为fork()
,因此sig处理程序未立即返回。
我想因为sig处理程序是static member function
,所以处理程序会阻塞fork()
编写子进程的线程。