【发布时间】:2014-12-19 19:13:54
【问题描述】:
我正在测试详细错误处理的想法,并希望使线程能够在需要处理错误时调用“getlasterror”函数。我为结构使用了一个便宜且简单的指针,但也使用pthread_t id 覆盖以前的条目(如果不需要或已处理错误信息)。
从 stackoverflow 帖子 How do you query a pthread to see if it is still running? 和 How do I determine if a pthread is alive? 看来,使用 pthread_kill 发送虚假信号可能是不安全的。是否真的没有替代机制来检查具有 id 的 pthread 是否存在?或者我可以禁用线程 ID 在运行时重用的能力吗? (我知道后者可能是一个安全问题......)
我之前没有写过任何代码,但我在 Leafpad 中大致完成了我的计划如下所示(因此请忽略任何语法错误,如果有的话!)。兴趣点自然是动态清理,如果应用程序正在关闭没有问题。任何其他替代想法也将受到欢迎:)
如果适用,这将是一个客户端/服务器程序,因此每个accept() 都会存在一个新线程。
struct error_info_structs
{
struct error_info** errs; // error_info struct with details
pthread_t** tids; // thread ids for each struct
uint32_t num; // number of error_info structs and thread ids
pthread_mutex_lock lock; // runtime locker
};
struct error_info_structs g_errs;
// assume we've done necessary initialization...
struct error_info*
get_last_runtime_error()
{
struct error_info* retval = NULL;
pthread_t tid = pthread_self();
pthread_mutex_lock(&g_errs.lock);
for ( uint32_t i = 0; i < g_errs.num; i++ )
{
if ( pthread_equal(g_errs.tids[i], tid) )
{
retval = g_errs.errs[i];
goto release_lock;
}
}
release_lock:
pthread_mutex_unlock(&g_errs.lock);
return retval;
}
void
raise_runtime_error(struct error_info* ei)
{
pthread_t tid = pthread_self();
pthread_mutex_lock(&g_errs.lock);
for ( uint32_t i = 0; i < g_errs.num; i++ )
{
if ( pthread_equal(g_errs.tids[i], tid) )
{
// replace existing
memcpy(&g_errs.errs[i], ei, sizeof(error_info));
goto release_lock;
}
/*
* Dynamic cleanup to lower risk of resource exhaustion.
* Do it here, where we actually allocate the memory, forcing
* this to be processed at least whenever a new thread raises
* an error.
*/
if ( pthread_kill(g_errs.tids[i], 0) != 0 )
{
// doesn't exist, free memory. safe to adjust counter.
free(g_errs.errs[i]);
free(g_errs.tids[i]);
g_errs.num--;
}
}
/*
* first error reported by this thread id. allocate memory to hold its
* details, eventually free when thread no longer exists.
*/
struct error_info* newei = malloc(sizeof(struct error_info));
if ( newei == NULL )
{
goto release_lock;
}
pthread_t* newt = malloc(sizeof(pthread_t));
if ( newt == NULL )
{
free(newei);
goto release_lock;
}
// realloc-bits omitted
g_errs.errs[g_errs.num] = newei;
g_errs.tids[g_errs.num] = newt;
g_errs.num++;
release_lock:
pthread_mutex_unlock(&g_errs.lock);
}
【问题讨论】:
-
if ( g_errs.tids[i] == tid )这坏了。你不能用这种方式比较pthread_t。 (考虑是否是struct。)查找pthread_equal以了解正确的比较方式。 -
不过,有一个不错的 pthread_equal() 函数可以为您比较它们。
-
首先,只要您的线程是可加入(我不明白为什么在你的应用程序中,你会让一个线程不可加入)。在您的代码中,在为线程释放资源之前,请使用
pthread_join()。 -
是的,我可能会在其他地方维护一个线程列表,这样他们就可以在一般情况下加入并像那样操作。我明天试试看更新,凌晨4点才过去。。
标签: c multithreading pthreads