C 具有无效线程的pthread_kill()

C 具有无效线程的pthread_kill(),c,pthreads,C,Pthreads,我想确定某个特定线程是否“存在” pthread_kill()似乎适合此任务,至少根据其功能 如果sig为0,则不发送信号,但仍执行错误检查 或者,正如我的系统手册页所说: 如果sig为0,则不发送信号,但仍执行错误检查;这可用于检查线程ID是否存在 但是,当我尝试传入未初始化的pthread\u t时,应用程序总是会出错 深入研究这一点,下面来自pthread\u kill.c(来自我的工具链)的代码片段似乎没有进行错误检查,只是尝试取消引用threadid(取消引用位于pd->tid) i

我想确定某个特定线程是否“存在”

pthread_kill()
似乎适合此任务,至少根据其功能

如果sig为0,则不发送信号,但仍执行错误检查

或者,正如我的系统手册页所说:

如果sig为0,则不发送信号,但仍执行错误检查;这可用于检查线程ID是否存在

但是,当我尝试传入未初始化的
pthread\u t
时,应用程序总是会出错


深入研究这一点,下面来自
pthread\u kill.c
(来自我的工具链)的代码片段似乎没有进行错误检查,只是尝试取消引用
threadid
(取消引用位于
pd->tid

int
__pthread_kill(threadid,signo)
pthread_t threadid;
国际签名;
{
struct pthread*pd=(struct pthread*)threadid;
/*确保描述符有效*/
如果(调试P和无效P(pd))
/*不是有效的线程句柄*/
返回ESRCH;
/*强制将pd->tid加载到局部变量或寄存器中。否则
如果ESRCH测试和tgkill之间存在线程,我们可能会返回
EINVAL,因为pd->tid将被内核清除*/
pid\u t tid=原子强制读取(pd->tid);

如果我想我是在开车回家的时候意识到这一点的,我怀疑很多其他人也会发现这一点很有用

我似乎一直在将工作者(线程)和任务(线程正在做什么)视为一个整体,而事实上它们不是。

正如我已经从问题中的代码片段确定的那样,问“这个线程存在吗?”是不合理的,因为
pthread\u t
很可能只是一个指针(它肯定在我的目标上)。这几乎肯定是一个错误的问题

进程ID、文件句柄、
malloc()
'd内存等也是如此。它们不使用唯一且从不重复的标识符,因此不是可以测试其存在性的唯一“实体”

我在问题中提出的怀疑很可能是真的-我将不得不为任务(而不是线程)使用类似于
正在运行
标志的东西

我考虑过的一种方法是使用初始化为1的信号量,
sem\u trywait()
sem\u post()
pthread\u cleanup\u push()
,如下例所示(为简洁起见,缺少清理)

#包括
#包括
#包括
#包括
#包括
#包括
构造我的任务{
扫描无法启动;
pthread_t tid;
/*任务相关的东西*/
};
void*my_task\u worker(void*arg){
struct my_task*task=arg;
pthread_cleanup_push(sem_post,&(task->can_start));
fprintf(stderr,“--任务启动!\n”);
美国LEEP(2500000);
fprintf(stderr,“--任务结束!\n”);
pthread_cleanup_pop(1);
返回NULL;
}
作废我的任务开始(结构我的任务*任务){
int ret;
ret=sem_trywait(&(任务->可以启动));
如果(ret!=0){
if(errno!=EAGAIN){
perror(“sem_trywait()”);
出口(1);
}
fprintf(stderr,“>>>任务已在运行…\n”);
返回;
}
ret=pthread\u create(&(task->tid),NULL,my\u task\u worker,task);
如果(ret!=0){
perror(“pthread_create()”);
出口(1);
}
fprintf(stderr,“>>>已启动任务!\n”);
返回;
}
int main(int argc,char*argv[]){
int ret;
构造我的任务;
int i;
memset(&task,0,sizeof(0));
ret=sem_init(&(task.can_start),0,1);
如果(ret!=0)
{
perror(“sem_init()”);
返回1;
}
对于(i=0;i<10;i++){
我的任务\u开始(&task);
睡眠(1);
}
返回0;
}
输出:

>>已启动任务!
---任务开始了!
>>>任务已在运行。。。
>>>任务已在运行。。。
---任务结束!
>>>开始执行任务!
---任务开始了!
>>>任务已在运行。。。
>>>任务已在运行。。。
---任务结束!
>>>开始执行任务!
---任务开始了!
>>>任务已在运行。。。
>>>任务已在运行。。。
---任务结束!
>>>开始执行任务!
---任务开始了!

“我想确定某个特定线程是否存在。你不可能,至少不可靠。因此设计并不重要。听起来你可能在混淆是否存在“特定线程”,在这种情况下,
pthread\u t
应该使用从
pthread\u create()返回的值初始化
对于该线程,存在“任何其他线程”,这是我能想象的传递未初始化的
pthread\u t
的唯一语义含义,正如您所看到的那样,它失败了……但是,正如@ThingyWotsit所说,您最好重新设计一些东西,这样就没有必要了。。。
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;