]> granicus.if.org Git - strace/commitdiff
2006-03-29 Dmitry V. Levin <ldv@altlinux.org>
authorDmitry V. Levin <ldv@altlinux.org>
Wed, 11 Oct 2006 22:55:25 +0000 (22:55 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Wed, 11 Oct 2006 22:55:25 +0000 (22:55 +0000)
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.

ChangeLog
process.c
strace.c

index bd4bde2c55404d479e50779cc17c4c0a32217fcc..a241c021c758d87e3217d2b6bec72bcee960c137 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+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.
+
 2006-08-22  Roland McGrath  <roland@redhat.com>
 
        * ipc.c (sys_msgget, sys_semget, sys_shmget): Show key values in hex.
index 1e03ff5ccd642365c36697a4978c958bff887c26..a0db041a852da9a3d6887db55f52714ee1cdd7ea 100644 (file)
--- a/process.c
+++ b/process.c
@@ -412,7 +412,7 @@ fork_tcb(struct tcb *tcp)
        if (nprocs == tcbtabsize) {
                if (expand_tcbtab()) {
                        tcp->flags &= ~TCB_FOLLOWFORK;
-                       fprintf(stderr, "sys_fork: tcb table full\n");
+                       return 1;
                }
        }
 
@@ -474,10 +474,8 @@ struct tcb *tcp;
                        return 0;
                if (syserror(tcp))
                        return 0;
-               if ((tcpchild = alloctcb(tcp->u_rval)) == NULL) {
-                       fprintf(stderr, "sys_fork: tcb table full\n");
+               if ((tcpchild = alloctcb(tcp->u_rval)) == NULL)
                        return 0;
-               }
                if (proc_open(tcpchild, 2) < 0)
                        droptcb(tcpchild);
        }
@@ -833,10 +831,9 @@ struct tcb *tcp;
                }
                else
 #endif
-               if ((tcpchild = alloctcb(pid)) == NULL) {
+               if (fork_tcb(tcp) || (tcpchild = alloctcb(pid)) == NULL) {
                        if (bpt)
                                clearbpt(tcp);
-                       fprintf(stderr, " [tcb table full]\n");
                        kill(pid, SIGKILL); /* XXX */
                        return 0;
                }
@@ -970,8 +967,7 @@ struct tcb *tcp;
                        return 0;
 
                pid = tcp->u_rval;
-               if ((tcpchild = alloctcb(pid)) == NULL) {
-                       fprintf(stderr, " [tcb table full]\n");
+               if (fork_tcb(tcp) || (tcpchild = alloctcb(pid)) == NULL) {
                        kill(pid, SIGKILL); /* XXX */
                        return 0;
                }
index 1553fb59aff577323db030ed32a38faff45562d2..0da34abe5fbc45dd610b4353a273cae898633584 100644 (file)
--- a/strace.c
+++ b/strace.c
@@ -442,11 +442,8 @@ char *argv[];
                                                        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 @@ Process %u attached - interrupt to quit\n",
                }
                default:
                        if ((tcp = alloctcb(pid)) == NULL) {
-                               fprintf(stderr, "tcb table full\n");
                                cleanup();
                                exit(1);
                        }
@@ -725,6 +721,8 @@ expand_tcbtab()
        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 @@ int pid;
                        return tcp;
                }
        }
+       fprintf(stderr, "%s: alloctcb: tcb table full\n", progname);
        return NULL;
 }
 
@@ -2104,8 +2103,12 @@ trace()
                                   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;
                                }