From dan@kulesh.obluda.cz  Thu Jul 14 14:09:49 2005
Return-Path: <dan@kulesh.obluda.cz>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 86D8516A41C
	for <FreeBSD-gnats-submit@freebsd.org>; Thu, 14 Jul 2005 14:09:49 +0000 (GMT)
	(envelope-from dan@kulesh.obluda.cz)
Received: from kulesh.obluda.cz (kulesh.obluda.cz [193.179.22.243])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 331AF43D45
	for <FreeBSD-gnats-submit@freebsd.org>; Thu, 14 Jul 2005 14:09:47 +0000 (GMT)
	(envelope-from dan@kulesh.obluda.cz)
Received: from kulesh.obluda.cz (localhost.eunet.cz [127.0.0.1])
	by kulesh.obluda.cz (8.13.3/8.13.3) with ESMTP id j6EE9jA5033305
	for <FreeBSD-gnats-submit@freebsd.org>; Thu, 14 Jul 2005 16:09:46 +0200 (CEST)
	(envelope-from dan@kulesh.obluda.cz)
Received: (from root@localhost)
	by kulesh.obluda.cz (8.13.3/8.13.1/Submit) id j6EE9jSC033304;
	Thu, 14 Jul 2005 16:09:45 +0200 (CEST)
	(envelope-from dan)
Message-Id: <200507141409.j6EE9jSC033304@kulesh.obluda.cz>
Date: Thu, 14 Jul 2005 16:09:45 +0200 (CEST)
From: Dan Lukes <dan@obluda.cz>
Reply-To: Dan Lukes <dan@obluda.cz>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: [ PATCH ] Unhandled malloc failure within libpthread's _thr_alloc()
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         83457
>Category:       bin
>Synopsis:       [ PATCH ] Unhandled malloc failure within libpthread's _thr_alloc()
>Confidential:   no
>Severity:       serious
>Priority:       low
>Responsible:    deischen
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Jul 14 14:10:09 GMT 2005
>Closed-Date:    Mon Aug 29 13:50:31 GMT 2005
>Last-Modified:  Tue Aug 30 10:00:33 GMT 2005
>Originator:     Dan Lukes
>Release:        FreeBSD 5.4-STABLE i386
>Organization:
Obludarium
>Environment:
System: FreeBSD kulesh.obluda.cz 5.4-STABLE FreeBSD 5.4-STABLE #8: Sat Jul 9 16:31:08 CEST 2005 dan@kulesh.obluda.cz:/usr/obj/usr/src/sys/KULESH i386
lib/libpthread/thread/thr_kern.c,v 1.112.2.2 2005/02/04 16:17:55 jhb

>Description:
	Unhandled malloc failure within libpthread's _thr_alloc()
>How-To-Repeat:
>Fix:

	The order of initialization of thread->tcb and thread->siginfo has
