2017-11-18 119 views
0

我有一个项目,我正在将作业添加到队列中,并且我有多个线程正在进行作业,并计算出自己的独立结果。如何停止在pthread_join上停滞的线程?

我的程序处理SIGINT信号,我试图加入线程来合并结果,打印到屏幕,然后退出。我的问题是,当我发送信号时线程似乎停止工作,或者他们在mutex_lock上被阻塞。这里是我的程序的重要部分,以便简洁。

的main.c

//the thread pool has a queue of jobs inside 
//called jobs (which is a struct) 
struct thread_pool * pool; 

void signal_handler(int signo) { 
    pool->jobs->running = 0; //stop the thread pool 
    pthread_cond_broadcast(pool->jobs->cond); 

    for (i = 0; i < tpool->thread_count; i++) { 
     pthread_join(tpool->threads[i], retval); 
     //do stuff with retval 
    } 

    //print results then exit 
    exit(EXIT_SUCCESS); 
} 

int main() { 
    signal(SIGINT, signal_handler); 
    //set up threadpool and jobpool 
    //start threads (they all run the workerThread function) 
    while (1) { 
     //send jobs to the job pool 
    } 
    return 0; 
} 

thread_stuff.c

void add_job(struct jobs * j) { 
    if (j->running) { 
     pthread_mutex_lock(j->mutex); 
     //add job to queue and update count and empty 
     pthread_cond_signal(j->cond); 
     pthread_mutex_unlock(j->mutex); 
    } 
} 

struct job * get_job(struct jobs * j) { 

    pthread_mutex_lock(j->mutex); 

    while (j->running && j->empty) 
     pthread_cond_wait(j->cond, j->mutex); 

    if (!j->running || j->empty) return NULL; 

    //get the next job from the queue 
    //unlock mutex and send a signal to other threads 
    //waiting on the condition 
    pthread_cond_signal(j->cond); 
    pthread_mutex_unlock(j->mutex); 
    //return new job 
} 

void * workerThread(void * arg) { 
    struct jobs * j = (struct jobs *) arg; 
    int results = 0; 
    while (j->running) { 
     //get next job and process results 
    } 
    return results; 
} 

感谢您的帮助,这是给我一个真正的头痛!

+0

如果您阅读[此POSIX信号概念参考](http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04),您将在2.4.3节的末尾看到一个列表的* async-safe *函数,因此可以从信号处理程序安全地使用。如果您查看该列表,您会看到['pthread_join](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_join.html)*未列出。这意味着你不应该在信号处理程序中调用它。 –

回答

2

您不应该从处理异步生成信号的信号处理程序(如SIGINT)中调用pthread_cond_waitpthread_join。相反,你应该为所有线程屏蔽SIGINT,产生一个专用线程,并在那里调用sigwait。这意味着您在信号处理程序环境之外检测到SIGINT信号的到达,因此您不受限于async-signal-safe functions。如果信号传递给其中一个工作线程,您还可以避免自我死锁的风险。

此时,您只需要按顺序关闭工作队列/线程池。根据具体情况,您现有的使用running标志的方法甚至可能不会改变。

+0

真棒谢谢!我也有一个问题,那么当我退出get_job函数由于关机,我没有解锁互斥体:')那么pthread_join不是一个异步信号安全函数的原因是什么? – ImpendingShroom

+0

很少有功能是异步信号安全的。 'pthread_join'需要释放资源,操作堆的函数永远不会异步信号安全,因为POSIX不需要一个异步信号安全的内存分配器。 –

+0

有道理,谢谢你的帮助! – ImpendingShroom