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);