MEDIUM: channel: don't always set CF_WAKE_WRITE on bi_put*

It was inappropriate to put this flag on every failed write into an
input buffer because it depends where it happens. When it's in the
context of an analyser (eg: hlua) it makes sense. When it's in the
context of an applet (eg: dumpstats), it does not make sense, and
it only happens to work because currently applets are scheduled by
the sessions. The proper solution for applets would be to add the
flag SI_FL_WAIT_ROOM on the stream interface.

Thus, we now don't set any flag anymore in bi_put* and it's up to the
caller to either set CF_WAKE_WRITE on the channel or SI_FL_WAIT_ROOM
on the stream interface. Changes were applied to hlua, peers and
dumpstats.
diff --git a/src/dumpstats.c b/src/dumpstats.c
index 0e87f09..8dd9459 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -579,8 +579,10 @@
 	if (target && s->listener->bind_conf->level < ACCESS_LVL_OPER)
 		chunk_appendf(msg, "# contents not dumped due to insufficient privileges\n");
 
-	if (bi_putchk(si_ic(si), msg) == -1)
+	if (bi_putchk(si_ic(si), msg) == -1) {
+		si->flags |= SI_FL_WAIT_ROOM;
 		return 0;
+	}
 
 	return 1;
 }
@@ -650,8 +652,10 @@
 	}
 	chunk_appendf(msg, "\n");
 
-	if (bi_putchk(si_ic(si), msg) == -1)
+	if (bi_putchk(si_ic(si), msg) == -1) {
+		si->flags |= SI_FL_WAIT_ROOM;
 		return 0;
+	}
 
 	return 1;
 }
@@ -1329,7 +1333,9 @@
 
 			/* return server's effective weight at the moment */
 			snprintf(trash.str, trash.size, "%d (initial %d)\n", sv->uweight, sv->iweight);
-			bi_putstr(si_ic(si), trash.str);
+			if (bi_putstr(si_ic(si), trash.str) == -1)
+				si->flags |= SI_FL_WAIT_ROOM;
+
 			return 1;
 		}
 		else if (strcmp(args[1], "map") == 0 || strcmp(args[1], "acl") == 0) {
@@ -2264,7 +2270,7 @@
 			 * would want to return some info right after parsing.
 			 */
 			if (buffer_almost_full(si_ib(si))) {
-				si_ic(si)->flags |= CF_WAKE_WRITE;
+				si->flags |= SI_FL_WAIT_ROOM;
 				break;
 			}
 
@@ -2342,12 +2348,16 @@
 			case STAT_CLI_PRINT:
 				if (bi_putstr(si_ic(si), appctx->ctx.cli.msg) != -1)
 					appctx->st0 = STAT_CLI_PROMPT;
+				else
+					si->flags |= SI_FL_WAIT_ROOM;
 				break;
 			case STAT_CLI_PRINT_FREE:
 				if (bi_putstr(si_ic(si), appctx->ctx.cli.err) != -1) {
 					free(appctx->ctx.cli.err);
 					appctx->st0 = STAT_CLI_PROMPT;
 				}
+				else
+					si->flags |= SI_FL_WAIT_ROOM;
 				break;
 			case STAT_CLI_O_INFO:
 				if (stats_dump_info_to_buffer(si))
@@ -2396,6 +2406,8 @@
 			if (appctx->st0 == STAT_CLI_PROMPT) {
 				if (bi_putstr(si_ic(si), appctx->st1 ? "\n> " : "\n") != -1)
 					appctx->st0 = STAT_CLI_GETREQ;
+				else
+					si->flags |= SI_FL_WAIT_ROOM;
 			}
 
 			/* If the output functions are still there, it means they require more room. */
@@ -2563,8 +2575,10 @@
 	             global.node, global.desc ? global.desc : ""
 	             );
 
-	if (bi_putchk(si_ic(si), &trash) == -1)
+	if (bi_putchk(si_ic(si), &trash) == -1) {
+		si->flags |= SI_FL_WAIT_ROOM;
 		return 0;
+	}
 
 	return 1;
 }
@@ -2576,8 +2590,10 @@
 static int stats_dump_pools_to_buffer(struct stream_interface *si)
 {
 	dump_pools_to_trash();
-	if (bi_putchk(si_ic(si), &trash) == -1)
+	if (bi_putchk(si_ic(si), &trash) == -1) {
+		si->flags |= SI_FL_WAIT_ROOM;
 		return 0;
+	}
 	return 1;
 }
 
