Phiber
Phiber

Reputation: 1103

No blocking thread

I have read this and this post on stackoverflow, but no one of them give me what I want to do.

In my case, I want to create a Thread, launch it and let it running with no blocking stat as long as the main process runs. This thread has no communication, no synchronization with the main process, it do his job fully independent.
Consider this code:

 #define DAY_PERIOD 86400 /* 3600*24 seconds */
 int main() {
   char wDir[255] = "/path/to/log/files";
   compress_logfiles(wDir);

   // do other things, this things let the main process runs all the time.
   // just segmentation fault, stackoverflow, memory overwrite or 
   // somethings like that stop it.

   return 0;
}

/* Create and launch thread */
void compress_logfiles(char *wDir)
{

    pthread_t compressfiles_th;

    if (pthread_create(&compressfiles_th, NULL, compress, wDir)) 
    {
        fprintf(stderr, "Error create compressfiles thread\n");
        return;
    }
    if (pthread_join(compressfiles_th, NULL)) 
    {
        //fprintf(stderr, "Error joining thread\n");
        return;
    }
   return;
}

void *compress(void *wDir)
{
    while(1)
    {
        // Do job to compress files
        // and sleep for one day 
        sleep(DAY_PERIOD); /* sleep one day*/
    }
    return NULL;
}

With ptheard_join in compress_logfiles function, the thread compresses all files successfully and never returns because it is in infinite while loop, so the main process still blocked all the time. If I remove ptheard_join from compress_logfiles function, the main process is not blocked because it don't wait thread returns, but the thread compresses one file and exit (there a lot of files, arround one haundred).

So, is there a way to let main process launch compressfiles_th thread and let it do his job without waiting it to finish or exit? I found pthread_tryjoin_np and pthread_timedjoin_np in Linux Programmer's Manual, it seems that pthread_tryjoin_np do the job if I don't care of the returned value, it is good idea to use it?

Thank you.

Edit 1:
Please note that the main process is daemonized after call to compress_logfiles(wDir), perhaps the daemonization kill the main process and re-launch it is the problem?

Edit 2: the solution

Credit to dbush

Yes, fork causes the problem, and pthread_atfork() solves it. I made this change to run the compressfiles_th without blocking main process:

 #define DAY_PERIOD 86400 /* 3600*24 seconds */
 char wDir[255] = "/path/to/log/files"; // global now

 // function added
void child_handler(){
    compress_logfiles(wDir); // wDir is global variable now
}

 int main() 
 {
     pthread_atfork(NULL, NULL, child_handler);
     // Daemonize the process.
     becomeDaemon(BD_NO_CHDIR & BD_NO_CLOSE_FILES & BD_NO_REOPEN_STD_FDS & BD_NO_UMASK0 & BD_MAX_CLOSE);
   // do other things, this things let the main process runs all the time.
   // just segmentation fault, stackoverflow, memory overwrite or 
   // somethings like that stop it.

   return 0;
}

child_handler() function is called after fork. pthread_atfork

Upvotes: 2

Views: 408

Answers (1)

dbush
dbush

Reputation: 225817

When you fork a new process, only the calling thread is duplicated, not all threads.

If you wish to daemonize, you need to fork first, then create your threads.

From the man page for fork:

The child process is created with a single thread--the one that called fork(). The entire virtual address space of the parent is replicated in the child, including the states of mutexes, condition variables, and other pthreads objects; the use of pthread_atfork(3) may be helpful for dealing with problems that this can cause.

Upvotes: 3

Related Questions