2017-11-18 55 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_wait 또는 pthread_join으로 호출하면 안됩니다. 대신 모든 스레드에 대해 SIGINT을 차단하고 전용 스레드를 생성 한 다음 sigwait을 호출해야합니다. 즉, SIGINT 신호가 신호 처리기 컨텍스트 외부에 도달했음을 감지하여 async-signal-safe functions으로 제한되지 않습니다. 또한 신호가 작업자 스레드 중 하나로 전달되는 경우 자체 교착 상태의 위험을 피할 수 있습니다.

이 시점에서 작업 대기열/스레드 풀을 순서대로 종료하면됩니다. 세부 사항에 따라 running 플래그를 사용하는 기존 방식은 변경되지 않을 수도 있습니다.

+0

굉장한 감사합니다! 나는 또한 종료 때문에 get_job 함수를 종료 할 때 문제가 발생했다. 뮤텍스를 잠금 해제하지 않았다. ') 그래서 pthread_join이 비동기 신호 안전 함수가 아닌 이유는 무엇입니까? – ImpendingShroom

+0

비동기 신호 안전 기능은 거의 없습니다. 'pthread_join'은 자원을 할당 해제 할 필요가 있고 POSIX는 비동기 시그널 세이프 메모리 할당자를 필요로하지 않기 때문에 힙을 조작하는 함수는 비동기 시그널에 안전하지 않습니다. –

+0

의미가 있습니다. 도움을 주셔서 감사합니다! – ImpendingShroom