@@ -3788,8 +3804,10 @@
 	case STAT_PX_ST_TH:
 		if (appctx->ctx.stats.flags & STAT_FMT_HTML) {
 			stats_dump_html_px_hdr(si, px, uri);
-			if (bi_putchk(rep, &trash) == -1)
+			if (bi_putchk(rep, &trash) == -1) {
+				si->flags |= SI_FL_WAIT_ROOM;
 				return 0;
+			}
 		}
 
 		appctx->ctx.stats.px_st = STAT_PX_ST_FE;
@@ -3797,9 +3815,12 @@
 
 	case STAT_PX_ST_FE:
 		/* print the frontend */
-		if (stats_dump_fe_stats(si, px))
-			if (bi_putchk(rep, &trash) == -1)
+		if (stats_dump_fe_stats(si, px)) {
+			if (bi_putchk(rep, &trash) == -1) {
+				si->flags |= SI_FL_WAIT_ROOM;
 				return 0;
+			}
+		}
 
 		appctx->ctx.stats.l = px->conf.listeners.n;
 		appctx->ctx.stats.px_st = STAT_PX_ST_LI;
@@ -3809,7 +3830,7 @@
 		/* stats.l has been initialized above */
 		for (; appctx->ctx.stats.l != &px->conf.listeners; appctx->ctx.stats.l = l->by_fe.n) {
 			if (buffer_almost_full(rep->buf)) {
-				rep->flags |= CF_WAKE_WRITE;
+				si->flags |= SI_FL_WAIT_ROOM;
 				return 0;
 			}
 
@@ -3826,9 +3847,12 @@
 			}
 
 			/* print the frontend */
-			if (stats_dump_li_stats(si, px, l, uri ? uri->flags : 0))
-				if (bi_putchk(rep, &trash) == -1)
+			if (stats_dump_li_stats(si, px, l, uri ? uri->flags : 0)) {
+				if (bi_putchk(rep, &trash) == -1) {
+					si->flags |= SI_FL_WAIT_ROOM;
 					return 0;
+				}
+			}
 		}
 
 		appctx->ctx.stats.sv = px->srv; /* may be NULL */
@@ -3841,7 +3865,7 @@
 			int sv_state;
 
 			if (buffer_almost_full(rep->buf)) {
-				rep->flags |= CF_WAKE_WRITE;
+				si->flags |= SI_FL_WAIT_ROOM;
 				return 0;
 			}
 
@@ -3904,9 +3928,12 @@
 				continue;
 			}
 
-			if (stats_dump_sv_stats(si, px, uri ? uri->flags : 0, sv, sv_state))
-				if (bi_putchk(rep, &trash) == -1)
+			if (stats_dump_sv_stats(si, px, uri ? uri->flags : 0, sv, sv_state)) {
+				if (bi_putchk(rep, &trash) == -1) {
+					si->flags |= SI_FL_WAIT_ROOM;
 					return 0;
+				}
+			}
 		} /* for sv */
 
 		appctx->ctx.stats.px_st = STAT_PX_ST_BE;
@@ -3914,9 +3941,12 @@
 
 	case STAT_PX_ST_BE:
 		/* print the backend */
-		if (stats_dump_be_stats(si, px, uri ? uri->flags : 0))
-			if (bi_putchk(rep, &trash) == -1)
+		if (stats_dump_be_stats(si, px, uri ? uri->flags : 0)) {
+			if (bi_putchk(rep, &trash) == -1) {
+				si->flags |= SI_FL_WAIT_ROOM;
 				return 0;
+			}
+		}
 
 		appctx->ctx.stats.px_st = STAT_PX_ST_END;
 		/* fall through */
@@ -3924,8 +3954,10 @@
 	case STAT_PX_ST_END:
 		if (appctx->ctx.stats.flags & STAT_FMT_HTML) {
 			stats_dump_html_px_end(si, px);
-			if (bi_putchk(rep, &trash) == -1)
+			if (bi_putchk(rep, &trash) == -1) {
+				si->flags |= SI_FL_WAIT_ROOM;
 				return 0;
+			}
 		}
 
 		appctx->ctx.stats.px_st = STAT_PX_ST_FIN;
