Published on

linux poll timeout 0: 비블로킹 확인과 이벤트 루프 활용

Authors
  • avatar
    Name
    Indo Yoon
    Twitter

linux poll timeout 0은 poll() 호출이 이벤트를 기다리지 않고 현재 준비 상태만 즉시 확인하도록 만드는 값이에요. 서버 운영 코드에서 논블로킹 점검, 이벤트 루프의 분기, 배포 중 종료 신호 확인에 자주 쓰여요. 다만 호출 위치를 잘못 잡으면 바쁜 대기가 되므로 반환값과 루프 구조를 함께 봐야 해요.

한눈에 보기

poll()은 여러 파일 디스크립터의 읽기·쓰기 준비 상태를 한 번에 묻는 시스템 호출이에요. 타임아웃 인자는 기다리는 방식만 바꾸고, 준비 상태를 알려주는 계약은 그대로예요.

  • 음수 타임아웃은 이벤트가 발생할 때까지 대기해요.
  • 0 타임아웃은 즉시 반환하고, 지금 준비된 디스크립터만 알려줘요.
  • 양수 타임아웃은 지정한 만료 조건까지만 기다려요.
  • 반환값 0은 준비된 디스크립터가 없다는 뜻이고, -1은 오류예요.
  • timeout 0은 파일 디스크립터를 논블로킹 모드로 바꾸는 설정과는 달라요.

여기서 중요한 점은 linux poll timeout 0이 "읽기나 쓰기를 논블로킹으로 수행한다"는 선언이 아니라는 거예요. poll()은 준비 상태만 알려주고, 실제 read()나 write()가 블로킹될 수 있는지는 파일 디스크립터의 상태와 코드 구조에 따라 달라져요.

poll 타임아웃 비교 표

타임아웃 인자poll 동작대표 사용 상황
음수이벤트가 올 때까지 기다려요유휴 상태에서 이벤트를 기다리는 메인 루프
0즉시 반환하고 현재 준비 상태만 확인해요논블로킹 점검, 큐 소진 후 재확인, 종료 플래그 확인
양수지정한 만료 조건까지만 기다려요타이머와 이벤트를 함께 처리하는 루프

표처럼 타임아웃은 세 가지로 나눠 볼 수 있어요. POSIX와 Linux man-pages는 음수는 무한 대기, 0은 즉시 반환, 양수는 제한 대기로 설명해요. 서버 코드에서는 이 차이를 루프의 역할에 맞춰 선택해야 해요.

linux poll timeout 0이 필요한 상황

이벤트 루프가 한 번 깨어난 뒤 남은 이벤트를 바로 확인할 때 timeout 0이 유용해요. 예를 들어 poll()이 읽기 가능을 알려줘서 깨어났는데, 큐에 처리할 항목이 더 남아 있을 수 있어요. 이때 0으로 한 번 더 확인하면 다음 대기로 넘어가기 전에 준비된 디스크립터를 정리할 수 있어요.

배포 중 종료 신호를 확인하는 루프에서도 자주 쓰여요. 긴 대기에 들어가기 전에 종료 플래그를 확인하고, 이미 종료 요청이 들어왔다면 대기하지 않고 정리 경로로 빠지는 식이에요. 이때 timeout 0은 "지금 상태를 보고 판단하겠다"는 의미로 쓰여요.

논블로킹 서버의 진단이나 테스트에서도 활용할 수 있어요. 특정 시점에 어떤 파일 디스크립터가 준비됐는지 스냅샷처럼 확인하고 싶을 때, 대기 없이 결과를 받을 수 있어요. 다만 이 용도는 반복 호출보다 단발성 점검에 어울려요.

단계별 확인 방법

  1. pollfd 배열을 만들고 감시할 파일 디스크립터와 관심 이벤트를 넣어요. revents는 호출 전에 0으로 설정해 두는 편이 안전해요.
  2. poll(fds, nfds, 0)처럼 타임아웃을 0으로 넘겨요. 이 호출은 이벤트를 기다리지 않고 바로 돌아와요.
  3. 반환값을 먼저 확인해요. -1이면 errno를 보고, EINTR이면 재시도할지 결정해요. 0이면 준비된 디스크립터가 없다는 뜻이에요.
  4. 반환값이 0보다 크면 각 항목의 revents를 확인해요. POLLIN, POLLOUT, POLLERR, POLLHUP, POLLNVAL을 구분해서 처리해요.
  5. 준비된 디스크립터만 읽기나 쓰기를 수행해요. 레벨 트리거 방식에서는 데이터를 충분히 비우지 않으면 다음 호출에서 같은 이벤트가 다시 보일 수 있어요.
  6. 0 타임아웃 호출을 루프 안에서 쉬지 않고 반복하지 않아요. 대기가 필요한 지점에서는 음수나 양수 타임아웃을 사용해요.

