2011-04-12 2 views
4

주기적으로 일부 인 메모리 구조를 업데이트해야하는 pylons 프로젝트가 있습니다. 이는 주문형으로 수행되어야합니다. 나는 이것을위한 신호 처리기를 생각해 내기로 결정했다. 사용자는 SIGUSR1을 메인 파일론 스레드로 보냅니다.이 파일은 프로젝트에서 처리합니다.Pylons의 신호 처리

이 신호, 다음과 같은 예외로 서버 충돌 취급 후에 제외하고 작동합니다

File "/usr/lib/python2.6/SocketServer.py", line 264, in handle_request 
    fd_sets = select.select([self], [], [], timeout) 
select.error: (4, 'Interrupted system call') 

는이 문제를 해결하는 것이 가능한가를?

TIA.

답변

5

예, 가능하지만 스톡 파이썬 라이브러리를 사용하는 것은 쉽지 않습니다. 이것은 파이썬이 모든 OS 오류를 예외로 변환하기 때문입니다. 그러나 EINTR은 실제로 사용 된 시스템 호출을 재 시도해야합니다. 파이썬에서 신호를 사용할 때마다이 오류가 산발적으로 발생합니다.

나는 SafeSocket (code that fixes this)을 가지고 있는데, 파이썬 모듈을 포크하고 그 기능을 추가했다. 그러나 시스템 호출이 사용되는 모든 곳에서 추가되어야합니다. 그래서 가능하지만 쉬운 일은 아닙니다. 하지만 내 오픈 소스 코드를 사용하면 수년간의 작업을 줄일 수 있습니다. ;-)

기본 패턴이 (시스템 호출 데코레이터로 구현)입니다 : 당신은 또한 당신의 선택 호출 주위에 있음을 사용할 수

# decorator to make system call methods safe from EINTR 
def systemcall(meth): 
    # have to import this way to avoid a circular import 
    from _socket import error as SocketError 
    def systemcallmeth(*args, **kwargs): 
     while 1: 
      try: 
        rv = meth(*args, **kwargs) 
      except EnvironmentError as why: 
       if why.args and why.args[0] == EINTR: 
        continue 
       else: 
        raise 
      except SocketError as why: 
       if why.args and why.args[0] == EINTR: 
        continue 
       else: 
        raise 
      else: 
       break 
     return rv 
    return systemcallmeth 

.

+1

참조 용으로, EINTR에 대한 재시도를 요구하는 (아직 열려있는) Python 티켓이 있습니다. http://bugs.python.org/issue9867 –

+0

@Gunnlaugur Briem good reference – Wei

2

수정 사항은, 적어도 실제 선택 라인의 12 year old python-dev list post

while True: 
     try: 
      readable, writable, exceptional = select.select(inputs, outputs, inputs, timeout) 
     except select.error, v: 
      if v[0] != errno.EINTR: raise 
     else: break 

세부 사항에서, 나를 위해 작동하지 중요한 ... 당신의 "fd_sets = select.select ([자동], [ ], [], timeout) "라인은 똑같이 작동해야합니다.

중요한 비트는 EINTR을 확인하고 잡히면 다시 시도/다시 시도하는 것입니다. 오, 그리고 errno를 가져 오는 것을 잊지 마세요.