@@ -4321,8 +4353,10 @@
 		else
 			stats_dump_csv_header();
 
-		if (bi_putchk(rep, &trash) == -1)
+		if (bi_putchk(rep, &trash) == -1) {
+			si->flags |= SI_FL_WAIT_ROOM;
 			return 0;
+		}
 
 		appctx->st2 = STAT_ST_INFO;
 		/* fall through */
@@ -4330,8 +4364,10 @@
 	case STAT_ST_INFO:
 		if (appctx->ctx.stats.flags & STAT_FMT_HTML) {
 			stats_dump_html_info(si, uri);
-			if (bi_putchk(rep, &trash) == -1)
+			if (bi_putchk(rep, &trash) == -1) {
+				si->flags |= SI_FL_WAIT_ROOM;
 				return 0;
+			}
 		}
 
 		appctx->ctx.stats.px = proxy;
@@ -4343,7 +4379,7 @@
 		/* dump proxies */
 		while (appctx->ctx.stats.px) {
 			if (buffer_almost_full(rep->buf)) {
-				rep->flags |= CF_WAKE_WRITE;
+				si->flags |= SI_FL_WAIT_ROOM;
 				return 0;
 			}
 
@@ -4364,8 +4400,10 @@
 	case STAT_ST_END:
 		if (appctx->ctx.stats.flags & STAT_FMT_HTML) {
 			stats_dump_html_end();
-			if (bi_putchk(rep, &trash) == -1)
+			if (bi_putchk(rep, &trash) == -1) {
+				si->flags |= SI_FL_WAIT_ROOM;
 				return 0;
+			}
 		}
 
 		appctx->st2 = STAT_ST_FIN;
@@ -4732,8 +4770,10 @@
 	s->txn.status = 200;
 	s->logs.tv_request = now;
 
-	if (bi_putchk(si_ic(si), &trash) == -1)
+	if (bi_putchk(si_ic(si), &trash) == -1) {
+		si->flags |= SI_FL_WAIT_ROOM;
 		return 0;
+	}
 
 	return 1;
 }
@@ -4777,8 +4817,10 @@
 	s->txn.status = 303;
 	s->logs.tv_request = now;
 
-	if (bi_putchk(si_ic(si), &trash) == -1)
+	if (bi_putchk(si_ic(si), &trash) == -1) {
+		si->flags |= SI_FL_WAIT_ROOM;
 		return 0;
+	}
 
 	return 1;
 }
@@ -4828,6 +4870,7 @@
 			si_ic(si)->to_forward = 0;
 			chunk_printf(&trash, "\r\n000000\r\n");
 			if (bi_putchk(si_ic(si), &trash) == -1) {
+				si->flags |= SI_FL_WAIT_ROOM;
 				si_ic(si)->to_forward = last_fwd;
 				goto fail;
 			}