짧은 예시는 int rc = poll(fds, nfds, 0);처럼 시작할 수 있어요. 여기서 중요한 것은 호출 자체보다 반환값과 revents를 올바르게 해석하는 일이에요. poll()이 0을 반환했는데 오류로 착각하면 정상적인 "준비된 항목 없음" 상태를 놓치게 돼요.

상황별 선택 기준

메인 이벤트 루프가 유휴 상태에서 이벤트를 기다리는 구조라면 음수 타임아웃이 자연스러워요. 타이머를 함께 처리해야 한다면 다음 타이머 만료까지를 양수 타임아웃으로 계산해 넘기는 방식이 일반적이에요. 이 구조에서는 timeout 0을 기본값으로 두지 않아요.

이벤트를 처리한 직후 추가로 준비된 항목이 있는지 확인할 때는 0이 어울려요. 예를 들어 연결 수락 루프에서 이미 대기 중인 연결을 모두 처리한 뒤, 더 남아 있는지 즉시 확인하는 식이에요. 이때도 파일 디스크립터가 논블로킹 모드인지 함께 확인해야 해요.

배포나 종료 경로에서는 0을 "종료 요청 확인" 용도로 쓸 수 있어요. 다만 종료 플래그를 확인하는 코드가 이벤트 루프 안에만 있다면, 긴 대기 중에는 반응이 늦어질 수 있어요. 신호 처리와 대기 해제 구조를 함께 설계해야 해요.

주의할 점

timeout 0을 루프에서 계속 호출하면 바쁜 대기가 될 수 있어요. 준비된 이벤트가 없는데도 호출을 반복하면 CPU를 낭비하고, 다른 작업의 응답성을 떨어뜨릴 수 있어요. 0은 "즉시 확인"이 필요한 지점에 제한적으로 쓰는 편이 좋아요.

반환값 0과 오류를 구분해야 해요. 0은 타임아웃 안에 준비된 디스크립터가 없다는 뜻이고, -1은 오류예요. EINTR은 신호로 인해 중단된 경우라서 재시도 정책을 정해야 해요.

poll()은 준비 상태만 알려줘요. 준비됐다는 이유만으로 read()가 절대 블로킹되지 않는다고 단정하면 안 돼요. 여러 스레드가 같은 디스크립터를 공유하거나, 파일 디스크립터가 블로킹 모드인 경우에는 실제 입출력 동작을 따로 확인해야 해요.

일반 파일은 대부분 준비 상태로 보고되는 경우가 많아서 디스크 입출력 완료를 기다리는 용도로 기대하기 어려워요. 네트워크 소켓이나 파이프처럼 이벤트 기반으로 다루는 대상에 쓰는 편이 일반적이에요. 닫힌 디스크립터는 POLLNVAL로 드러날 수 있으니 revents 검사를 생략하지 않아요.

epoll과 혼동하지 않는 것도 중요해요. epoll_wait()의 타임아웃 0도 즉시 확인이라는 개념은 비슷하지만, 등록 기반 이벤트 모델과 반환 구조가 달라요. 코드를 옮길 때는 관심 이벤트와 엣지·레벨 트리거 차이를 다시 확인해야 해요.

자주 묻는 질문

poll timeout 0은 논블로킹 읽기와 같은 뜻인가요?

아니에요. timeout 0은 poll()이 기다리지 않고 준비 상태만 묻는다는 뜻이에요. 파일 디스크립터 자체를 논블로킹 모드로 바꾸는 설정과는 별개라서, 실제 읽기 호출의 동작도 함께 확인해야 해요.

timeout 0으로 계속 호출하면 CPU를 많이 쓰나요?

이벤트가 없는데 반복 호출하면 바쁜 대기가 되어 자원을 낭비할 수 있어요. 대기가 필요한 루프에서는 음수나 양수 타임아웃을 두고, 0은 상태 점검이 필요한 지점에서만 쓰는 편이 안전해요.

poll이 0을 반환하면 오류인가요?

아니에요. 0은 타임아웃 안에 준비된 디스크립터가 없다는 뜻이에요. 오류는 -1과 errno로 구분하고, EINTR 같은 중단 상황은 재시도 여부를 결정해야 해요.

epoll_wait timeout 0과 같나요?

즉시 확인한다는 개념은 비슷하지만 API와 이벤트 모델이 달라요. epoll은 등록한 관심 이벤트를 기반으로 하고, poll은 호출할 때마다 배열을 검사해요. 코드를 바꿀 때 반환값과 이벤트 플래그를 다시 확인해야 해요.

출처

관련 운영 글: Linux 이벤트 루프에서 대기 시간과 종료 신호를 함께 다루는 방법