Fix a race between fork/trace_me and first ptrace request
- That first ptrace may fail if ltrace is too quick
diff --git a/ChangeLog b/ChangeLog
index bd06c47..c095263 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
2012-02-07 Petr Machata <[email protected]>
+ * common.h (wait_for_proc): New interface.
+ * sysdeps/linux-gnu/trace.c: Implement it.
+ * execute_program.c: Call it.
+
+2012-02-07 Petr Machata <[email protected]>
+
* configure.ac (ELF_HASH_TAKES_SIGNED_CHAR): Rename to
ELF_HASH_TAKES_CHARP, adjust configure message accordingly.
* ltrace-elf.c: Adapt to the rename
diff --git a/common.h b/common.h
index 715898d..fa80076 100644
--- a/common.h
+++ b/common.h
@@ -329,6 +329,7 @@
extern int process_stopped(pid_t pid);
extern enum process_status process_status(pid_t pid);
extern void trace_set_options(Process * proc, pid_t pid);
+extern void wait_for_proc(pid_t pid);
extern void trace_me(void);
extern int trace_pid(pid_t pid);
extern void untrace_pid(pid_t pid);
diff --git a/execute_program.c b/execute_program.c
index 47f514d..859f32c 100644
--- a/execute_program.c
+++ b/execute_program.c
@@ -89,6 +89,8 @@
_exit(1);
}
+ wait_for_proc(pid);
+
debug(1, "PID=%d", pid);
return pid;
diff --git a/sysdeps/linux-gnu/trace.c b/sysdeps/linux-gnu/trace.c
index db18df0..67e1f93 100644
--- a/sysdeps/linux-gnu/trace.c
+++ b/sysdeps/linux-gnu/trace.c
@@ -77,6 +77,29 @@
}
}
+/* There's a (hopefully) brief period of time after the child process
+ * exec's when we can't trace it yet. Here we wait for kernel to
+ * prepare the process. */
+void
+wait_for_proc(pid_t pid)
+{
+ size_t i;
+ for (i = 0; i < 100; ++i) {
+ /* We read from memory address 0, but that shouldn't
+ * be a problem: the reading will just fail. We are
+ * looking for a particular reason of failure. */
+ if (ptrace(PTRACE_PEEKTEXT, pid, 0, 0) != -1
+ || errno != ESRCH)
+ return;
+
+ usleep(1000);
+ }
+
+ fprintf(stderr, "\
+I consistently fail to read a word from the freshly launched process.\n\
+I'll now try to proceed with tracing, but this shouldn't be happening.\n");
+}
+
int
trace_pid(pid_t pid) {
debug(DEBUG_PROCESS, "trace_pid: pid=%d", pid);