2009-06-01 1 views
4

한 번에 허용되는 인스턴스의 동시 실행 수를 제어하는 ​​래퍼를 만들려고합니다. 그렇게하기 위해, 나는 시스템 전체 세마포어를 사용하고있다. 세마포어를 만들고 sem_wait()을 실행하고 자식 프로세스를 시작한 다음 자식이 종료되면 sem_post()을 수행합니다. 괜찮습니다.sem_wait()/sem_post()의 신호 안전한 사용

문제는이 래퍼로 보낸 신호를 안전하게 처리하는 방법입니다. 신호를 포착하지 않으면 명령이 sem_post()을하지 않고 종료되어 세마포어 수가 영구적으로 1 씩 감소합니다. 그래서 sem_post()을 수행하는 신호 처리기를 만들었습니다. 그러나 여전히 문제가 있습니다. 핸들러가 sem_wait() 전에 연결된 경우

이 신호는 sem_wait()없이 발생하는 sem_post()을 일으키는 sem_wait() 완료되기 전에 도착할 수 행한다. 신호 처리기를 설정하기 전에 sem_wait()을 수행하면 그 반대가 가능합니다.

명백한 다음 단계는 핸들러와 sem_wait()의 설정 중에 신호를 차단하는 것이 었습니다. 이것은 내가 지금 무슨의 의사입니다 :

void handler(int sig) 
{ 
    sem_post(sem); 
    exit(1); 
} 

... 
sigprocmask(...); /* Block signals */ 
sigaction(...);  /* Set signal handler */ 
sem_wait(sem); 
sigprocmask(...); /* Unblock signals */ 
RunChild(); 
sem_post(sem); 
exit(0); 

문제는 이제 sem_wait() 차단할 수 있으며, 그 시간 동안, 신호가 차단되어 있다는 점이다. 프로세스를 죽이려하는 사용자는 "kill -9"에 의존하게 될지도 모릅니다. 이는 내가 어떤 경우이든 상관없이 내가 격려하고 싶지 않은 행동입니다. sem_trywait()을 잠시 사용하고 sigpending()을 테스트 할 수는 있지만 더 긴 세마포어를 기다리는 프로세스가 다음에 실행될 것이라는 보장이 없기 때문에 공정성에 영향을 미칩니다.

세마포어 수집 중에 신호를 처리 할 수있는 안전한 솔루션이 있습니까? 나는 "세마포어를 가지고 있습니까?"라고 생각하고 신호 차단을 제거하는 것을 고려하고 있습니다.하지만 세마포어를 획득 한 이후 100 % 안전하지는 않습니다. 전역 설정은 원자가 아니지만 대기 중에 신호를 차단하는 것보다 낫습니다.

답변

6

sem_wait() 신호가 차단 되나요? 나는 이것이 사실이라고 생각하지 않는다. man page for sem_wait()EINTR 오류 코드가 sem_wait()에서 신호에 의해 중단 된 경우 오류 코드가 반환된다고 말합니다.

이 오류 코드를 처리 할 수 ​​있어야 신호가 수신됩니다. 신호가 수신되지 않은 경우가 있습니까?

sem_wait()이 반환 할 수있는 오류 코드를 처리하도록하십시오. 드물지 만, 100 % 확신을 원하면 100 % 기지를 커버하고 싶습니다.

+0

내가 불분명하면 죄송합니다.sem_wait()는 말한대로 신호를 차단하지 않지만 sigprocmask()를 사용하여 차단합니다. 하지만, 당신은 핸들러가 종료해서는 안되지만 "종료 할 시간"을 말하는 플래그를 설정해야한다는 것을 의미하는 EINTR 에러 코드를 살펴 보는 것이 올바른 해결책이라고 생각합니다. 나는 그것을 시험 할 것이다. 감사. – Jeremy

+0

그게 효과가 있어요. 신호 차단을 제거하고 신호 처리기를 변경하여 종료 할 때의 전체적인 의미를 설정했습니다. sem_wait()가 에러를 리턴하면, 나는 끝내고 세마포어 카운트를 보존한다. 아이를 기다리고 있으면 timeToQuit도 테스트합니다. 종료 할 시간이되면 자식을 죽이고 세마포어 수를 유지하는 sem_post()를 수행합니다. 감사. 그것은 kill -9를 무시하고 신호 안전해야합니다. – Jeremy

0

문제가 올바르게 해결되고 있습니까? 자식이 종료 될 때까지 기다리려면 waitpid() 시스템 호출을 사용하는 것이 좋습니다. 관찰 한 바와 같이, 신호가 수신되는 경우 어린이가 sem_post()을 수행 할 것으로 기대하는 것이 신뢰할 수 없습니다.

+0

사실, 자식은 세마포어를 인식하지 못하고 부모는 내가 보여주지 않은 의사 코드의 RunChild() 함수에서 waitpid()를 수행하고 있습니다. 그 부분은 괜찮 았고 sem_take()가 완료된 후 부모에게 보내진 신호와 자식의 종료를 처리하고있었습니다. 나는 신호 처리기와 sem_wait() 설정 사이의 중요한 부분에 대해 걱정했지만 sem_wait() 오류 코드를 확인하는 것은 내가 볼 수없는 간단한 해결책이었다. – Jeremy

0

나는이 오래 알고 있지만, 여전히 구글의 예의를 읽는 사람들의 이익을 ...에 대한

간단한 (만?)이 문제에 대한 강력한 솔루션은 시스템 V 세마포어를 사용하는 것입니다있는 클라이언트가 자동으로 커널에 의해 반환되는 방식으로 세마포어 리소스를 획득 할 수있게합니다. 프로세스가 어떻게 종료됩니까?