2009-11-04 4 views
5

내 사용자 공간 응용 프로그램이 EINTR 신호를받은 후 차단되는 경우가 있습니다.EINTR (인터럽트 된 시스템 호출) 처리 방법

내가 strace를 함께 기록하는 것 :

time(NULL)        = 1257343042 
time(NULL)        = 1257343042 
rt_sigreturn(0xbff07be4)    = -1 EINTR (Interrupted system call) 
--- SIGALRM (Alarm clock) @ 0 (0) --- 
time(NULL)        = 1257343042 
futex(0xb7cea80c, 0x80 /* FUTEX_??? */, 2) = ? ERESTARTSYS (To be restarted) 
--- SIGUSR1 (User defined signal 1) @ 0 (0) --- 
sigreturn()        = ? (mask now [ALRM]) 
futex(0xb7cea80c, 0x80 /* FUTEX_??? */, 2) = ? ERESTARTSYS (To be restarted) 
--- SIGWINCH (Window changed) @ 0 (0) --- 
futex(0xb7cea80c, 0x80 /* FUTEX_??? */, 2) = ? ERESTARTSYS (To be restarted) 
--- SIGTERM (Terminated) @ 0 (0) --- 
time(NULL)        = 1257343443 
time(NULL)        = 1257343443 
futex(0xb7cea80c, 0x80 /* FUTEX_??? */, 2) = ? ERESTARTSYS (To be restarted) 
--- SIGWINCH (Window changed) @ 0 (0) --- 
futex(0xb7cea80c, 0x80 /* FUTEX_??? */, 2 

내가 EINTR 신호를 잡을 수있는 방법 나는 그런 쓰기 등의 우려 호출을 반복 할 수 있습니다 읽거나 선택? 시스템 호출로 작업하는 타사 라이브러리를 사용 했더라도이 EINTR이 발생한 위치를 어떻게 확인할 수 있습니까?

왜 내 앱이 EINTR을받은 후 완전히 차단 되었습니까 (strace 덤프를 참조하십시오 : 보통 처리해야하는 SIGUSR1을 보냈습니다)? 그리고 futex()가 ERESTARTSYS를 사용자 공간으로 반환하는 이유는 무엇입니까?

감사

+3

에서 "패자 모드"의 설명을 참조하십시오. –

+0

'gstack' 또는'gdb'를 사용하여 스택 트레이스를 얻고 프로그램이 현재 멈춰있는 곳을 찾습니다. – mark4o

답변

17

쓰기 (또는 다른 차단 작업)을 호출하는 코드는 EINTR을 알고 있어야한다. 블로킹 연산 중에 신호가 발생하면, 연산은 (a) 부분 완료를 반환하거나, (b) 반환 실패, 아무것도하지 않고 errno를 EINTR로 설정합니다.

while(size > 0) { 
    int written = write(filedes, buf, size); 
    if (written == -1) { 
     if (errno == EINTR) continue; 
     return -1; 
    } 
    buf += written; 
    size -= written; 
} 
return 0; // success 

또는 EINTR을 시도 행동 조금 더 나은 무언가에 대한

는, 많은 기록 : 중단 후 재 시도 쓰기 작업을 전부 아니면 실패에 대한

그래서, 당신은 이런 식으로 뭔가를 할 것

int total = 0; 
while(size > 0) { 
    int written = write(filedes, buf, size); 
    if (written == -1) { 
     if (errno == EINTR) continue; 
     return (total == 0) ? -1 : total; 
    } 
    buf += written; 
    total += written; 
    size -= written; 
} 
return total; // bytes written 

GNU가 아닌 표준이 있습니다 : 그것은 수 및 보고서 실패에 기록 얼마나 많은 (그래서 호출 신호에 의해 중단이 아닌 다른 이유로 실패 할 부분 쓰기를 계속 할 것인지 여부와 방법을 결정할 수 있습니다) 등 관심을 가질만한 TEMP_FAILURE_RETRY 매크로. 내가 원할 때 문서를 찾을 수 없다. 지금 포함.

+1

감사합니다. http://www.gnu.org/s/libc/manual/html_node/Interrupted-Primitives.html에서 매크로에 Docu를 찾았습니다. 잠긴 futex() 함수에 대해 알고 있습니까? – Maus

+1

ERESTARTSYS에 대해 모르겠다. 내부 구현 세부 사항이라고 생각합니다. 사용자 모드 시스템 코드는 반환 된 호출을 다시 시도하거나 EINTR로 변환해야하기 때문에 추적에서 볼 수 있지만 사용자 코드로 반환되는 것을 보지 말아야합니다. . 하지만 나는 틀릴 수도 있습니다. 토요일에 면도 했으므로 Linux Geek 자격 증명과 같은 것이 없습니다. –

+2

futex는 세마포어와 같은 상위 수준의 기능을 구현하는 Linux 전용 "라이트 대기"잠금 프레임 워크입니다. 및 뮤텍스. futex (7)를 참조하십시오. –

2

는 EINTR가 신호가 아니라 오류 번호가 신호에 의해 인터럽트 시스템 호출에 반환도 Worse is Better