title: Thread management in a cloned process with CLONE_VM flag set
body: <p>I need help with thread management inside cloned process.
  The point is that I need to create and destroy <em>threads</em> inside a cloned process <strong>asynchronously</strong> (<code>PTHREAD_CANCEL_ASYNCHRONOUS</code> is set). Everything is fine if CLONE_VM is not set, but I need it because main and child process <strong>must</strong> share the same address space. 
  Below is an example that demonstrate the question. Being compiled with <code>CLONE_VM</code> flag the program hangs at <code>pthread_join</code> while without <code>CLONE_VM</code> everything is fine.
  Are there any ways to deal with this problem?</p>
  
  <p>P.S. Tried at Debian GNU/Linux versions 7,8 and unstable (kernels 3.2, 3.16, 4.0).</p>
  
  <pre><code>#include &lt;stdlib.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;pthread.h&gt;
  #include &lt;sched.h&gt;
  #include &lt;string.h&gt;
  #include &lt;signal.h&gt;
  #include &lt;sys/types.h&gt;
  #include &lt;sys/wait.h&gt;
  
  /* Compile with # gcc -o pthread_test -lpthread pthread_test.c */
  
  #define CLONE 1
  
  pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  
  void *thread_test(void *unused)
  {
      pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
      pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
      pthread_mutex_unlock(&amp;mutex);
      pause();
      return NULL;
  }
  
  int test(void *unused)
  {
      void *status;
      int r;
      pthread_t thread;
      pthread_mutex_lock(&amp;mutex);
      if ((r = pthread_create(&amp;thread, NULL, thread_test, NULL)) != 0) {
          printf("pthread_create returned %d\n", r);
          exit(1);
      }
      pthread_mutex_lock(&amp;mutex);
      printf("cancelling thread\n");
      r = pthread_cancel(thread);
      printf("pthread cancel returned : %s(%d)\n", strerror(r), r);
      printf("joining thread\n");
      r = pthread_join(thread, &amp;status);
      printf("pthread_join returned : %s\n", strerror(r));
      if (status == PTHREAD_CANCELED)
          printf("child was canceled\n");
      else
          printf("child exit status is %u\n", (unsigned)status);
  
      return 0;
  }
  
  int main(void)
  {
  #if CLONE
      void *stack = (void *)malloc(16384);
      if (clone(test, stack + 16383, CLONE_VM | CLONE_FS | CLONE_FILES, NULL) &lt; 0) {
          printf("clone failed\n");
          exit(1);
      }
      waitpid(0, NULL, __WCLONE);
      return 0;
  #else
      void *stack = (void *)malloc(16384);
      if (clone(test, stack + 16383, /*CLONE_VM |*/ CLONE_FS | CLONE_FILES, NULL) &lt; 0) {
          printf("clone failed\n");
          exit(1);
      }
      waitpid(0, NULL, __WCLONE);
      return 0;
  #endif
  }
  </code></pre>