2006-03-29  Dmitry V. Levin  <ldv@altlinux.org>

	Fix race conditions in tcb allocation.
	* process.c (fork_tcb): Return error code as documented.  Do not
	print "tcb table full" error message.
	[USE_PROCFS] (internal_fork): Do not print "tcb table full"
	error message.
	[SYS_clone || SYS_clone2] (internal_clone, internal_fork): Call
	fork_tcb() before alloctcb().  Do not print "tcb table full"
	error message.
	* strace.c (main): Do not print "tcb table full" error message.
	(expand_tcbtab): Print error message in case of memory allocation
	failure.
	(alloctcb): Print error message when tcb table is full.
	(trace): Expand tcb table if necessary prior to allocating
	entry there.  Do not print "tcb table full" error message.
	Fixes RH#180293.
diff --git a/strace.c b/strace.c
index 1553fb5..0da34ab 100644
--- a/strace.c
+++ b/strace.c
@@ -442,11 +442,8 @@
 							tcp = NULL;
 						else
 							tcp = alloctcb(tid);
-						if (tcp == NULL) {
-							fprintf(stderr, "%s: out of memory\n",
-								progname);
+						if (tcp == NULL)
 							exit(1);
-						}
 						tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED|TCB_FOLLOWFORK;
 						tcbtab[c]->nchildren++;
 						tcbtab[c]->nclone_threads++;
@@ -626,7 +623,6 @@
 		}
 		default:
 			if ((tcp = alloctcb(pid)) == NULL) {
-				fprintf(stderr, "tcb table full\n");
 				cleanup();
 				exit(1);
 			}
@@ -725,6 +721,8 @@
 	if (newtab == NULL || newtcbs == NULL) {
 		if (newtab != NULL)
 			free(newtab);
+		fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
+			progname);
 		return 1;
 	}
 	for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
@@ -763,6 +761,7 @@
 			return tcp;
 		}
 	}
+	fprintf(stderr, "%s: alloctcb: tcb table full\n", progname);
 	return NULL;
 }
 
@@ -2104,8 +2103,12 @@
 				   will we have the association of parent and
 				   child so that we know how to do clearbpt
 				   in the child.  */
-				if ((tcp = alloctcb(pid)) == NULL) {
-					fprintf(stderr, " [tcb table full]\n");
+				if (nprocs == tcbtabsize &&
+				    expand_tcbtab())
+					tcp = NULL;
+				else
+					tcp = alloctcb(pid);
+				if (tcp == NULL) {
 					kill(pid, SIGKILL); /* XXX */
 					return 0;
 				}