Friday, August 10, 2012

Creating A Detached PThread using Thread Attribute

In some cases you neither need the child thread to return information to the
main thread nor want the main thread to wait for it. This behavior can be achieved by making the child thread a detached thread. A detached thread can be created by using the thread attribute or by using Posix thread method "pthread_detach". here we will discuss about the former case i.e using the thread attribute.

1. Init thread attribute:
A thread attribute can be init by following function:

int pthread_attr_init(pthread_attr_t *attr);

2. Functions for Detached state:
Below functions are used to set and get the detached state of a thread.

int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);

Parameter:
1. attr: Thread attribute to init.
2. detachstate: Flag to set the required thread state. It can take the vales of "PTHREAD_CREATE_JOINABLE" or "PTHREAD_CREATE_DETACHED". The default value to detachstate is "PTHREAD_CREATE_JOINABLE". When it is "PTHREAD_CREATE_DETACHED" it creates a detached thread.

3. Example:
Below is the program to create a detached thread using thread attribute. We'll call it detachedThread.c.
detachedThread.c

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

bool thread_finished = 0;

void* start_function(void* value)
{
printf("%s is now entering the thread function.\n", (char*)value);
sleep(4);
thread_finished =1;
printf("%s is now leaving the thread function.\n", (char*)value);
pthread_exit(value);
}

main()
{
int res,err;
pthread_attr_t attr;
pthread_t thread1;

res = pthread_attr_init(&attr);
if (res != 0) {
perror("Attribute init failed");
exit(EXIT_FAILURE);
}
res = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if (res != 0) {
perror("Setting detached state failed");
exit(EXIT_FAILURE);
}

res = pthread_create(&thread1, &attr, start_function, (void*)"Thread1");
if (res != 0) {
perror("Creation of thread failed");
exit(EXIT_FAILURE);
}

while(!thread_finished) {
printf("Waiting for thread1 to finish.\n");
sleep(1);
}

printf("Child thread finished.\n");
pthread_attr_destroy(&attr);
}

When you compile and run the program, you'll see the output as:

Waiting for thread1 to finish.
Thread1 is now entering the thread function.
Waiting for thread1 to finish.
Waiting for thread1 to finish.
Waiting for thread1 to finish.
Thread1 is now leaving the thread function.
Child thread finished.

3 comments:

  1. IMO when one doesn`t want the main thread to wait for child thread to return, he should remove the waiting loop:
    while(!thread_finished) {
    printf("Waiting for thread1 to finish.\n");
    sleep(1);
    }
    and instead use
    sleep(2); // to allow child to execute to the sleep()call
    pthread_join(thread1, NULL); // to forcibly terminate the child before it execute thread_finished=1

    ReplyDelete
  2. The changes I gave: to test preliminary cancellation of a (hung) thread (before it call pthread_exit) do not work.
    Actually it seems impossible: to join a thread, it must have PTHREAD_CREATE_JOINABLE attribute. And then join(..) will wait for thread to call pthread_exit().
    pthread_cancel can be used, but it is asynchronous, so it won`t destroy the thread before it returns. Also it wont abort the thread execution unless the thread is in a 'cancellation point'. So we have to write our threads carefully - not to hang by design...

    ReplyDelete
  3. @Angel Genchev
    It's a simple program to test thread attribute. We are creating the thread with "PTHREAD_CREATE_DETACHED" , so we can't join the threads.

    Also the while loop is not required in actual scenerios as we don't want to wait for the child thread. But since this is an example program I put this code to check that the child thread has actually finished.

    ReplyDelete