@@ -4852,7 +4895,8 @@
 
 			if (last_len != data_len) {
 				chunk_printf(&trash, "\r\n%06x\r\n", (last_len - data_len));
-				bi_putchk(si_ic(si), &trash);
+				if (bi_putchk(si_ic(si), &trash) == -1)
+					si->flags |= SI_FL_WAIT_ROOM;
 
 				si_ic(si)->total += (last_len - data_len);
 				si_ib(si)->i     += (last_len - data_len);
@@ -4877,8 +4921,10 @@
 	if (appctx->st0 == STAT_HTTP_DONE) {
 		if (appctx->ctx.stats.flags & STAT_CHUNKED) {
 			chunk_printf(&trash, "\r\n0\r\n\r\n");
-			if (bi_putchk(si_ic(si), &trash) == -1)
+			if (bi_putchk(si_ic(si), &trash) == -1) {
+				si->flags |= SI_FL_WAIT_ROOM;
 				goto fail;
+			}
 		}
 		/* eat the whole request */
 		bo_skip(si_oc(si), si_ob(si)->o);
@@ -4976,8 +5022,10 @@
 	if (appctx->ctx.sess.section > 0 && appctx->ctx.sess.uid != sess->uniq_id) {
 		/* session changed, no need to go any further */
 		chunk_appendf(&trash, "  *** session terminated while we were watching it ***\n");
-		if (bi_putchk(si_ic(si), &trash) == -1)
+		if (bi_putchk(si_ic(si), &trash) == -1) {
+			si->flags |= SI_FL_WAIT_ROOM;
 			return 0;
+		}
 		appctx->ctx.sess.uid = 0;
 		appctx->ctx.sess.section = 0;
 		return 1;
@@ -5256,8 +5304,10 @@
 			     sess->txn.rsp.next, sess->res.buf->i,
 			     sess->res.buf->size);
 
-		if (bi_putchk(si_ic(si), &trash) == -1)
+		if (bi_putchk(si_ic(si), &trash) == -1) {
+			si->flags |= SI_FL_WAIT_ROOM;
 			return 0;
+		}
 
 		/* use other states to dump the contents */
 	}
@@ -5279,8 +5329,10 @@
 		 */
 		chunk_reset(&trash);
 		chunk_appendf(&trash, "# id (file) description\n");
-		if (bi_putchk(si_ic(si), &trash) == -1)
+		if (bi_putchk(si_ic(si), &trash) == -1) {
+			si->flags |= SI_FL_WAIT_ROOM;
 			return 0;
+		}
 
 		/* Now, we start the browsing of the references lists.
 		 * Note that the following call to LIST_ELEM return bad pointer. The only
@@ -5308,6 +5360,7 @@
 				/* let's try again later from this session. We add ourselves into
 				 * this session's users so that it can remove us upon termination.
 				 */
+				si->flags |= SI_FL_WAIT_ROOM;
 				return 0;
 			}
 
@@ -5426,6 +5479,7 @@
 				/* let's try again later from this session. We add ourselves into
 				 * this session's users so that it can remove us upon termination.
 				 */
+				si->flags |= SI_FL_WAIT_ROOM;
 				return 0;
 			}
 
@@ -5476,6 +5530,7 @@
 				/* let's try again later from this session. We add ourselves into
 				 * this session's users so that it can remove us upon termination.
 				 */
+				si->flags |= SI_FL_WAIT_ROOM;
 				return 0;
 			}
 
@@ -5680,6 +5735,7 @@
 				/* let's try again later from this session. We add ourselves into
 				 * this session's users so that it can remove us upon termination.
 				 */
+				si->flags |= SI_FL_WAIT_ROOM;
 				LIST_ADDQ(&curr_sess->back_refs, &appctx->ctx.sess.bref.users);
 				return 0;
 			}
@@ -5695,8 +5751,10 @@
 			else
 				chunk_appendf(&trash, "Session not found.\n");
 
-			if (bi_putchk(si_ic(si), &trash) == -1)
+			if (bi_putchk(si_ic(si), &trash) == -1) {
+				si->flags |= SI_FL_WAIT_ROOM;
 				return 0;
+			}
 
 			appctx->ctx.sess.target = NULL;
 			appctx->ctx.sess.uid = 0;
@@ -5977,6 +6035,7 @@
 
 		if (bi_putchk(si_ic(si), &trash) == -1) {
 			/* Socket buffer full. Let's try again later from the same point */
+			si->flags |= SI_FL_WAIT_ROOM;
 			return 0;
 		}
 
@@ -6061,6 +6120,7 @@
 
 			if (bi_putchk(si_ic(si), &trash) == -1) {
 				/* Socket buffer full. Let's try again later from the same point */
+				si->flags |= SI_FL_WAIT_ROOM;
 				return 0;
 			}
 			appctx->ctx.errors.ptr = 0;
@@ -6071,8 +6131,10 @@
 			/* the snapshot changed while we were dumping it */
 			chunk_appendf(&trash,
 				     "  WARNING! update detected on this snapshot, dump interrupted. Please re-check!\n");
-			if (bi_putchk(si_ic(si), &trash) == -1)
+			if (bi_putchk(si_ic(si), &trash) == -1) {
+				si->flags |= SI_FL_WAIT_ROOM;
 				return 0;
+			}
 			goto next;
 		}
 
@@ -6088,6 +6150,7 @@
 
 			if (bi_putchk(si_ic(si), &trash) == -1) {
 				/* Socket buffer full. Let's try again later from the same point */
+				si->flags |= SI_FL_WAIT_ROOM;
 				return 0;
 			}
 			appctx->ctx.errors.ptr = newptr;