簡體   English   中英

保護主線程免受工作線程中的錯誤的影響

[英]Protecting main thread from errors in worker thread

當使用posix線程時,是否有某種方法可以“保護”主線程免受工作線程引起的錯誤(例如解除引用的空指針,除零等)。 “工作線程”是指由pthread_create()創建的posix線程。

不幸的是,我們不能使用例外 - 所以沒有“捕獲”等。

這是我的測試程序(C ++):

void* workerThreadFunc(void* threadId) {
  int* a = NULL;
  *a = 5; //Error (segmentation fault)
  pthread_exit(NULL);
}

int main() {
  cout << "Main thread start" << endl;

  pthread_t workerThread;
  pthread_attr_t attr;
  pthread_attr_init(&attr);
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
  pthread_create(&workerThread, &attr, workerThreadFunc, (void*)0);
  pthread_join(workerThread, NULL);

  cout << "Main thread end" << endl;
}

在上面的示例中,workerThread引起的錯誤將終止整個程序。 但我希望主線程繼續運行,盡管這個錯誤。 這有可能實現嗎?

聽起來像你應該使用多個進程,而不是線程。 獨立進程會自動受到保護,免受其他進程中發生的這類錯誤的影響。

您可以使用管道或共享內存(或其他形式的IPC)在線程之間傳遞數據,這樣做的另一個好處就是只共享您要共享的內存,因此工作線程中的錯誤無法踩到堆棧上主“線程”,因為它是一個單獨的進程,具有單獨的地址空間。

線程可能很有用,但有幾個缺點,有時在單獨的進程中運行更合適。

我能想到這樣做的唯一方法是注冊一個信號處理程序,它可以代替中止程序,取消當前運行的線程,如下所示:

void handler(int sig)
{
    pthread_exit(NULL);
}

signal(SIGSEGV, handler);

但請注意,這是不安全的,因為pthread_exit未被列為信號處理程序內的安全系統調用之一。 它可能會起作用,也可能不起作用,這取決於您正在運行的O / S,以及您正在處理的信號。

假設您的系統使用POSIX中的信號排序(盡管可能屬於“無例外”規則),那么POSIX說:

在生成時,應確定是為過程還是為過程中的特定線程生成了信號。 應該為導致生成信號的線程生成由可歸因於特定線程的某些動作(例如硬件故障)生成的信號。

因此,您可以在每個pthread的基礎上處理SIGSEGVSIGFPE等(但請注意,您只能為整個過程設置一個信號處理函數)。 因此,您可以“保護”該過程,使其免於因單個pthread失敗而停止死亡......直至某一點。 當然,問題在於你可能會發現很難分辨出進程的狀態 - 失敗的pthread和所有其他的pthreads - 失敗的pthread可能會持有多個互斥鎖。 失敗的pthread可能會使一些共享數據結構混亂。 誰知道什么樣的糾結事物 - 除非pthreads基本上是獨立的。 也許可以安排其他pthreads“優雅地”關閉......而不是崩潰和燃燒。 最終,它可能更安全地阻止所有pthreads死亡,而不是試圖繼續在一些不太明確的狀態。 它完全取決於應用程序的性質。

沒有什么是無用的......線程可以比流程更容易地相互通信,並且啟動和停止成本更低 - 流程不易受到其他流程故障的影響。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM