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() всегда печатает "Joinable". Может ли кто-нибудь сказать мне, где я ошибаюсь?


person Manlio    schedule 01.06.2011    source источник


Ответы (3)


Ваш testFunction ничего не исследует в текущем потоке, а просто изначально отсоединенный флаг совершенно нового объекта атрибута, который вы только что создали. Более того, в API потоков POSIX совершенно невозможно восстановить атрибуты, с которыми был создан поток, или определить, является ли поток отсоединенным или нет. Вы просто должны верить, что реализация ведет себя так, как требуется, точно так же, как вы должны верить, что если malloc(100) возвращает ненулевой указатель, он указывает на место, в котором вы можете хранить не менее 100 байтов. Такова природа С.

person R.. GitHub STOP HELPING ICE    schedule 01.06.2011
comment
Странный. По крайней мере, это означает, что отладить его будет еще сложнее. Однако спасибо. - person Manlio; 03.06.2011
comment
Я смущен, как это может усложнить отладку. Является ли поток отсоединенным или нет, зависит исключительно от контракта между кодом, создавшим поток, и потоком. Вы обычно хотите решить, должен ли поток быть отсоединенным или присоединяемым при его создании. Единственный случай, когда это может быть не так, - это когда ваш поток выполняет задачу, которую родитель может захотеть подождать, но которую он может захотеть отказаться, оставив флаг отказа, чтобы завершить свою задачу в фоновом режиме и кэшировать/запоминать результат. - person R.. GitHub STOP HELPING ICE; 03.06.2011

Попробуйте запустить следующий код. Это должно устранить путаницу.

/*------------------------------- 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
person enthusiasticgeek    schedule 04.02.2013

Ваша testFunction не читает атрибуты текущего потока. Вместо вызова pthread_attr_init() вам может помочь pthread_getattr_np(), если он присутствует в вашей системе, но вам нужно будет передать pthread_t для рассматриваемого потока туда, откуда он запрашивается.

person crazyscot    schedule 01.06.2011
comment
А если его нет? Я использую MacOSX 10.6.7, я разрабатываю XCode 4.0.2... - person Manlio; 01.06.2011
comment
Это pthread_attr_get_np() во FreeBSD, поэтому, вероятно, то же самое в Mac OSX. - person Mel; 01.06.2011
comment
pthread_getattr_np, а также нестандартны и вам не следует их использовать. - person R.. GitHub STOP HELPING ICE; 02.06.2011