BUG/MINOR: deinit/threads: make hard-stop-after perform a clean exit

As reported in GH issue #99, when hard-stop-after triggers and threads
are in use, the chance that any thread releases the resources in use by
the other ones is non-null. Thus no thread should be allowed to deinit()
nor exit by itself.

Here we take a different approach. We simply use a 3rd possible value
for the "killed" variable so that all threads know they must break out
of the run-poll-loop and immediately stop.

This patch was tested by commenting the stream_shutdown() calls in
hard_stop() to increase the chances to see a stream use released
resources. With this fix applied, it never crashes anymore.

This fix should be backported to 1.9 and 1.8.
diff --git a/include/types/global.h b/include/types/global.h
index a87b407..5fca648 100644
--- a/include/types/global.h
+++ b/include/types/global.h
@@ -233,7 +233,7 @@
 extern const int one;
 extern const struct linger nolinger;
 extern int stopping;	/* non zero means stopping in progress */
-extern int killed;	/* non zero means a hard-stop is triggered */
+extern int killed;	/* >0 means a hard-stop is triggered, >1 means hard-stop immediately */
 extern char hostname[MAX_HOSTNAME_LEN];
 extern char localpeer[MAX_HOSTNAME_LEN];
 extern struct list global_listener_queue; /* list of the temporarily limited listeners */
diff --git a/src/haproxy.c b/src/haproxy.c
index df9a686..9c93bed 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -2524,6 +2524,10 @@
 		if ((jobs - unstoppable_jobs) == 0)
 			break;
 
+		/* also stop  if we failed to cleanly stop all tasks */
+		if (killed > 1)
+			break;
+
 		/* expire immediately if events are pending */
 		wake = 1;
 		if (fd_cache_mask & tid_bit)
diff --git a/src/proxy.c b/src/proxy.c
index 9fda6e2..575a8ef 100644
--- a/src/proxy.c
+++ b/src/proxy.c
@@ -1071,9 +1071,9 @@
 	if (killed) {
 		ha_warning("Some tasks resisted to hard-stop, exiting now.\n");
 		send_log(NULL, LOG_WARNING, "Some tasks resisted to hard-stop, exiting now.\n");
-		/* Do some cleanup and explicitly quit */
-		deinit();
-		exit(0);
+		killed = 2;
+		t->expire = TICK_ETERNITY;
+		return t;
 	}
 
 	ha_warning("soft-stop running for too long, performing a hard-stop.\n");