2004-06-03 Roland McGrath <roland@redhat.com>
* strace.c (main) [LINUX]: Expand TCBTAB as necessary for threads
attached. Attach threads only under -f. Set TCB_FOLLOWFORK in them.
(expand_tcbtab): New function, broken out of ...
* process.c (fork_tcb): ... here, call that.
* defs.h: Declare expand_tcbtab.
diff --git a/defs.h b/defs.h
index 6d22d34..95cd897 100644
--- a/defs.h
+++ b/defs.h
@@ -413,6 +413,7 @@
extern struct tcb *alloctcb P((int));
extern struct tcb *pid2tcb P((int));
extern void droptcb P((struct tcb *));
+extern int expand_tcbtab P((void));
extern void set_sortby P((char *));
extern void set_overhead P((int));
diff --git a/process.c b/process.c
index 038fc14..7764725 100644
--- a/process.c
+++ b/process.c
@@ -402,27 +402,10 @@
fork_tcb(struct tcb *tcp)
{
if (nprocs == tcbtabsize) {
- /* Allocate some more TCBs and expand the table.
- We don't want to relocate the TCBs because our
- callers have pointers and it would be a pain.
- So tcbtab is a table of pointers. Since we never
- free the TCBs, we allocate a single chunk of many. */
- struct tcb **newtab = (struct tcb **)
- realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
- struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
- sizeof *newtcbs);
- int i;
- if (newtab == NULL || newtcbs == NULL) {
- if (newtab != NULL)
- free(newtab);
+ if (expand_tcbtab()) {
tcp->flags &= ~TCB_FOLLOWFORK;
fprintf(stderr, "sys_fork: tcb table full\n");
- return 1;
}
- for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
- newtab[i] = &newtcbs[i - tcbtabsize];
- tcbtabsize *= 2;
- tcbtab = newtab;
}
tcp->flags |= TCB_FOLLOWFORK;
diff --git a/strace.c b/strace.c
index a8a1e40..5fc640d 100644
--- a/strace.c
+++ b/strace.c
@@ -403,7 +403,7 @@
# ifdef LINUX
if (tcp->flags & TCB_CLONE_THREAD)
continue;
- {
+ if (followfork) {
char procdir[MAXPATHLEN];
DIR *dir;
sprintf(procdir, "/proc/%d/task", tcp->pid);
@@ -424,13 +424,17 @@
(char *) 1, 0) < 0)
++nerr;
else if (tid != tcbtab[c]->pid) {
- tcp = alloctcb(tid);
+ if (nprocs == tcbtabsize &&
+ expand_tcbtab())
+ tcp = NULL;
+ else
+ tcp = alloctcb(tid);
if (tcp == NULL) {
fprintf(stderr, "%s: out of memory\n",
progname);
exit(1);
}
- tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED;
+ tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED|TCB_FOLLOWFORK;
tcbtab[c]->nchildren++;
tcbtab[c]->nclone_threads++;
tcbtab[c]->nclone_detached++;
@@ -688,6 +692,33 @@
return;
}
+int
+expand_tcbtab()
+{
+ /* Allocate some more TCBs and expand the table.
+ We don't want to relocate the TCBs because our
+ callers have pointers and it would be a pain.
+ So tcbtab is a table of pointers. Since we never
+ free the TCBs, we allocate a single chunk of many. */
+ struct tcb **newtab = (struct tcb **)
+ realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
+ struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
+ sizeof *newtcbs);
+ int i;
+ if (newtab == NULL || newtcbs == NULL) {
+ if (newtab != NULL)
+ free(newtab);
+ return 1;
+ }
+ for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
+ newtab[i] = &newtcbs[i - tcbtabsize];
+ tcbtabsize *= 2;
+ tcbtab = newtab;
+
+ return 0;
+}
+
+
struct tcb *
alloctcb(pid)
int pid;