Fixed segfault in traced process when receiving a signal

Specifically, when a signal was received while enabling a breakpoint
diff --git a/ChangeLog b/ChangeLog
index 7a09e57..41c496a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2009-02-11  Juan Cespedes <cespedes@debian.org>
+
+	* Fixed bug present since the first version (!) of ltrace,
+          which caused many programs to segfault when a signal is received:
+	  + When a breakpoint is hit, and we need to continue with it, we:
+	    1) remove the breakpoint
+	    2) order a SINGLESTEP
+	    3) when control comes back, set the breakpoint again
+	    4) let the process continue
+	  + The problem came when a signal is received in the middle
+	    of all this (specifically, between 2) and 3)).
+	    If this is so, we treat the signal "in the usual way",
+	    it is, at the end we issue a "CONTINUE" instead of the
+	    needed SINGLESTEP.
+
 2008-12-10  Juan Cespedes <cespedes@debian.org>
 
 	* summary.c: Fix "ltrace -o -c"
diff --git a/ltrace.h b/ltrace.h
index f029664..fd60594 100644
--- a/ltrace.h
+++ b/ltrace.h
@@ -216,6 +216,7 @@
 extern void *instruction_pointer;
 
 extern struct event *wait_for_something(void);
+extern struct process * pid2proc(pid_t pid);
 extern void process_event(struct event *event);
 extern void execute_program(struct process *, char **);
 extern int display_arg(enum tof type, struct process *proc, int arg_num, arg_type_info *info);
diff --git a/proc.c b/proc.c
index 511eb5e..88edd0a 100644
--- a/proc.c
+++ b/proc.c
@@ -59,3 +59,17 @@
 	continue_process(pid);
 	proc->breakpoints_enabled = 1;
 }
+
+struct process *
+pid2proc(pid_t pid) {
+	struct process *tmp;
+
+	tmp = list_of_processes;
+	while (tmp) {
+		if (pid == tmp->pid) {
+			return tmp;
+		}
+		tmp = tmp->next;
+	}
+	return NULL;
+}
diff --git a/sysdeps/linux-gnu/trace.c b/sysdeps/linux-gnu/trace.c
index f348fc8..a90d46a 100644
--- a/sysdeps/linux-gnu/trace.c
+++ b/sysdeps/linux-gnu/trace.c
@@ -197,13 +197,25 @@
 
 void
 continue_after_signal(pid_t pid, int signum) {
-	/* We should always trace syscalls to be able to control fork(), clone(), execve()... */
-	ptrace(PTRACE_SYSCALL, pid, 0, signum);
+	struct process *proc;
+
+	proc = pid2proc(pid);
+	if (proc && proc->breakpoint_being_enabled) {
+#if defined __sparc__  || defined __ia64___
+		ptrace(PTRACE_SYSCALL, pid, 0, signum);
+#else
+		ptrace(PTRACE_SINGLESTEP, pid, 0, signum);
+#endif
+	} else {
+		ptrace(PTRACE_SYSCALL, pid, 0, signum);
+	}
 }
 
 void
 continue_process(pid_t pid) {
-	continue_after_signal(pid, 0);
+	/* We always trace syscalls to control fork(), clone(), execve()... */
+
+	ptrace(PTRACE_SYSCALL, pid, 0, 0);
 }
 
 void
diff --git a/wait_for_something.c b/wait_for_something.c
index 0f57fe5..eb7ea52 100644
--- a/wait_for_something.c
+++ b/wait_for_something.c
@@ -16,10 +16,6 @@
 
 static struct event event;
 
-/* This should also update `current_process' */
-
-static struct process *pid2proc(int pid);
-
 struct event *
 wait_for_something(void) {
 	pid_t pid;
@@ -154,17 +150,3 @@
 	    event.proc->instruction_pointer - DECR_PC_AFTER_BREAK;
 	return &event;
 }
-
-static struct process *
-pid2proc(pid_t pid) {
-	struct process *tmp;
-
-	tmp = list_of_processes;
-	while (tmp) {
-		if (pid == tmp->pid) {
-			return tmp;
-		}
-		tmp = tmp->next;
-	}
-	return NULL;
-}