gdb로python 디버깅

7574 단어 Pythongdbtech

개시하다


gdb로 ptyhon 프로세스를 연결하고 ptyhon 영역을 디버깅하는 방법입니다.
gdb에서 C/C++ 디버깅을 할 수 있지만,python 영역은 쉽게 볼 수 없기 때문에,pythn-debuginfo를 사용하여 디버깅 방법을 기록하십시오.
정보의 출처는 참고 문헌[1]을 참조한다.

언제 쓸 수 있을까요?

  • pdb에서 스레드 사이의 부접/해촉을 진행할 수 없기 때문에 다중 스레드 디버깅을 하려고 합니다
  • 특정 환경에서만 발생하는 오류, 장시간 실행 후 종료 등 로그 출력의 디버깅 등 조사가 까다롭다
  • IDE에서 검사기 등의 환경,pydev 등을suspend로 사용할 수 없으면 스레드가 멈추지 않습니다
  • 개발 환경

  • python2.7/python3.6.8(모두yum에 설치)
  • Cent OS 7
    CentOS Linux release 7.7.1908 (Core)
  • GNU gdb
    GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-115.el7
  • 설정

  • 디버깅용 창고 활성화,ptyhon-debuginfo 설치
    (python 2.7의 경우)
  • # debuginfo-install python
    
    (python 3의 경우)
    # debuginfo-install python3 libgcc
    
    저도 다음과 같은 방법을 써서 시험용 창고를 효과적으로 설치했지만 debuginfo-install이 더 똑똑해 보여서 수정하고 있습니다.yum --disablerepo='*' --enablerepo='*-debug*' install python-debuginfopytohon3에서libgcc의 debuginfo를 설치해야 한다는 욕을 먹고 기록을 추가했다.다른 포장이 필요할지도 몰라요.만약 부족하다면, 다음에 기술한 gdb가 시작될 때, 설치해야 할 물건에 대해 메시지를 출력해야 합니까?

    사용법

  • 디버깅할 프로세스의 ID 가져오기
  • 아래 명령을 통해 gdb를 시작하고 첨부
  • $ gdb python <PID>
    
  • psyhon-debuginfo에 사용되는 명령 파일 실행
    (python 2.7의 경우)
  • (gdb) source /usr/lib/debug/usr/lib64/libpython2.7.so.1.0.debug-gdb.py
    
    (python 3의 경우)
    (gdb) source /usr/lib/debug/usr/lib64/libpython3.6dm.so.1.0-3.6.8-18.el7.x86_64.debug-gdb.py
    
    이번에는 3.6.8을 사용했습니다./usr/lib/debug/usr/lib64/아래를 참조하여 해당 버전의 파일을 적절하게 적용하십시오.
  • 다음 명령을 사용할 수 있기 때문에 디버깅
  • py-list이 범위의 Pythhon 코드 출력
  • py-btPythhon 코드의 뒤로 추적
  • py-up파이썬 스택
  • py-down파이썬 스택 아래
  • py-printPython 스택의 변수 표시
  • py-localsPython 스택 변수 목록 표시
  • 이상의 설명은 참고 문헌[2]을 인용했다.
    나는 사용 방법 등의 도움을 찾았지만 찾지 못했다.
    정보, 명령 파일*이 있을 수 있습니다.debug-gdb.py의 소스를 보고, 어떤 지령을 사용할 수 있는지/어떻게 사용하는 것이 비교적 빠를 수 있는지 봅시다.

    데모

  • 잠금 해제를 실행하는python 프로그램
    무엇이든지 좋습니다. 다음은 이 보도를 위해 제작을 시도하는 절차입니다.
  • pythondebugggb.py
    pythondebugggb.py
    import threading
    import time
    
    class MultiThreadDeadLock(object):
        '''
        MultiThreadDeadLock
        デッドロックを意図的におこすテスト用の実装
        '''
    
        def __init__(self):
            '''
            constructor
            '''
            self._counter = 0
            self.main()
    
        def increment(self, lock):
            '''
            カウンタをインクリメントします。
            :param lock: (object) threading.Lock()で取得した排他用オブジェクト
            :return: None
            '''
            while True:
                time.sleep(0.1) # スレッド間の割り込み用に少し待たせる
                lock.acquire()
                self._counter += 1
                lock.release()
    
        def print_counter(self, lock):
            '''
            現在のカウンタを表示します。
            デッドロックを再現するため3より大きい場合に意図的にロックを解放せずにExceptionをraiseします。
            :param lock: (object) threading.Lock()で取得した排他用オブジェクト
            :return: None
            '''
            while True:
                time.sleep(0.1) # スレッド間の割り込み用に少し待たせる
                lock.acquire()
                print("counter = {}".format(self._counter))
                if self._counter > 3:
                    # 意図的にExceptionをraiseして、デッドロックさせる。
                    # 実際には、予期しないところでExceptionがraiseされることだろう...
                    raise RuntimeError()
                lock.release()
    
        def main(self):
            '''
            メイン処理
            :return: None
            '''
            lock = threading.Lock()
    
            inc_thread = threading.Thread(target=self.increment, args=(lock,))
            print_thread = threading.Thread(target=self.print_counter, args=(lock,))
            inc_thread.start()
            print_thread.start()
            inc_thread.join()
            print_thread.join()
    
    if __name__ == '__main__':
        MultiThreadDeadLock()
    

  • 프로세스 ID 확인
    ps 명령어나 pgrep로 찾아보세요.

  • gdb로 연결, 명령 파일 *.debug-gdb.실행py,실행py-bt
  • $ gdb python3 7066
    GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-115.el7
    Copyright (C) 2013 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
    and "show warranty" for details.
    This GDB was configured as "x86_64-redhat-linux-gnu".
    For bug reporting instructions, please see:
    <http://www.gnu.org/software/gdb/bugs/>...
    Reading symbols from /usr/bin/python3.6...Reading symbols from /usr/lib/debug/usr/bin/python3.6.debug...done.
    done.
    (中略)
    done.
    Loaded symbols for /lib64/libgcc_s.so.1
    0x00007f5a083e8afb in futex_abstimed_wait (cancel=true, private=<optimized out>, 
        abstime=0x0, expected=0, futex=0x7f59fc000c10)
        at ../nptl/sysdeps/unix/sysv/linux/sem_waitcommon.c:43
    43	      err = lll_futex_wait (futex, expected, private);
    (gdb) source /usr/lib/debug/usr/lib64/libpython3.6dm.so.1.0-3.6.8-18.el7.x86_64.debug-gdb.py
    (gdb) py-bt
    Traceback (most recent call first):
      <built-in method acquire of _thread.lock object at remote 0x7f5a011328c8>
      File "/usr/lib64/python3.6/threading.py", line 1072, in _wait_for_tstate_lock
        elif lock.acquire(block, timeout):
      File "/usr/lib64/python3.6/threading.py", line 1056, in join
        self._wait_for_tstate_lock()
      File "pythondebuggdb.py", line 68, in main
        inc_thread.join()
      File "pythondebuggdb.py", line 26, in __init__
        self.main()
      File "pythondebuggdb.py", line 72, in <module>
        MultiThreadDeadLock()
    
    스레드 전환

  • (gdb) info threads
      Id   Target Id         Frame 
      2    Thread 0x7f5a01094700 (LWP 7067) "python3" 0x00007f5a083e8afb in futex_abstimed_wait (cancel=true, private=<optimized out>, abstime=0x0, expected=0, futex=0x2471020)
        at ../nptl/sysdeps/unix/sysv/linux/sem_waitcommon.c:43
    * 1    Thread 0x7f5a08d20740 (LWP 7066) "python3" 0x00007f5a083e8afb in futex_abstimed_wait (cancel=true, private=<optimized out>, abstime=0x0, expected=0, futex=0x7f59fc000c10)
        at ../nptl/sysdeps/unix/sysv/linux/sem_waitcommon.c:43
    (gdb) thread 2
    [Switching to thread 2 (Thread 0x7f5a01094700 (LWP 7067))]
    #0  0x00007f5a083e8afb in futex_abstimed_wait (cancel=true, private=<optimized out>, 
        abstime=0x0, expected=0, futex=0x2471020)
        at ../nptl/sysdeps/unix/sysv/linux/sem_waitcommon.c:43
    43	      err = lll_futex_wait (futex, expected, private);
    
  • py-list에서 이 줄을 확인하는 동시에py-bt로 다른 라인 측면의 창고 추적을 확인
  • 두 라인 모두 lock입니다.acquire () 에 멈춰 있어서 사라진 자물쇠인 줄 알았어요.

    참고 문헌


    다음은 각주 참조
    각주
    Debugging an inactive python process ↩︎
    파이톤으로 gdb를 조작합니다. ↩︎

    좋은 웹페이지 즐겨찾기