切換語言為:簡體

Python 應用開發中遇到的卡死問題排查過程

  • 爱糖宝
  • 2024-08-01
  • 2101
  • 0
  • 0

問題背景

最近在開發一款自動化的應用,其中有一個自動化任務會由下面這三個按鈕控制:

Python 應用開發中遇到的卡死問題排查過程

邏輯也很簡單,我大概畫下圖就是這樣的:

Python 應用開發中遇到的卡死問題排查過程

但是,在測試時,卻發現了問題:

當我點選暫停任務後,此時子執行緒被阻塞。如果我這個時候點選停止,那麼就會任務結束。

之後,如果我再點選開始執行,整個應用就會卡死,非常離譜。

以下是簡化後的程式碼:

import threading
import time
from sample_singleton import singleton

@singleton class TestThreadingEvent: def init(self): self._stop_event = threading.Event() self._pause_event = threading.Event() self._thread = None

def set_stop(self):
    self._stop_event.set()

def set_pause(self):
    self._pause_event.set()

def start(self):
    print("任務開始")
    self._stop_event.clear()
    self._pause_event.set()
    print("開始執行")
    self._thread = threading.Thread(target=self._run)
    self._thread.start()

def _run(self):
    count = 0
    while True:
        if self._stop_event.is_set():
            print("任務被成功停止")
            return
        print(f"是否需要暫停:{not self._pause_event.is_set()}")
        self._pause_event.wait()
        # 執行任務
        print(f"do something: {count}")
        time.sleep(1)
        count += 1

def pause(self):
    print("點選了暫停")
    self._pause_event.clear()
    time.sleep(2)

def stop(self):
    print("點選了停止")
    self._stop_event.set()
    print("成功停止")
    if self._thread is not None:
        self._thread.join()  # 確保執行緒終止

按照程式碼邏輯,我期待的結果是點選停止後,再次點選開始就可以開始重新執行,但是,雖然第一次顯示停止了,可如果想再次開始,程式就會卡住不動了,下面為測試時輸出的結果:

我點選了開始
任務開始
開始執行
是否需要暫停:False
do something: 0
我點選了暫停
是否需要暫停:True
我點選了停止
成功停止
# 然後在這裏卡死

昨天下午一直在程式碼中斷點找原因,搞了半天,都沒能解決,下班前我甚至都在懷疑是不是 Python 程式碼的問題,想去看看原始碼找原因了。

找出原因

不過簡化程式碼,確實比較有效,當我把整個流程簡化成上面的程式碼,就比較方便找出問題出在哪裏了。

是因為,當我點選“暫停”後,子執行緒進入阻塞狀態。當執行“停止”操作時,使用了 self._thread.join(),這會導致主執行緒阻塞,直到子執行緒 self._thread 完成。然而,如果子執行緒因阻塞狀態無法完成,就會導致主執行緒永久等待,結果是主執行緒卡死。

後面我看了下我們實際開發的應用程式碼,問題要更復雜點,但說到底,都是執行緒阻塞狀態沒有得到正確處理,導致的卡死。

解決辦法

由於主執行緒卡死是因為子執行緒的阻塞狀態造成的,可以透過以下兩種方法解決:

  1. 處理子執行緒阻塞:引入超時控制,確保子執行緒在合理時間內完成任務,並在必要時修改子執行緒的阻塞狀態,以避免主執行緒長時間等待。

  2. 銷燬子執行緒:如果子執行緒在完成任務後不再需要重複使用,可以考慮在結束時直接銷燬該執行緒,以避免阻塞主執行緒。

這兩種方法可以有效避免主執行緒因子執行緒阻塞而卡死的問題。

0則評論

您的電子郵件等資訊不會被公開,以下所有項目均必填

OK! You can skip this field.