【发布时间】:2017-05-23 16:44:07
【问题描述】:
我想确定某个特定线程是否“存在”。
pthread_kill() 似乎适合这个任务,至少根据它的man page。
如果 sig 为 0,则不发送信号,但仍会进行错误检查。
或者,正如我系统的手册页所说:
如果sig为0,则不发送信号,但仍进行错误检查;这可用于检查线程 ID 是否存在。
但是,当我尝试传入未初始化的 pthread_t 时,应用程序总是 SEGFAULT。
深入研究,来自pthread_kill.c(来自我的工具链)的以下 sn-p 似乎做了 no 错误检查,并且只是尝试取消引用 threadid(取消引用在pd->tid)。
int
__pthread_kill (threadid, signo)
pthread_t threadid;
int signo;
{
struct pthread *pd = (struct pthread *) threadid;
/* Make sure the descriptor is valid. */
if (DEBUGGING_P && INVALID_TD_P (pd))
/* Not a valid thread handle. */
return ESRCH;
/* Force load of pd->tid into local variable or register. Otherwise
if a thread exits between ESRCH test and tgkill, we might return
EINVAL, because pd->tid would be cleared by the kernel. */
pid_t tid = atomic_forced_read (pd->tid);
if (__builtin_expect (tid <= 0, 0))
/* Not a valid thread handle. */
return ESRCH;
我们甚至不能依赖零作为一个好的初始化器,原因如下:
# define DEBUGGING_P 0
/* Simplified test. This will not catch all invalid descriptors but
is better than nothing. And if the test triggers the thread
descriptor is guaranteed to be invalid. */
# define INVALID_TD_P(pd) __builtin_expect ((pd)->tid <= 0, 0)
此外,我在链接的手册页中注意到以下内容(但不是在我的系统上):
POSIX.1-2008 建议,如果实现在其生命周期结束后检测到线程 ID 的使用,pthread_kill() 应返回错误 ESRCH。在可以检测到无效线程 ID 的情况下,glibc 实现会返回此错误。 但还要注意,POSIX 表示尝试使用生命周期已结束的线程 ID 会产生未定义的行为,并且在调用 pthread_kill() 时尝试使用无效的线程 ID 可以,例如,导致分段错误。
正如here by R.. 所述,我要求的是可怕的未定义行为。
看来该手册确实具有误导性——尤其是在我的系统上。
- 是否有一种好的/可靠的方法来询问是否存在线程? (可能不使用
pthread_kill()) - 是否有一个好的值可以用来初始化
pthread_t类型变量,即使我们必须自己捕获它们?
我怀疑答案是使用pthread_cleanup_push() 并保留我自己的is_running 标志,但想听听其他人的想法。
【问题讨论】:
-
'我想确定一个特定的线程是否'存在'。你不能,至少不可靠。设计无所谓。
-
听起来你可能对检查“特定线程”是否存在感到困惑,在这种情况下,
pthread_t应该使用从pthread_create()为该线程返回的值初始化,使用“任何其他线程”存在,这是我可以想象的唯一语义含义,你传递一个未初始化的pthread_t,而且,正如你所见,它失败了......但是,正如@ThingyWotsit 所说,你会更好重新设计东西,这样就没有必要了……