1

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

Community
  • 1
  • 1
Phiber
  • 1,041
  • 5
  • 17
  • 40
  • 1
    The above code does not exhibit the behavior you describe. If I comment out the call to `pthread_join`, the thread function does not exit. Please update your question with a [Minimal, Complete, Verifiable Example](http://stackoverflow.com/help/mcve). – dbush Aug 16 '16 at 15:27
  • 2
    I'd suggest moving the call to pthread_join() to the bottom of main(), so that the main thread is free to do whatever it wants until the time it is ready to exit. (At that point you'll want to call pthread_join() to make sure that the compress-thread has terminated before main() returns, to avoid potential race conditions between the compress-thread and the process cleanup. You'll need to have some mechanism to get the compress-thread to exit at that point, of course; e.g. setting an atomic variable that the compress-thread periodically checks would be sufficient) – Jeremy Friesner Aug 16 '16 at 15:33
  • In the Edit 2, I added becomeDaemon function without its declaration, I see it is not necessary in this context but if someone needs it I can give him the declaration – Phiber Aug 16 '16 at 20:28

1 Answers1

3

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.

dbush
  • 205,898
  • 23
  • 218
  • 273