2017-11-18 149 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