Generalize the stopping handler so that it can be reused

- though more generalizing may be needed
diff --git a/sysdeps/linux-gnu/trace.c b/sysdeps/linux-gnu/trace.c
index 11d6b97..af9423c 100644
--- a/sysdeps/linux-gnu/trace.c
+++ b/sysdeps/linux-gnu/trace.c
@@ -233,7 +233,7 @@
 	struct event_handler super;
 
 	/* The task that is doing the re-enablement.  */
-	Process * task_enabling_breakpoint;
+	Process *task_enabling_breakpoint;
 
 	/* The pointer being re-enabled.  */
 	struct breakpoint *breakpoint_being_enabled;
@@ -241,6 +241,9 @@
 	/* Artificial atomic skip breakpoint, if any needed.  */
 	void *atomic_skip_bp_addr;
 
+	/* When all tasks are stopped, this callback gets called.  */
+	void (*on_all_stopped)(struct process_stopping_handler *);
+
 	enum {
 		/* We are waiting for everyone to land in t/T.  */
 		psh_stopping = 0,
@@ -684,6 +687,21 @@
 	post_singlestep(self, eventp);
 }
 
+static void
+disable_and_singlestep(struct process_stopping_handler *self)
+{
+	struct Process *teb = self->task_enabling_breakpoint;
+	debug(DEBUG_PROCESS, "all stopped, now SINGLESTEP %d", teb->pid);
+	if (self->breakpoint_being_enabled->enabled)
+		disable_breakpoint(teb, self->breakpoint_being_enabled);
+	if (singlestep(self) < 0) {
+		singlestep_error(self, &event);
+		//goto psh_sinking;  /* XXX FIME */
+		abort();
+	}
+	self->state = psh_singlestep;
+}
+
 /* This event handler is installed when we are in the process of
  * stopping the whole thread group to do the pointer re-enablement for
  * one of the threads.  We pump all events to the queue for later
@@ -696,7 +714,6 @@
 	struct process_stopping_handler * self = (void *)super;
 	Process * task = event->proc;
 	Process * leader = task->leader;
-	struct breakpoint *sbp = self->breakpoint_being_enabled;
 	Process * teb = self->task_enabling_breakpoint;
 
 	debug(DEBUG_PROCESS,
@@ -731,16 +748,8 @@
 		/* If everyone is stopped, singlestep.  */
 		if (each_task(leader, NULL, &task_blocked,
 			      &self->pids) == NULL) {
-			debug(DEBUG_PROCESS, "all stopped, now SINGLESTEP %d",
-			      teb->pid);
-			if (sbp->enabled)
-				disable_breakpoint(teb, sbp);
-			if (singlestep(self) < 0) {
-				singlestep_error(self, &event);
-				goto psh_sinking;
-			}
-
-			self->state = state = psh_singlestep;
+			(self->on_all_stopped)(self);
+			state = self->state;
 		}
 		break;
 
@@ -749,7 +758,8 @@
 		 * have now stepped, and can re-enable the breakpoint.  */
 		if (event != NULL && task == teb) {
 
-			/* This is not the singlestep that we are waiting for.  */
+			/* This is not the singlestep that we are
+			 * waiting for.  */
 			if (event->type == EVENT_SIGNAL) {
 				if (singlestep(self) < 0) {
 					singlestep_error(self, &event);
@@ -761,6 +771,7 @@
 			/* Essentially we don't care what event caused
 			 * the thread to stop.  We can do the
 			 * re-enablement now.  */
+			struct breakpoint *sbp = self->breakpoint_being_enabled;
 			if (sbp->enabled)
 				enable_breakpoint(teb, sbp);
 
@@ -807,10 +818,44 @@
 	free(self->pids.tasks);
 }
 
+int
+process_install_stopping_handler(struct Process *proc, struct breakpoint *sbp,
+				 void (*cb)(struct process_stopping_handler *))
+{
+	struct process_stopping_handler *handler = calloc(sizeof(*handler), 1);
+	if (handler == NULL)
+		return -1;
+
+	handler->super.on_event = process_stopping_on_event;
+	handler->super.destroy = process_stopping_destroy;
+	handler->task_enabling_breakpoint = proc;
+	handler->breakpoint_being_enabled = sbp;
+	handler->on_all_stopped = cb;
+
+	install_event_handler(proc->leader, &handler->super);
+
+	if (each_task(proc->leader, NULL, &send_sigstop,
+		      &handler->pids) != NULL) {
+		destroy_event_handler(proc);
+		return -1;
+	}
+
+	/* And deliver the first fake event, in case all the
+	 * conditions are already fulfilled.  */
+	Event ev = {
+		.type = EVENT_NONE,
+		.proc = proc,
+	};
+	process_stopping_on_event(&handler->super, &ev);
+
+	return 0;
+}
+
 void
 continue_after_breakpoint(Process *proc, struct breakpoint *sbp)
 {
 	set_instruction_pointer(proc, sbp->addr);
+
 	if (sbp->enabled == 0) {
 		continue_process(proc->pid);
 	} else {
@@ -821,32 +866,12 @@
 		/* we don't want to singlestep here */
 		continue_process(proc->pid);
 #else
-		struct process_stopping_handler * handler
-			= calloc(sizeof(*handler), 1);
-		if (handler == NULL) {
-			perror("malloc breakpoint disable handler");
-		fatal:
+		if (process_install_stopping_handler
+		    (proc, sbp, &disable_and_singlestep) < 0) {
+			perror("process_stopping_handler_create");
 			/* Carry on not bothering to re-enable.  */
 			continue_process(proc->pid);
-			return;
 		}
-
-		handler->super.on_event = process_stopping_on_event;
-		handler->super.destroy = process_stopping_destroy;
-		handler->task_enabling_breakpoint = proc;
-		handler->breakpoint_being_enabled = sbp;
-		install_event_handler(proc->leader, &handler->super);
-
-		if (each_task(proc->leader, NULL, &send_sigstop,
-			      &handler->pids) != NULL)
-			goto fatal;
-
-		/* And deliver the first fake event, in case all the
-		 * conditions are already fulfilled.  */
-		Event ev;
-		ev.type = EVENT_NONE;
-		ev.proc = proc;
-		process_stopping_on_event(&handler->super, &ev);
 #endif
 	}
 }