2016-08-16 3 views
1

멀티 스레드 프로그램이 있습니다. 프로그램이 실행 중일 때 pexpect.spawn()을 호출하는 동안 일부 스레드가 정지하는 경우가 있습니다.쉘을 생성 할 때 pexpect 다중 스레드 프로그램이 중단됩니다.

이 프로그램은 각 스레드에 Session 개체를 만들고 Session 개체는 만들어지면 pexpect 세션을 생성합니다. 프로그램에서 각 Session 객체는 하나의 특정 스레드에 바인딩됩니다. 다음

class CustomizedThread(threading.Thread): 
    __init__(self, thread_name): 
     super().__init__(name=thread_name) 

    def run(self): 
     session = Session() 
     ... 

class Session: 
    __init__(self, session_name): 
     self.name = session_name 
     print('Thread {} is spawning a shell in session {}.'.format(
      threading.currentThread(), session.name)) 
     self.pexpect_session = pexpect.spawn('/bin/sh') 
     print('Thread {} finished spawning a shell in session {}.'.format(
      threading.currentThread(), session.name)) 
     self.pexpect_session.sendline('ssh MACHINE_NAME') 
     ... 

    __del__(self): 
     print('Thread {} is cleaning up session {}.'.format(
      threading.currentThread(), session.name)) 
     self.pexepect_session.close(force=True) 

는 세션의 소멸자 스레드 2

... 
Thread 1 is spawning a shell in session 1. 
Thread 1 finished spawning a shell in session 1. 
Thread 2 is spawning a shell in session 2. 
Thread 2 is cleaning up session 1. 

현수 부착시) (pexpect.spawn하는 통화 중에 트리거 한 개체 스레드 2 걸려 예시 출력 프로세스를 gdb로 바꾼다. 다음과 같은 스택 추적을 얻는다. 그것은 파일 기술자에 예외 메시지를 작성하려고 할 때 스레드가 걸려 보여줍니다 : "종료"

(gdb) where 
#0 0x00007fff9628391a in write() from /usr/lib/system/libsystem_kernel.dylib 
#1 0x000000010ed7aa22 in _Py_write_impl (fd=2, buf=0x10f3f1010, count=76, gil_held=1) at ../Python/fileutils.c:1269 
#2 0x000000010ed7a9a1 in _Py_write (fd=2, buf=0x10f3f1010, count=76) at ../Python/fileutils.c:1327 
#3 0x000000010ede8795 in _io_FileIO_write_impl (self=0x10f3875f8, b=0x7000013dd168) at ../Modules/_io/fileio.c:840 
#4 0x000000010ede7957 in _io_FileIO_write (self=0x10f3875f8, arg=0x11312c148) 
at ../Modules/_io/clinic/fileio.c.h:245 
#5 0x000000010ebbfd72 in PyCFunction_Call (func=0x112ed7b98, args=0x112fc6330, kwds=0x0) 
at ../Objects/methodobject.c:134 
#6 0x000000010eb2803d in PyObject_Call (func=0x112ed7b98, arg=0x112fc6330, kw=0x0) at ../Objects/abstract.c:2165 
#7 0x000000010eb290de in PyObject_CallMethodObjArgs (callable=0x112ed7b98, name=0x10f234d40) 
at ../Objects/abstract.c:2394 
#8 0x000000010edf0456 in _bufferedwriter_raw_write (self=0x10f25de58, 
start=0x10f3f1010 "\nThread 2 is cleaning up session 1. \"terminated\" is 0, but there was no child process. Did someone else call waitpid() on our process?\n"..., 
len=76) at ../Modules/_io/bufferedio.c:1847 

예외 메시지를 '0이지만, 자식 프로세스는 없었다. 다른 사람이 우리 프로세스에서 waitpid()를 호출 했습니까? ' pexpect 세션 pexpect의 산란() 메소드

self.pexepect_session.close(force=True) 

또한 폐쇄 라인으로부터되면, 프로세스는 실행하기 (I는 GDB에 부착 공정) '/ 빈/쉬'갈래 상위 프로세스에 예외 메시지를 작성하도록 파이프가 작성됩니다.

forked 프로세스 가비지가 다른 스레드의 Session 개체를 수집 한 것처럼 보이지만 다른 스레드에서 세션을 닫으려고 할 때 예외가 발생했습니다. 예외 메시지가 다른 쪽에서 읽혀 져야하기 때문에 프로세스가 파이프에 예외 메시지를 쓰려고합니다.

답변

0

스레드를 사용하여 쉘을 생성하고 pexpect를 사용하여 ssh를 실행하는 대신 Paramiko을 사용하십시오. ssh를 구현하는 매우 훌륭하고 성숙한 라이브러리입니다. 어쨌든 파이썬에서 더 효율적일 수있는 단일 스레드에서 여러 세션을 실행할 수 있습니다. 여기를 참조하십시오 : Long-running ssh commands in python paramiko module (and how to end them)

+0

감사합니다. 이 프로그램은 SSH 이상의 것을 필요로합니다. 일부 임베디드 보드에 telnet을 사용하는 경우에도 사용되며, Paramiko는이를 지원하지 않습니다. –

+0

@ Tsu-Hao : 그러면 https://docs.python.org/2/library/telnetlib.html은 어떻습니까? –

0

멀티 프로세싱으로 전환하면 문제를 해결할 수 있습니다. 멀티 스레딩과 포크를 혼합하는 것은 문제가 있습니다.

관련 문제