2011-06-01 38 views
2

我創建一個線程爲分離時出現問題。這裏是我寫的代碼:Pthread創建爲分離

void* testFunction() { 

    pthread_attr_t attr; 
    int chk,rc; 

pthread_attr_init(&attr); 
printf("thread_attr_init: %d\n",rc); 

pthread_attr_getdetachstate(&attr, &chk); 
printf("thread_attr_getdetachedstate: %d\n",rc); 

if(chk == PTHREAD_CREATE_DETACHED) 
    printf("Detached\n"); 
else if (chk == PTHREAD_CREATE_JOINABLE) 
    printf("Joinable\n"); 

return NULL; 
} 


int main (int argc, const char * argv[]) { 

pthread_t thread1; 
pthread_attr_t attr; 

int rc; 

rc = pthread_attr_init(&attr); 

printf("attr_init: %d\n",rc); 
rc = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 
printf("attr_setdetachedstate: %d\n",rc); 

rc = pthread_create(&thread1, &attr, testFunction, NULL); 
printf("attr_create: %d\n",rc); 

sleep(4); 
pthread_cancel(thread1); 

return 0; 
} 

問題是testFunction()總是打印「可連接」。任何人都可以告訴我哪裏出錯了嗎?

回答

6

您的testFunction未檢查有關當前線程的任何內容,而僅檢查您剛創建的全新屬性對象的最初分離標誌。而且,在POSIX線程API中完全不可能恢復創建線程的屬性,或者確定線程是否被分離。你只需要相信實現的行爲是按照需要的,就像你必須相信那樣,如果malloc(100)返回一個非空指針,它指向一個可以存儲至少100個字節的位置。這是C的本質。

+0

奇數。至少,這意味着它將更難以調試。不過謝謝。 – Saphrosit 2011-06-02 22:57:04

+0

我很困惑這是如何增加任何難度的調試。線程是否被分離純粹是創建線程的代碼與線程之間的契約的問題。你*通常*想要決定一個線程在創建時是否應該被分離或連接。唯一不是這樣的情況是當你的線程正在執行一個「父母」可能想等待的任務,但是它可能想要放棄的任務時,留下「未被授權」標誌在後臺完成其任務並且緩存/記憶結果。 – 2011-06-02 23:58:28

1

您的testFunction不讀取當前線程的屬性。如果您的系統中存在pthread_attr_init(),pthread_getattr_np()可能會有所幫助,但是您需要將pthread_t傳遞給正在查詢的線程。

+0

如果它不存在呢?我正在運行MacOSX 10.6.7,我正在使用XCode 4.0.2進行開發...... – Saphrosit 2011-06-01 14:45:43

+0

它是FreeBSD上的pthread_attr_get_np(),在Mac OSX上很可能也是如此。 – Mel 2011-06-01 15:42:05

+0

甚至沒有'pthread_attr_get_np()'似乎可用... – Saphrosit 2011-06-01 17:09:43

4

嘗試運行下面的代碼。這應該可以消除混淆。

/*------------------------------- join_01.c --------------------------------* 
On Linux, compile with: 
cc -std=c99 -pthread join_01.c -o join_01 
    gcc join_01.c -o join_01 -std=c99 -lpthread (Ubuntu) 

Check your system documentation how to enable C99 and POSIX threads on 
other Un*x systems. 

Copyright Loic Domaigne. 
Licensed under the Apache License, Version 2.0. 
*--------------------------------------------------------------------------*/ 

#include <unistd.h> // sleep() 
#include <pthread.h> 
#include <stdio.h> 
#include <stdlib.h> // EXIT_SUCCESS 
#include <string.h> // strerror() 
#include <errno.h> 

/***************************************************************************/ 
/* our macro for errors checking           */ 
/***************************************************************************/ 
#define COND_CHECK(func, cond, retv, errv) \ 
if ((cond)) \ 
{ \ 
    fprintf(stderr, "\n[CHECK FAILED at %s:%d]\n| %s(...)=%d (%s)\n\n",\ 
       __FILE__,__LINE__,func,retv,strerror(errv)); \ 
    exit(EXIT_FAILURE); \ 
} 

#define ErrnoCheck(func,cond,retv) COND_CHECK(func, cond, retv, errno) 
#define PthreadCheck(func,rc) COND_CHECK(func,(rc!=0), rc, rc) 

/*****************************************************************************/ 
/* thread- dummy thread              */ 
/*****************************************************************************/ 
void* 
thread(void* ignore) 
{ 
    sleep(1); 
    return NULL; 
} 

/*****************************************************************************/ 
/* detach_state. Print detachstate of a thread.        */ 
/*****************************************************************************/ 
/* 
* We find out indirectly if a thread is detached using pthread_join(). 
* If a thread is detached, then pthread_join() fails with EINVAL. 
* Otherwise the thread is joined, and hence was joinable. 
* 
*/ 
void 
detach_state(
    pthread_t tid, // thread to check detach status 
    const char *tname // thread name 
    ) 
{ 
    int rc; // return code 

    rc = pthread_join(tid, NULL); 
    if (rc==EINVAL) 
    { 
     printf("%s is detached\n", tname); 
    } 
    else if (rc==0) 
    { 
     printf("%s was joinable\n", tname); 
    } 
    else 
    { 
     printf("%s: pthread_join() = %d (%s)\n", 
      tname, rc, strerror(rc) 
      ); 
    } 
} 

/*****************************************************************************/ 
/* main- main thread               */ 
/*****************************************************************************/ 
int 
main() 
{ 
    pthread_t tid1, tid2, tid3; // thread 1,2 and 3. 
    pthread_attr_t attr;  // thread's attribute 
    int rc; // return code 

    /*--------------------------------------------------------*/ 
    /* 1st test: normal thread creation      */ 
    /*--------------------------------------------------------*/ 
    rc = pthread_create(&tid1, NULL, thread, NULL); 
    PthreadCheck("pthread_create", rc); 
    detach_state(tid1, "thread1"); // expect: joinable 

    /*--------------------------------------------------------*/ 
    /* 2nd test: detach thread from main thread    */ 
    /*--------------------------------------------------------*/ 
    rc = pthread_create(&tid2, NULL, thread, NULL); 
    PthreadCheck("pthread_create", rc); 
    rc = pthread_detach(tid2); 
    PthreadCheck("pthread_detach", rc); 
    detach_state(tid2, "thread2"); // expect: detached 

    /*--------------------------------------------------------*/ 
    /* 3rd test: create detached thread      */ 
    /*--------------------------------------------------------*/ 

    // set detachstate attribute to DETACHED 
    // 
    rc=pthread_attr_init(&attr); 
    PthreadCheck("pthread_attr_init", rc); 
    rc=pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 
    PthreadCheck("pthread_attr_setdetachstate", rc); 

    // create thread now 
    // 
    rc = pthread_create(&tid3, &attr, thread, NULL); 
    PthreadCheck("pthread_create", rc); 
    detach_state(tid3, "thread3"); 

    /*--------------------------------------------------------*/ 
    /* that's all folks!          */ 
    /*--------------------------------------------------------*/ 
    return EXIT_SUCCESS; 
} 

輸出應該

$ ./join_01 
thread1 was joinable 
thread2 is detached 
thread3 is detached