2012-05-12 3 views
3

두 개의 스레드 (Linux, NPTL)가 있고 파일 설명자 중 하나 이상에서 폴링하는 스레드가 하나 있고 다른 하나가 닫히면 그 중 하나가 합리적인 것입니까? 동작? MT 환경에서하지 말아야 할 일을하고 있습니까?폴링중인 파일 설명 자 닫기

제가 생각하기에 주된 이유는 폴링 스레드와 통신하고 인터럽트 등을하고 싶지 않다는 것입니다. 대신 어떤 이유로 든 설명자를 닫고 싶습니다. 폴링 스레드가 깨어 난다면, 나는 파일 참조가 다음 폴링 전에 스레드에 의해 버려 져야한다는 표시 인 POLLNVAL을 포함하는 것을 기대한다.

간단한 테스트를 거쳤습니다. POLLNVAL이 정확히 무슨 일이 일어나는지 보여줍니다. 그러나이 경우 POLLNVAL은 제한 시간이 만료 될 때만 설정되며 소켓을 닫으면 poll()이 반환되지 않는 것처럼 보입니다. 이 경우 스레드를 종료하여 poll()을 다시 시작하여 되돌릴 수 있습니다.

#define _GNU_SOURCE 

#include <stdio.h> 
#include <pthread.h> 
#include <poll.h> 
#include <errno.h> 
#include <sys/types.h> 
#include <unistd.h> 
#include <string.h> 
#include <signal.h> 

static pthread_t main_thread; 

void * close_some(void*a) { 

    printf("thread #2 (%d) is sleeping\n", getpid()); 
    sleep(2); 
    close(0); 
    printf("socket closed\n"); 
    // comment out the next line to not forcefully interrupt 
    pthread_kill(main_thread, SIGUSR1); 
    return 0; 

} 

void on_sig(int s) { 
    printf("signal recieved\n"); 
} 

int main(int argc, char ** argv) { 

    pthread_t two; 
    struct pollfd pfd; 
    int rc; 

    struct sigaction act; 
    act.sa_handler = on_sig; 
    sigemptyset(&act.sa_mask); 
    act.sa_flags = 0; 
    sigaction(SIGUSR1, &act, 0); 

    main_thread = pthread_self(); 

    pthread_create(&two, 0, close_some, 0); 

    pfd.fd = 0; 
    pfd.events = POLLIN | POLLRDHUP; 

    printf("thread 0 (%d) polling\n", getpid()); 

    rc = poll(&pfd, 1, 7000); 

    if (rc < 0) { 
     printf("error : %s\n", strerror(errno)); 
    } else if (!rc) { 
     printf("time out!\n"); 
    } else { 
     printf("revents = %x\n", pfd.revents); 
    } 
    return 0; 

} 

답변

3

Linux의 경우 적어도 위험합니다. close에 대한 매뉴얼 페이지는 경고 :

그들이 동일한 프로세스에서 다른 스레드의 시스템 호출에 의해 사용 될 수 있지만 파일 기술자를 닫 아마 현명하다. 파일 설명자를 다시 사용할 수 있기 때문에 의도하지 않은 부작용을 유발할 수있는 다소 불명확 한 경쟁 조건이 있습니다 ( ).

당신이 리눅스에있어 때문에, 당신은 할 수있는 다음

  • eventfd을 설정하고 설문 조사에 추가
  • 신호 eventfd (쓸) 당신이 할 때 당신이 eventfd에 활동을 볼 때 즉시 FD를 닫을 수, 설문 조사에서 FD
  • 을 닫고 poll
에서 제거

또는 signal 처리기를 설정하고 poll이 반환 될 때 errno == EINTR을 확인할 수 있습니다. 시그널 핸들러는 여러분이 닫을 fd의 값으로 전역 변수를 설정하기 만하면됩니다. 당신이 리눅스에있어 이후


당신은 poll에 표준이 아닌 대안이기는하지만 우수한으로 epoll을 고려할 수 있습니다.

+0

감사합니다. 그 스 니펫은 정확하게 읽어야합니다. 재사용으로 인해 문제가 발생할 수 있습니다. 나는 리모콘에 연결될 것이기 때문에 직접 fd에 쓸 수는 없으므로 사용자 정의 시그널링이 필요합니다. –