Fix failure handling for thread creation
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / solaris2 / kopensolaris-gnu / createthread.c
index 157512c..1917152 100644 (file)
@@ -25,6 +25,7 @@
 #include <sys/stack.h>
 #include <sys/stack.h>
 #include <sys/regset.h>
+#include <sys/lwp.h>
 #include <inline-syscall.h>
 #include <schedP.h>
 #include <createthread_arch.c>
@@ -69,10 +70,10 @@ create_thread (struct pthread *pd, const struct pthread_attr *attr,
   /* We set the thread to be initially suspended so that we can set
      scheduling magic.  */
   int lwp_flags =
-      ((attr->flags & ATTR_FLAG_DAEMON) ? THR_DAEMON : 0) |
-      ((attr->flags & ATTR_FLAG_DETACHSTATE) ? THR_DETACHED : 0);
+      ((attr->flags & ATTR_FLAG_DAEMON) ? LWP_DAEMON : 0) |
+      ((attr->flags & ATTR_FLAG_DETACHSTATE) ? LWP_DETACHED : 0);
   if ((attr->flags & ATTR_FLAG_THR_CREATE) == 0)
-    lwp_flags |= THR_SUSPENDED;
+    lwp_flags |= LWP_SUSPENDED;
   errval = INLINE_SYSCALL (lwp_create, 3, &ctx, lwp_flags, &pd->tid);
   if (errval == 0 && (attr->flags & ATTR_FLAG_THR_CREATE) == 0)
     {
@@ -97,16 +98,24 @@ create_thread (struct pthread *pd, const struct pthread_attr *attr,
             errval = EPERM;
         }
 
-      /* Resume thread if requested.  */
-      if (errval == 0)
+      if (errval == 0 && !(attr->flags & ATTR_FLAG_SUSPENDED))
         {
-          if (!(attr->flags & ATTR_FLAG_SUSPENDED))
-            errval = INLINE_SYSCALL (lwp_continue, 1, pd->tid);
+          errval = INLINE_SYSCALL (lwp_continue, 1, pd->tid);
         }
+      else if (errval != 0)
+        {
+          pd->flags |= ATTR_FLAG_CREATE_FAILED;
+          INLINE_SYSCALL (lwp_continue, 1, pd->tid);
+
+          if (!IS_DETACHED (pd))
+            {
+              int result;
+              lll_wait_tid (pd->tid);
+            }
 
-      /* Kill the thread if we didn't succeed above.  */
-      if (errval != 0)
-        INLINE_SYSCALL (lwp_kill, 2, pd->tid, SIGKILL);
+          /* Note: if the thread is detached, start_thread will free pd;
+             otherwise the caller of create_thread will free pd.  */
+        }
     }
 
   if (errval == 0)
@@ -119,13 +128,6 @@ create_thread (struct pthread *pd, const struct pthread_attr *attr,
   else
     {
       atomic_decrement (&__nptl_nthreads); /* Oops, we lied for a second.  */
-
-      /* Failed.  If the thread is detached, remove the TCB here since
-         the caller cannot do this.  The caller remembered the thread
-         as detached and cannot reverify that it is not since it must
-         not access the thread descriptor again.  */
-      if (IS_DETACHED (pd))
-        __deallocate_stack (pd);
     }
 
   return errval;