Shortcut tests for fork/exec syscalls
This change should speed up strace by a tiny bit.
More importantly, it makes it much more clear that
fork and exec fixups are not necessary for any reasonably
recent kernels. IOW: syscall_fixup_for_fork_exec() and its callees
are all dead code.
* defs.h: Declare new need_fork_exec_workarounds flag variable.
* strace.c: Define need_fork_exec_workarounds flag variable.
(test_ptrace_setoptions_followfork): Return 0/1 as success/fail indicator.
(test_ptrace_setoptions_for_all): Likewise.
(init): Set need_fork_exec_workarounds to TRUE if needed.
* syscall.c: Rename internal_syscall() to syscall_fixup_for_fork_exec().
(trace_syscall_entering): Call syscall_fixup_for_fork_exec() only if
need_fork_exec_workarounds == TRUE.
(trace_syscall_exiting): Likewise.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/strace.c b/strace.c
index 3df3fbb..eac6ba5 100644
--- a/strace.c
+++ b/strace.c
@@ -65,6 +65,7 @@
unsigned int followfork = 0;
unsigned int ptrace_setoptions = 0;
unsigned int xflag = 0;
+bool need_fork_exec_workarounds = 0;
bool debug_flag = 0;
bool Tflag = 0;
bool qflag = 0;
@@ -1165,7 +1166,7 @@
* First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
* and then see which options are supported by the kernel.
*/
-static void
+static int
test_ptrace_setoptions_followfork(void)
{
int pid, expected_grandchild = 0, found_grandchild = 0;
@@ -1258,10 +1259,11 @@
if (debug_flag)
fprintf(stderr, "ptrace_setoptions = %#x\n",
ptrace_setoptions);
- return;
+ return 0;
}
error_msg("Test for PTRACE_O_TRACECLONE failed, "
"giving up using this feature.");
+ return 1;
}
/*
@@ -1278,7 +1280,7 @@
* int $0x80
* (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
*/
-static void
+static int
test_ptrace_setoptions_for_all(void)
{
const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
@@ -1287,8 +1289,9 @@
int it_worked = 0;
/* this fork test doesn't work on no-mmu systems */
+ /* FIXME: isn't it better to assume we *succeed*? */
if (strace_vforked)
- return;
+ return 1;
pid = fork();
if (pid < 0)
@@ -1357,11 +1360,12 @@
if (debug_flag)
fprintf(stderr, "ptrace_setoptions = %#x\n",
ptrace_setoptions);
- return;
+ return 0;
}
error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
"giving up using this feature.");
+ return 1;
}
#ifdef USE_SEIZE
@@ -1654,9 +1658,14 @@
run_gid = getgid();
}
+ /*
+ * On any reasonably recent Linux kernel (circa about 2.5.46)
+ * need_fork_exec_workarounds should stay 0 after these tests:
+ */
+ /*need_fork_exec_workarounds = 0; - already is */
if (followfork)
- test_ptrace_setoptions_followfork();
- test_ptrace_setoptions_for_all();
+ need_fork_exec_workarounds = test_ptrace_setoptions_followfork();
+ need_fork_exec_workarounds |= test_ptrace_setoptions_for_all();
test_ptrace_seize();
/* Check if they want to redirect the output. */