Pthread create as detached
Asked Answered
R

4

4

I have a problem creating a thread as detached. Here's the code I wrote:

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;
}

The problem is that testFunction() always print "Joinable". Can anyone tell me where I'm getting wrong?

Rambow answered 1/6, 2011 at 14:25 Comment(0)
S
7

Your testFunction is not examining anything about the current thread, rather just the initially-detached flag of a completely new attribute object you just created. Moreover, it is completely impossible, in the POSIX threads API, to recover the attributes a thread was created with or determine if a thread is detached or not. You simply have to trust that the implementation behaves as required, just like you have to trust that, if malloc(100) returns a non-null pointer, it points to a location at which you can store at least 100 bytes. This is the nature of C.

Schenk answered 1/6, 2011 at 22:9 Comment(2)
Odd. At least, it means it'll even more difficult to debug it. However thanks.Rambow
I'm confused how this can add any difficulty to debugging. Whether a thread is detached or not is purely a matter of the contract between the code that created the thread and the thread. You usually want to decide on whether a thread should be detached or joinable when creating it. The only time this might not be the case is when your thread is performing a task that the "parent" might want to wait on, but which it might want to abandon, leaving the "disowned" flag to finish its task in the background and cache/memoize the result.Schenk
K
8

Try running the following code. That should clear the confusion.

/*------------------------------- 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;
}

The output should be

$ ./join_01 
thread1 was joinable
thread2 is detached
thread3 is detached
Kempe answered 4/2, 2013 at 22:57 Comment(0)
S
7

Your testFunction is not examining anything about the current thread, rather just the initially-detached flag of a completely new attribute object you just created. Moreover, it is completely impossible, in the POSIX threads API, to recover the attributes a thread was created with or determine if a thread is detached or not. You simply have to trust that the implementation behaves as required, just like you have to trust that, if malloc(100) returns a non-null pointer, it points to a location at which you can store at least 100 bytes. This is the nature of C.

Schenk answered 1/6, 2011 at 22:9 Comment(2)
Odd. At least, it means it'll even more difficult to debug it. However thanks.Rambow
I'm confused how this can add any difficulty to debugging. Whether a thread is detached or not is purely a matter of the contract between the code that created the thread and the thread. You usually want to decide on whether a thread should be detached or joinable when creating it. The only time this might not be the case is when your thread is performing a task that the "parent" might want to wait on, but which it might want to abandon, leaving the "disowned" flag to finish its task in the background and cache/memoize the result.Schenk
E
1

Your testFunction is not reading the current thread's attributes. Instead of calling pthread_attr_init(), pthread_getattr_np() might help you if it's present on your system, but you will need to pass the pthread_t for the thread in question onto wherever it's being queried from.

Ebba answered 1/6, 2011 at 14:34 Comment(3)
What if it's not present? I'm running MacOSX 10.6.7, I'm developing with XCode 4.0.2...Rambow
It's pthread_attr_get_np() on FreeBSD, so likely the same on Mac OSX.Canvas
pthread_getattr_np and likewise are nonstandard and not something you should be using.Schenk
Z
0

Try these, It should be work

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>



void* testFunction(void* arg) {
pthread_attr_t* attr = (pthread_attr_t*)arg;
int chk;

// Use pthread_attr_getdetachstate correctly to retrieve the detachstate attribute
pthread_attr_getdetachstate(attr, &chk);
printf("thread_attr_getdetachedstate: %d\n", chk);

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, &attr);
printf("attr_create: %d\n", rc);

sleep(4);
pthread_cancel(thread1);

return 0;
}
Zeal answered 1/8, 2023 at 7:9 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Owensby

© 2022 - 2024 — McMap. All rights reserved.