【问题标题】:Is there a safe method to check if a pthread exists?是否有一种安全的方法来检查 pthread 是否存在?
【发布时间】: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


【解决方案1】:

...我可以禁用线程 ID 在运行时重用的功能吗?

不,你不能。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-13
    • 2014-02-03
    • 1970-01-01
    • 2013-06-18
    • 1970-01-01
    • 2021-03-05
    相关资源
    最近更新 更多