been swapped. It simplify cleanup after siginfo alloc failure (tcb is not
initialized yet, so it's not necesarry to destroy it)

	Over-nested if-else structures has been rearanged to improve
readability of code. Use 'goto' for exception handlings is not violation of
'structured programming rule'

--- patch begins here ---
--- lib/libpthread/thread/thr_kern.c.ORIG	Mon Feb 14 12:33:31 2005
+++ lib/libpthread/thread/thr_kern.c	Thu Jul 14 16:03:24 2005
@@ -2363,37 +2363,43 @@
 		}
 	}
 	if ((thread == NULL) &&
-	    ((thread = malloc(sizeof(struct pthread))) != NULL)) {
-		bzero(thread, sizeof(struct pthread));
-		if (curthread) {
-			_pthread_mutex_lock(&_tcb_mutex);
-			thread->tcb = _tcb_ctor(thread, 0 /* not initial tls */);
-			_pthread_mutex_unlock(&_tcb_mutex);
-		} else {
-			thread->tcb = _tcb_ctor(thread, 1 /* initial tls */);
-		}
-		if (thread->tcb == NULL) {
-			free(thread);
-			thread = NULL;
-		} else {
-			thread->siginfo = calloc(_SIG_MAXSIG,
-				sizeof(siginfo_t));
-			/*
-			 * Initialize thread locking.
-			 * Lock initializing needs malloc, so don't
-			 * enter critical region before doing this!
-			 */
-			if (_lock_init(&thread->lock, LCK_ADAPTIVE,
-			    _thr_lock_wait, _thr_lock_wakeup) != 0)
-				PANIC("Cannot initialize thread lock");
-			for (i = 0; i < MAX_THR_LOCKLEVEL; i++) {
-				_lockuser_init(&thread->lockusers[i],
-				    (void *)thread);
-				_LCK_SET_PRIVATE2(&thread->lockusers[i],
-				    (void *)thread);
-			}
-		}
+	    ((thread = calloc(1, sizeof(struct pthread))) == NULL))
+		goto done;
+
+	thread->siginfo = calloc(_SIG_MAXSIG, sizeof(siginfo_t));
+	if (thread->siginfo == NULL) {
+		free(thread);
+		thread = NULL;
+		goto done;
+	}
+
+	if (curthread) {
+		_pthread_mutex_lock(&_tcb_mutex);
+		thread->tcb = _tcb_ctor(thread, 0 /* not initial tls */);
+		_pthread_mutex_unlock(&_tcb_mutex);
+	} else {
+		thread->tcb = _tcb_ctor(thread, 1 /* initial tls */);
+	}
+	if (thread->tcb == NULL) {
+		free(thread);
+		thread = NULL;
+		goto done;
+	}
+
+	/*
+	 * Initialize thread locking.
+	 * Lock initializing needs malloc, so don't
+	 * enter critical region before doing this!
+	 */
+	if (_lock_init(&thread->lock, LCK_ADAPTIVE,
+	    _thr_lock_wait, _thr_lock_wakeup) != 0)
+		PANIC("Cannot initialize thread lock");
+	for (i = 0; i < MAX_THR_LOCKLEVEL; i++) {
+		_lockuser_init(&thread->lockusers[i], (void *)thread);
+		_LCK_SET_PRIVATE2(&thread->lockusers[i], (void *)thread);
 	}
+
+done:
 	return (thread);
 }
 
