我正在使用 posix 线程在 C 中使用固定数量的线程处理程序。
当线程由于某些错误而终止时,如何通知我?
有信号可以检测吗?
如果是这样,信号处理程序是否可以创建一个新线程以保持线程数相同?
我正在使用 posix 线程在 C 中使用固定数量的线程处理程序。
当线程由于某些错误而终止时,如何通知我?
有信号可以检测吗?
如果是这样,信号处理程序是否可以创建一个新线程以保持线程数相同?
那么你就没有问题了。
也许向主线程发射一个 USR1 信号,告诉它事情已经变成梨形了(我想说山雀向上!)
使用您提供的最新输入,我建议您执行以下操作来获取特定进程已启动的线程数-
#include<stdio.h>
#define THRESHOLD 50
int main ()
{
unsigned count = 0;
FILE *a;
a = popen ("ps H `ps -A | grep a.out | awk '{print $1}'` | wc -l", "r");
if (a == NULL)
printf ("Error in executing command\n");
fscanf(a, "%d", &count );
if (count < THRESHOLD)
{
printf("Number of threads = %d\n", count-1);
// count - 1 in order to eliminate header.
// count - 2 if you don't want to include the main thread
/* Take action. May be start a new thread etc */
}
return 0;
}
备注:
ps H
显示所有线程。
$1
打印在我的系统 Ubuntu 上显示 PID 的第一列。列号可能会因系统而异
将a.out
其替换为您的进程名称
反引号将评估其中的表达式并为您提供进程的 PID。我们正在利用所有 POSIX 线程将具有相同 PID 的事实。
通过将函数指针传递给中间函数来创建线程。异步启动该中间函数并让它同步调用传递的函数。当函数返回或抛出异常时,您可以以任何您喜欢的方式处理结果。
我怀疑当线程因任何原因死亡或退出时,Linux 会向您发出信号。您可以手动执行此操作。
首先,让我们考虑两种线程结束的方式:
在第一种方法中,线程本身可以告诉某人(比如线程管理器)它正在被终止。然后线程管理器将产生另一个线程。
在第二种方法中,看门狗线程可以跟踪线程是否处于活动状态。这或多或少是这样完成的:
Thread:
while (do stuff)
this_thread->is_alive = true
work
Watchdog:
for all threads t
t->timeout = 0
while (true)
for all threads t
if t->is_alive
t->timeout = 0
t->is_alive = false
else
++t->timeout
if t->timeout > THRESHOLD
Thread has died! Tell the thread manager to respawn it
如果由于任何原因无法采用 Ed Heal 的“正常工作”方法(这是我对 OP 问题的最喜欢的答案,顺便说一句),那么懒惰的狐狸可能会看看pthread_cleanup_push()
andpthread_cleanup_pop()
宏,并考虑包括整个线程函数的主体在这两个宏之间。
知道线程是否完成的干净方法是调用pthread_join()
该线程。
// int pthread_join(pthread_t thread, void **retval);
int retval = 0;
int r = pthread_join(that_thread_id, &retval);
... here you know that_thread_id returned ...
问题pthread_join()
是,如果线程永远不会返回(继续按预期运行),那么您将被阻止。因此,这在您的情况下不是很有用。
但是,您实际上可以检查是否可以加入(tryjoin),如下所示:
//int pthread_tryjoin_np(pthread_t thread, void **retval);
int retval = 0;
int r = pthread_tryjoin_np(that_thread_id, &relval);
// here 'r' tells you whether the thread returned (joined) or not.
if(r == 0)
{
// that_thread_id is done, create new thread here
...
}
else if(errno != EBUSY)
{
// react to "weird" errors... (maybe a perror() at least?)
}
// else -- thread is still running
还有一个定时加入,它将等待您指定的时间,例如几秒钟。根据要检查的线程数以及您的主进程是否处于其他位置,这可能是一个解决方案。在线程 1 上阻塞 5 秒,然后在线程 2 上阻塞 5 秒,等等。对于 1,000 个线程,每个循环需要 5,000 秒(大约需要 85 分钟来处理所有线程以及管理事物所需的时间......)
手册页中有一个示例代码,它显示了如何使用 pthread_timedjoin_np() 函数。您所要做的就是放置一个 for 循环来检查每个线程。
struct timespec ts;
int s;
...
if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
/* Handle error */
}
ts.tv_sec += 5;
s = pthread_timedjoin_np(thread, NULL, &ts);
if (s != 0) {
/* Handle error */
}
如果你的主进程有其他事情要做,我建议你不要使用定时版本,尽可能快地遍历所有线程。