1

별도의 스레드에서 실행되는 장기 실행 프로세스를 종료하려고 할 때 문제가 발생합니다.스레드에서 실행중인 python 하위 프로세스를 종료 할 때 일관성없는 동작이 발생했습니다.

아래는 프로그램입니다. WorkOne은 서브 프로세스를 작성하고 로그 행을 생성하는 장기 실행 프로세스 "adb logcat"을 실행합니다. main()에서 WorkOne을 시작하고 5 초 동안 기다렸다가 멈추려 고 시도합니다. 다수의 실행은 다중 출력

제공 가끔 [A] 얻을
import threading 
import time 
import subprocess 
import sys 

class WorkOne(threading.Thread): 

    def __init__(self): 
     threading.Thread.__init__(self) 
     self.event = threading.Event() 
     self.process = subprocess.Popen(['adb','logcat'], stdout=subprocess.PIPE, stderr=sys.stdout.fileno())  

    def run(self): 
     for line in iter(self.process.stdout.readline,''):    
      #print line 
      if self.event.is_set(): 
       self.process.terminate() 
       self.process.kill() 
       break; 
     print 'exited For' 

    def stop(self): 
     self.event.set() 

def main(): 

    print 'starting worker1' 
    worker1 = WorkOne() 
    worker1.start() 
    print 'number of threads: ' + str(threading.active_count()) 
    time.sleep(5) 
    worker1.stop() 
    worker1.join(5) 
    print 'number of threads: ' + str(threading.active_count()) 

if __name__ == '__main__': 
    main() 

:

starting worker1 
number of threads: 2 
number of threads: 1 
exited For 

때때로 I는 [C]를 얻을 :

starting worker1 
number of threads: 2 
number of threads: 2 
exited For 

때때로 I는 [B]를 얻을

starting worker1 
number of threads: 2 
number of threads: 2 

나는 [B] 모든 시간을 기대해야한다고 생각합니다. 이자형. 여기서 뭐가 잘못 됐어?

+1

'join()'호출에서 타임 아웃을 설정했기 때문에, 스레드가 멈춘 경우에도 (예를 들어'for' 루프에서 새로운 라인을 기다리고 있습니다.) 스레드가 살아있을 수 있습니다. –

+0

그게 문제 같아서, for 루프에서 stop 메소드로 호출을 종료하고 끝내고, 이제는 기대했던 일관된 출력을 얻습니다. – Harkish

답변

0

서브 프로세스가 10 초 미만인 경우에만 [B]가 가능하다고 생각합니다. 주 스레드는 5 초간 휴면하고 은 join()의 5 초 시간 내에 완료됩니다.

join() 호출 후에도 worker에 10 초 이상의 시간 초과가 발생할 수 있기 때문에 호출 할 수 있습니다. 그런 다음 [A] (몇 초 후 하위 프로세스 완료) 또는 [C] (하위 프로세스 완료)를 얻을 수 있습니다.

항상 [B], 그래서 메인 스레드가 대기 worker 완료 될 때까지 join()의 timeout 인수를 제거 취득 (또는 루프의 외부에 킬 (kill) 전화를 거는 10 초 이내에 프로세스를 종료 확인)합니다.

0

변경

 if self.event.is_set(): 
      self.process.terminate() 
      self.process.kill() 
      break; 

 if self.event.is_set(): 
      self.process.terminate() 
      self.process.wait() 
      break 

에 세미콜론은 문제가 여기에 있다는 것을 죽은 공짜입니다.

wait()이 없으면 스레드가 가끔 work1.join(5)의 차단을 해제하는 경우가 있습니다. 이러한 경우, threading.active_count() @ A.Rodas 말한대로, work1.join(5)이 (가) work1이 완료 될 때까지 해제되지 않습니다에 참여하기 위해 work1.join()을해야한다, (2)

를 돌려줍니다. 만약 당신이 연속적으로 다음 killterminate 전화 싶어 왜 그런데


, 나는 확실하지 않다. Unix에서 kill은 더 심각한 형태의 종결 코드입니다. Windows에서는 동일합니다. 따라서 kill을 호출 할 경우 종료를 호출 할 필요가 없습니다.

subprocess에 의해 호출 된 프로그램을 알고 있기 때문에 종료하기에 충분하면 프로그램을 중지해야합니다.

따라서 또는 self.process.kill() 중 하나만 필요합니다.