MEDIUM: cli: yield between each pipelined command

Pipelining commands on the CLI is sometimes needed for batched operations
such as map deletion etc, but it causes two problems:
  - some possibly long-running commands will be run in series without
    yielding, possibly causing extremely long latencies that will affect
    quality of service and even trigger the watchdog, as seen in github
    issue #1515.

  - short commands that end on a buffer size boundary, when not run in
    interactive mode, will often cause the socket to be closed when
    the last command is parsed, because the buffer is empty.

This patch proposes a small change to this: by yielding in the CLI applet
after processing a command when there are data left, we significantly
reduce the latency, since only one command is executed per call, and
we leave an opportunity for the I/O layers to refill the request buffer
with more commands, hence to execute all of them much more often.

With this change there's no more watchdog triggered on long series of
"del map" on large map files, and the operations are much less disturbed.
It would be desirable to backport this patch to stable versions after some
period of observation in recent versions.

(cherry picked from commit fa7b4f6691646dc6bdebdb0d11c9cdf0382aeccb)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit ec91650b88e1ef11decbca4b1eb11913bd7ccf03)
Signed-off-by: Willy Tarreau <w@1wt.eu>
diff --git a/src/cli.c b/src/cli.c
index a65db80..454347a 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -1064,6 +1064,17 @@
 			appctx->st0 = CLI_ST_GETREQ;
 			/* reactivate the \n at the end of the response for the next command */
 			appctx->st1 &= ~APPCTX_CLI_ST1_NOLF;
+
+			/* this forces us to yield between pipelined commands and
+			 * avoid extremely long latencies (e.g. "del map" etc). In
+			 * addition this increases the likelihood that the stream
+			 * refills the buffer with new bytes in non-interactive
+			 * mode, avoiding to close on apparently empty commands.
+			 */
+			if (co_data(si_oc(si))) {
+				appctx_wakeup(appctx);
+				goto out;
+			}
 		}
 	}