@@ -2180,7 +2180,7 @@
 {
 	struct kse *kse = NULL;
 	char *stack;
-	kse_critical_t crit;
+	kse_critical_t crit = NULL;
 	int i;
 
 	if ((curthread != NULL) && (free_kse_count > 0)) {
--- patch ends here ---
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->deischen 
Responsible-Changed-By: glebius 
Responsible-Changed-When: Fri Aug 12 12:30:38 GMT 2005 
Responsible-Changed-Why:  
For Daniel's review. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=83457 

From: Gleb Smirnoff <glebius@freebsd.org>
To: Dan Lukes <dan@obluda.cz>
Cc: freebsd-gnats-submit@freebsd.org
Subject: Re: bin/83457: [ PATCH ] Unhandled malloc failure within libpthread's _thr_alloc()
Date: Sat, 13 Aug 2005 06:08:17 +0400

 ----- Forwarded message from Daniel Eischen <deischen@freebsd.org> -----
 
 From: Daniel Eischen <deischen@freebsd.org>
 To: Gleb Smirnoff <glebius@freebsd.org>
 cc: freebsd-bugs@freebsd.org
 Subject: Re: bin/83457: [ PATCH ] Unhandled malloc failure within libpthread's
  _thr_alloc()
 Date: Fri, 12 Aug 2005 11:09:57 -0400 (EDT)
 Delivered-To: glebius@freebsd.org
 Reply-To: Daniel Eischen <deischen@freebsd.org>
 In-Reply-To: <200508121232.j7CCWtHI090384@freefall.freebsd.org>
 
 On Fri, 12 Aug 2005, Gleb Smirnoff wrote:
 
 > Synopsis: [ PATCH ] Unhandled malloc failure within libpthread's _thr_alloc()
 >
 > Responsible-Changed-From-To: freebsd-bugs->deischen
 > Responsible-Changed-By: glebius
 > Responsible-Changed-When: Fri Aug 12 12:30:38 GMT 2005
 > Responsible-Changed-Why:
 > For Daniel's review.
 >
 > http://www.freebsd.org/cgi/query-pr.cgi?pr=83457
 
 Please, no gotos.  Rearranging things like that, I can't tell what
 was changed.  What is the problem?  There is also a setting of
 crit = NULL that doesn't seem to be related to anything.
 
 -- 
 DE
 
 ----- End forwarded message -----
 
 -- 
 Totus tuus, Glebius.
 GLEBIUS-RIPN GLEB-RIPE

From: Dan Lukes <dan@obluda.cz>
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/83457: [ PATCH ] Unhandled malloc failure within libpthread's
 _thr_alloc()
Date: Sat, 27 Aug 2005 10:46:35 +0200

 	The main reason for this PR:
 		failures of calloc() on line 2379 is ignored.
 
 
 	Unfortunately, the cleanup in the case of failure there seems to be 
 complicated. So I swap the order of the initialisation - it simplify the 
 cleanup as mentioned within original text of PR.
 
 	Ad 'goto' - i know several ways to handling 'exception' within function.
 
   ================
 1. Nested ifs:
 
 	func1()
 	if (error) {
 		func2()
 		if (error) {
 			func3()
 			...
 			...	return(OK)
 		}
 	}
 	[cleanup_code]
 	return(FAIL)
 
 2. If with repeated cleanup code:
 	func1()
 	if (error) {
 		[cleanup_code]
 		return(FAIL)
 	}
 	func2()
 	if (error) {
 		[cleanup_code]
 		return(FAIL)
 	}
 	...
 	return(OK)
 
 
 3. do ... while style:
 	do {
 		func1()
 		if (error)
 			break;
 		func2()
 		if (error)
 			break;
 		...
 	} while true;
 	if (error) {
 		[cleanup_code]
 		return(FAIL)
 	}
 	return(OK)
 
 4. goto style:
 	func1()
 	if (error)
 		goto err;
 	func2()
 	if (error)
 		goto err;
 	...
 	return(OK)
 
   err:
 	[cleanup_code]
 	return(FAIL)
   ================
 
 	The selection of the style is mainly based on personal preference of 
 code writer. IMHO, [1] style make unreadable code; [2] style make code 
 with many repeated identical or almost identical piece of cleanup_code 
 which complicate future changes within code. I use [3] or [4] with 
 personal preference of [4] as it seems to be simplest and most readable 
 way to handle it. Note the libpthread code contains some gotos already.
 
 	Despite of my personal preference, I'm ready to follow personal 
 preferences of designated commiter. I can send patch written with other 
 style if you reveal your preferences to me.
 
 
 						Dan
 
 P.S. Please note the english isn't my native language. Be carefull when 
 reading the text. The reader's assumptions based on feeling of "tone of 
 voice" of writer and other "out-of-band" informations based on writer's 
 word selections and arrangement may be wrong from scratch.
 
State-Changed-From-To: open->closed 
State-Changed-By: deischen 
State-Changed-When: Mon Aug 29 13:50:04 GMT 2005 
State-Changed-Why:  
Fixed. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=83457 

From: Dan Lukes <dan@obluda.cz>
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/83457: [ PATCH ] Unhandled malloc failure within libpthread's
 _thr_alloc()
Date: Tue, 30 Aug 2005 11:59:18 +0200

 	See PR 85468
 
 http://www.freebsd.org/cgi/query-pr.cgi?pr=85468
 
>Unformatted:
