about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--nptl/ChangeLog7
-rw-r--r--nptl/sysdeps/pthread/createthread.c16
2 files changed, 20 insertions, 3 deletions
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index 2182cac1cf..01c6c10165 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -1,5 +1,12 @@
 2004-09-24  Ulrich Drepper  <drepper@redhat.com>
 
+	* pthread_create.c (__pthread_create_2_1): Remember whether thread
+	is created detached and if yes, do not try to free the stack in case
+	the thread creation failed.
+	* sysdeps/pthread/createthread.c (do_clone): Free stack here if clone
+	call fails.  Don't depend on INTERNAL_SYSCALL_ERRNO return zero in
+	case there has been no error.  [BZ #405]
+
 	* pthread_create.c (start_thread): Don't wait for scheduler data
 	etc to be set at the beginning of the function.  The cancellation
 	infrastructure must have been set up.  And enable async
diff --git a/nptl/sysdeps/pthread/createthread.c b/nptl/sysdeps/pthread/createthread.c
index 49383cf769..fb8d8ce937 100644
--- a/nptl/sysdeps/pthread/createthread.c
+++ b/nptl/sysdeps/pthread/createthread.c
@@ -66,8 +66,16 @@ do_clone (struct pthread *pd, const struct pthread_attr *attr,
 
   if (ARCH_CLONE (fct, STACK_VARIABLES_ARGS, clone_flags,
 		  pd, &pd->tid, TLS_VALUE, &pd->tid) == -1)
-    /* Failed.  */
-    return errno;
+    {
+      /* 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 errno;
+    }
 
   /* Now we have the possibility to set scheduling parameters etc.  */
   if (__builtin_expect (stopped != 0, 0))
@@ -95,7 +103,9 @@ do_clone (struct pthread *pd, const struct pthread_attr *attr,
 	      (void) INTERNAL_SYSCALL (tkill, err2, 2, pd->tid, SIGCANCEL);
 #endif
 
-	      return INTERNAL_SYSCALL_ERRNO (res, err);
+	      return (INTERNAL_SYSCALL_ERROR_P (res, err)
+		      ? INTERNAL_SYSCALL_ERRNO (res, err)
+		      : 0);
 	    }
 	}