简体   繁体   English

waitpid和pthread_cond_wait(3)

[英]waitpid and pthread_cond_wait(3)

I'm working on a linux app which uses producer and consumer threads. 我正在开发一个使用生产者和消费者线程的linux应用程序。 It's a fairly mature app and I don't want to change the architecture more than I have to. 这是一个相当成熟的应用程序,我不想更改我的体系结构。

The producer and consumer threads are linked via a waitable queue. 生产者和消费者线程通过可等待的队列链接。 This is a class implemented via std::queue together with a condition variable and mutex. 这是一个通过std :: queue与条件变量和互斥锁一起实现的类。

Now I want the consumer threads to be able to fork/exec a child process, and to wait till either the child process is finished, or the waitable queue is non empty, whichever happens first. 现在我希望消费者线程能够分叉/执行子进程,并等到子进程完成,或者等待队列非空,以先发生者为准。 If the waitable queue is non empty then the child process must be killed. 如果可等待队列非空,则必须终止子进程。 Edit: The child processes are third party apps that can't be changed. 编辑:子进程是无法更改的第三方应用程序。

One possibility is to call pthread_cond_signal() on my condition variable when the child process terminates, but how to make that happen? 一种可能性是当子进程终止时在我的条件变量上调用pthread_cond_signal(),但是如何实现呢? I can't use a handler for SIGCHLD, at least not directly, because the man page says that pthread_cond_signal() can't be used from a signal handler. 我不能使用SIGCHLD的处理程序,至少不能直接使用,因为手册页说pthread_cond_signal()不能从信号处理程序中使用。

One possible way would be spawn the child process, then start a thread to a blocking waitpid(), and finally pthread_cond_signal(). 一种可能的方法是生成子进程,然后启动一个线程到一个阻塞的waitpid(),最后是pthread_cond_signal()。 This seems a little clunky though: do I really need to spawn a thread just to keep an eye on a pid? 这看起来有点笨拙:我真的需要生成一个线程只是为了关注pid吗?

For mixing waitpid and select/poll/epoll there's the Self Pipe Trick . 对于混合waitpid和select / poll / epoll,有Self Pipe Trick Is there any equivalent for mixing waitpid and condition variables? 混合waitpid和条件变量有没有相应的东西?

Note 1: On some implementations, SIGCHLD interrupts the condition variable wait functions. 注1:在某些实现中,SIGCHLD中断条件变量等待函数。 This isn't portable and if possible I'd rather not rely on this behaviour. 这是不可移植的,如果可能的话,我宁愿不依赖这种行为。

Note 2: As the condition variable is encapsulated within the waitable queue class, I'd need to extend this class to allow the app to signal the mutex. 注意2:由于条件变量封装在可等待的队列类中,我需要扩展此类以允许应用程序发出互斥锁信号。 This is just a trivial implementation detail which I've glossed over in my question. 这只是一个简单的实现细节,我在我的问题中掩盖了这一点。

Maybe this works, but I am not sure: 也许这有效,但我不确定:

Create a semaphore, which will be registered in your waitable queue and locked/altered/unlocked whenever the waitable queue itself is going to change it's own lock in order to indicate a change of state. 创建一个信号量,只要可等待队列本身要改变它自己的锁定以指示状态的改变,它就会在你的可等待队列中注册并被锁定/更改/解锁。 You should change it's own mutex while it holds the semaphore. 您应该在拥有信号量时更改它自己的互斥锁。

Implement a signal handler for SIGCHLD , which then will perform semaphore locking/altering/unlocking when a 3rd party app will terminate and does nothing if that is not the case. SIGCHLD实现信号处理程序,然后在第三方应用程序终止时执行信号量锁定/更改/解锁,如果不是这样,则不执行任何操作。

In the above cases, they will wait for 1 and increment (as one semaphore operation) on your semaphore, when they want to acquire the semaphore lock, then do their work and then change the semaphore to 0 (decrementing by 2) in order to unlock it for your waiting thread. 在上面的例子中,他们将等待1并在你的信号量上增加(作为一个信号量操作),当他们想要获取信号量锁,然后完成他们的工作然后将信号量更改为0 (递减2)以便为你的等待线程解锁它。 This way you wont have two sucessful locks from any of the queues/3rd party apps continously. 这样你就不会有来自任何队列/第三方应用程序的两个成功锁。

In your actual thread, that is supposed to either wait for a 3rd party app to terminate or your waitable queue, you basically have it wait for a lock on the same semaphore while waiting for 0 (and decrement it, if there are other waiters for 0). 在你的实际线程中,应该等待第三方应用程序终止或你的等待队列,你基本上让它在等待0时等待锁定同一个信号量(如果还有其他服务员则减少它0)。 If the lock is acquired, you check if the mutex on your waitable queue is released. 如果获取了锁,则检查可等待队列上的互斥锁是否已释放。 If not, you know that your 3rd party app terminated. 如果没有,您知道您的第三方应用已终止。 You perform your work and then change your semaphore to 1 by incrementing it and thus unlock the semaphore for your queue and 3rd party app again. 您执行工作,然后通过递增它将信号量更改为1 ,从而再次为您的队列和第三方应用程序解锁信号量。

Since a semop(2) -lock call can be interupted by signal handlers, you will have to check on EINTR and loop any lock attempt you have. 由于semop(2) -lock调用可以由信号处理程序中断,因此您必须检查EINTR并循环任何锁定尝试。

This probably works if it is guaranteed that a signal handler will finish it's execution (of which I think that it is). 如果保证信号处理程序将完成它的执行(我认为它是),这可能有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM