2014-12-01 41 views
0

我有一個服務器應用程序,它在隊列中等待,獲取傳入消息,併產生一個線程來處理收到的消息併發送答覆。是我使用pthread在分離的線程上創建錯誤11

的並行線程部分/選項如下:

pthread_attr_t child_attr; 
pthread_attr_setdetachstate(&child_attr, PTHREAD_CREATE); 

// other code here 

while (true) 
{ 

    // code here to wait on valid message (msg) 
    if (valid_message(msg)) 
    { 
     pthread_t child_thread; 
     MessageProcessor * processor = new MessageProcessor(); 
     if (0 == pthread_create(&child_thread, &child_attr, processor->process, (void *) msg)) 
     { 
      printf("Thread dispatch successful\n"); 
     } 
     else 
     { 
      printf("Error %d: could not create thread\n", errno); 
     } 
    } 
} 

// other code here 
pthread_attr_destroy(&child_attr); 

我每次運行它,顯示的錯誤代碼是,這顯然將表明我的過程已經越過了最大線程閾值,基於我在互聯網上閱讀的內容。

然而,

  • 這是從一開始就發生的事情,而不是之後我已經運行了一段時間的應用程序。
  • 線程創建爲分離的,所以我不應該使用pthread_join()。
  • 我使用top以及ps -p <PID> -lfT來檢查應用程序有多少線程正在使用,並且只有3個線程(一個用於主服務器,一個用於消息接收器,另一個用於隊列系統的消息發送器)

PS

「過程」 的原型如下:

class MessageProcessor 
{ 
    MessageProcessor(); 
    static void * MessageProcessor::process(void * arg); 
} 

void * MessageProcessor::process(void * arg) 
{ 
    // do something here with arg 
} 
+0

由「顯示錯誤代碼」假設你實際上意味着「這是傳遞到過程中的信號」,信號11 SIGSEGV是,這是違反分段的情況,通常是由於指針使用不當造成的。如果11實際上是errno變量的報告值,那麼可能是EAGAIN,它通常表示暫時失敗,應該在稍後重試。 – twalberg 2014-12-01 21:54:12

+0

@twalberg通過顯示的錯誤代碼,我的意思是在我的代碼中printf()中顯示的錯誤 - 這是'errno'。每分鐘接收一條消息10分鐘,直到發送有效的回覆,因此重試正在進行。但是,每次收到郵件時,錯誤始終爲11. – Sagar 2014-12-01 22:03:44

+0

您是否有機會更改堆棧大小?你有很多線程本地存儲數據? EAGAIN表示資源短缺,而不是特定的資源。線程分配需要:新的進程/線程,堆棧的內存和TLS段的副本。 – Dummy00001 2014-12-01 22:11:10

回答

1

你的代碼是使用未初始化的child_attr,你必須做的:

pthread_attr_init(&child_attr); 
    pthread_attr_setdetachstate(&child_attr, PTHREAD_CREATE_DETACHED); 
+0

工作正常!謝謝! – Sagar 2014-12-02 19:08:35

1

錯誤號11通常EAGAIN,在這種情況下,它是指N o更多進程(linux將線程視爲輕量級進程 - 請參閱克隆手冊頁)。

while(true)循環將永遠運行進程。

請注意,如果您有像ARM這樣的特殊版本的Linux,則錯誤編號11不需要爲EAGAIN。所以用一粒鹽來回答這個問題。

+0

while(true)實際上等待一個有效的消息在繼續之前被接收(如上面的代碼註釋中所示),所以我知道它不會創建無限數量的線程。另外,正如我所說的,我檢查了該進程在運行時的線程數量,只有3. – Sagar 2014-12-01 22:01:36

+0

真實但沒有密切關係。 'errno'在這裏是紅鯡魚。 – pilcrow 2014-12-02 14:16:21

4

與所有pthreads函數一樣,pthread_create不會將errno設置爲報告錯誤,而是返回錯誤編號。要查看失敗原因,您需要輸出返回值,而不是errno

const int err = pthread_create(&child_thread, &child_attr, processor->process, (void *) msg); 

if (err == 0) 
    printf("Thread dispatch successful\n"); 
else 
    printf("Error %d: could not create thread\n", err); 

POSIX指定errno像這樣:

錯誤號的值應只對函數的調用,這就是它明確規定後,設置被定義[...]的errno的值只能在函數的返回值指示爲有效時才被檢查。

由於pthread_create未記錄設置errno這意味着值pthread_create呼叫後沒有定義,並且不應該被檢查。

+2

我認爲最後一句話嚴格來說太強了。任何函數*可能會改變錯誤 - 但是這個值是沒有意義的,除非被記錄如此。 – pilcrow 2014-12-02 03:25:57

+0

@pilcrow,好點,謝謝 - 我已經更新了 – 2014-12-02 10:08:23

+0

這不是* undefined *。它總是有一個合適的價值:在開始時它有0,任何人都可以稍後改變它。它已被定義,但如果在庫/函數調用之前和之後未檢查「errno」,則可能無法正確反映故障。 – 2014-12-02 10:13:30