c - PTHREAD_CANCELED 和线程的启动函数返回值有什么问题

标签 c multithreading unix pthreads pthread-join

我正在阅读 Kerrisk's book并看到以下内容作为注释,

Caution is required when using a cast integer as the return value of a thread’s start function. The reason for this is that PTHREAD_CANCELED, the value returned when a thread is canceled (see Chapter 32), is usually some implementation-defined integer value cast to void *. If a thread’s start function returns the same integer value, then, to another thread that is doing a pthread_join(), it will wrongly appear that the thread was canceled. In an application that employs thread cancellation and chooses to return cast integer values from a thread’s start functions, we must ensure that a normally terminating thread does not return an integer whose value matches PTHREAD_CANCELED on that Pthreads implementation. A portable application would need to ensure that normally terminating threads don’t return integer values that match PTHREAD_CANCELED on any of the implementations on which the application is to run.

我不明白笔记的重要性。你能把它编码(显示它的简单代码片段)只是为了说明吗?这些案例中的问题是什么?

最佳答案

这是 PTHREAD_CANCELED 的典型定义(逐字引用自 /usr/include/pthread.h 在我输入此内容的机器上,它运行带有 GNU libc 的 Linux):

#define PTHREAD_CANCELED ((void *) -1)

因此,如果您有这样的代码来检查取消:

void *thread_result;
int rv = pthread_join(child, &thread_result);
if (rv)
    error_exit("pthread_join failed", rv);
if (thread_result == PTHREAD_CANCELED)
    error_exit("thread canceled", 0);

你不能也有这样的线程过程:

static void *appears_to_be_canceled(void *unused)
{
    return ((void *) -1);
}

因为PTHREAD_CANCELED((void *) -1)是平等的。请注意,该数字不能保证为 -1,它可能因系统而异,并且没有好的方法可以在编译时找出它是什么,因为 ((void *)...)#if 中不可用表达。

有两种很好的方法可以避免这个问题:

  • 不要使用线程取消,所以你不必检查 PTHREAD_CANCELED并且不必关心它的数值是多少。由于其他几个原因,这是一个好主意,最重要的是取消使得编写健壮的多线程代码比现在更难。
  • 仅从您的线程过程中返回有效的指针,而不是数字。一个好的习语是这样的:

    struct worker_data
    {
       // put _everything_ your thread needs to access in here
    };
    static void *worker_proc (void *data_)
    {
       struct worker_data *data = data_;
       // do stuff with `data` here 
       return data_;
    }
    

    返回 worker_data object 表示调用 pthread_join 的代码不必跟踪哪个 worker_data pthread_t对应的对象.这也意味着成功完成的线程的返回值保证不等于PTHREAD_CANCELED。 ,因为 PTHREAD_CANCELED保证不会与任何有效指针进行比较。

关于c - PTHREAD_CANCELED 和线程的启动函数返回值有什么问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54335311/

相关文章:

c - 在c中将可变参数传递给子进程UNIX

c - 编译 OCILIB OCI Wrapper 库的问题

c - 在 C 中格式化字符串

c - 动态分配用户输入的字符串

multithreading - epoll_wait 在几个线程上更快?

java - synchronized 是否像 Lock.lock() 那样停放并发线程?

java - 我可以使用多线程一次多次进行相同的休息调用吗?

c++ - 将 CMAKE_C_FLAGS 和 CMAKE_CXX_FLAGS 设置为同一件事而不重复自己?

unix - 是否有用于检查 Protocol Buffer 的权威 *nix 命令行工具?

javascript - node.js 错误 : ENOSYS spawn when executing command line command