From fe127937a8d3d198d91a989895093b1faedce809 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Tue, 21 Apr 2015 19:23:39 +0200 Subject: [PATCH] MEDIUM: applet: make the applets only use si_applet_{cant|want|stop}_{get|put} The applets don't fiddle with SI_FL_WAIT_ROOM anymore, instead they indicate what they want, possibly that they failed (eg: WAIT_ROOM), and it's done() / update() which finally updates the WAIT_* flags according to the channels' and stream interface's states. This solves the issue of the pauses during a "show sess" without creating busy loops. --- src/applet.c | 7 ++++ src/dumpstats.c | 76 +++++++++++++++++++++--------------------- src/peers.c | 2 +- src/stream.c | 2 +- src/stream_interface.c | 20 +++++------ 5 files changed, 55 insertions(+), 52 deletions(-) diff --git a/src/applet.c b/src/applet.c index 37303f744..481000a80 100644 --- a/src/applet.c +++ b/src/applet.c @@ -37,6 +37,13 @@ void applet_run_active() continue; } + /* We always pretend the applet can't get and doesn't want to + * put, it's up to it to change this if needed. This ensures + * that one applet which ignores any event will not spin. + */ + si_applet_cant_get(si); + si_applet_stop_put(si); + curr->applet->fct(curr); si_applet_done(si); } diff --git a/src/dumpstats.c b/src/dumpstats.c index c835b1eb9..b8e822ff5 100644 --- a/src/dumpstats.c +++ b/src/dumpstats.c @@ -557,7 +557,7 @@ static int stats_dump_table_head_to_buffer(struct chunk *msg, struct stream_inte chunk_appendf(msg, "# contents not dumped due to insufficient privileges\n"); if (bi_putchk(si_ic(si), msg) == -1) { - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); return 0; } @@ -630,7 +630,7 @@ static int stats_dump_table_entry_to_buffer(struct chunk *msg, struct stream_int chunk_appendf(msg, "\n"); if (bi_putchk(si_ic(si), msg) == -1) { - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); return 0; } @@ -1311,7 +1311,7 @@ static int stats_sock_parse_request(struct stream_interface *si, char *line) /* return server's effective weight at the moment */ snprintf(trash.str, trash.size, "%d (initial %d)\n", sv->uweight, sv->iweight); if (bi_putstr(si_ic(si), trash.str) == -1) - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); return 1; } @@ -2247,7 +2247,7 @@ static void cli_io_handler(struct appctx *appctx) * would want to return some info right after parsing. */ if (buffer_almost_full(si_ib(si))) { - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); break; } @@ -2326,7 +2326,7 @@ static void cli_io_handler(struct appctx *appctx) if (bi_putstr(si_ic(si), appctx->ctx.cli.msg) != -1) appctx->st0 = STAT_CLI_PROMPT; else - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); break; case STAT_CLI_PRINT_FREE: if (bi_putstr(si_ic(si), appctx->ctx.cli.err) != -1) { @@ -2334,7 +2334,7 @@ static void cli_io_handler(struct appctx *appctx) appctx->st0 = STAT_CLI_PROMPT; } else - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); break; case STAT_CLI_O_INFO: if (stats_dump_info_to_buffer(si)) @@ -2384,7 +2384,7 @@ static void cli_io_handler(struct appctx *appctx) if (bi_putstr(si_ic(si), appctx->st1 ? "\n> " : "\n") != -1) appctx->st0 = STAT_CLI_GETREQ; else - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); } /* If the output functions are still there, it means they require more room. */ @@ -2541,7 +2541,7 @@ static int stats_dump_info_to_buffer(struct stream_interface *si) ); if (bi_putchk(si_ic(si), &trash) == -1) { - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); return 0; } @@ -2556,7 +2556,7 @@ static int stats_dump_pools_to_buffer(struct stream_interface *si) { dump_pools_to_trash(); if (bi_putchk(si_ic(si), &trash) == -1) { - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); return 0; } return 1; @@ -3809,7 +3809,7 @@ static int stats_dump_proxy_to_buffer(struct stream_interface *si, struct proxy if (appctx->ctx.stats.flags & STAT_FMT_HTML) { stats_dump_html_px_hdr(si, px, uri); if (bi_putchk(rep, &trash) == -1) { - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); return 0; } } @@ -3821,7 +3821,7 @@ static int stats_dump_proxy_to_buffer(struct stream_interface *si, struct proxy /* print the frontend */ if (stats_dump_fe_stats(si, px)) { if (bi_putchk(rep, &trash) == -1) { - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); return 0; } } @@ -3834,7 +3834,7 @@ static int stats_dump_proxy_to_buffer(struct stream_interface *si, struct proxy /* 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)) { - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); return 0; } @@ -3853,7 +3853,7 @@ static int stats_dump_proxy_to_buffer(struct stream_interface *si, struct proxy /* print the frontend */ if (stats_dump_li_stats(si, px, l, uri ? uri->flags : 0)) { if (bi_putchk(rep, &trash) == -1) { - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); return 0; } } @@ -3870,7 +3870,7 @@ static int stats_dump_proxy_to_buffer(struct stream_interface *si, struct proxy enum srv_stats_colour sv_colour; if (buffer_almost_full(rep->buf)) { - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); return 0; } @@ -3949,7 +3949,7 @@ static int stats_dump_proxy_to_buffer(struct stream_interface *si, struct proxy if (stats_dump_sv_stats(si, px, uri ? uri->flags : 0, sv, sv_state, sv_colour)) { if (bi_putchk(rep, &trash) == -1) { - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); return 0; } } @@ -3962,7 +3962,7 @@ static int stats_dump_proxy_to_buffer(struct stream_interface *si, struct proxy /* print the backend */ if (stats_dump_be_stats(si, px, uri ? uri->flags : 0)) { if (bi_putchk(rep, &trash) == -1) { - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); return 0; } } @@ -3974,7 +3974,7 @@ static int stats_dump_proxy_to_buffer(struct stream_interface *si, struct proxy if (appctx->ctx.stats.flags & STAT_FMT_HTML) { stats_dump_html_px_end(si, px); if (bi_putchk(rep, &trash) == -1) { - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); return 0; } } @@ -4367,7 +4367,7 @@ static int stats_dump_stat_to_buffer(struct stream_interface *si, struct uri_aut stats_dump_csv_header(); if (bi_putchk(rep, &trash) == -1) { - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); return 0; } @@ -4378,7 +4378,7 @@ static int stats_dump_stat_to_buffer(struct stream_interface *si, struct uri_aut if (appctx->ctx.stats.flags & STAT_FMT_HTML) { stats_dump_html_info(si, uri); if (bi_putchk(rep, &trash) == -1) { - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); return 0; } } @@ -4392,7 +4392,7 @@ static int stats_dump_stat_to_buffer(struct stream_interface *si, struct uri_aut /* dump proxies */ while (appctx->ctx.stats.px) { if (buffer_almost_full(rep->buf)) { - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); return 0; } @@ -4414,7 +4414,7 @@ static int stats_dump_stat_to_buffer(struct stream_interface *si, struct uri_aut if (appctx->ctx.stats.flags & STAT_FMT_HTML) { stats_dump_html_end(); if (bi_putchk(rep, &trash) == -1) { - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); return 0; } } @@ -4784,7 +4784,7 @@ static int stats_send_http_headers(struct stream_interface *si) s->logs.tv_request = now; if (bi_putchk(si_ic(si), &trash) == -1) { - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); return 0; } @@ -4831,7 +4831,7 @@ static int stats_send_http_redirect(struct stream_interface *si) s->logs.tv_request = now; if (bi_putchk(si_ic(si), &trash) == -1) { - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); return 0; } @@ -4883,7 +4883,7 @@ static void http_stats_io_handler(struct appctx *appctx) 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_applet_cant_put(si); si_ic(si)->to_forward = last_fwd; goto out; } @@ -4909,7 +4909,7 @@ static void http_stats_io_handler(struct appctx *appctx) if (last_len != data_len) { chunk_printf(&trash, "\r\n%06x\r\n", (last_len - data_len)); if (bi_putchk(si_ic(si), &trash) == -1) - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); si_ic(si)->total += (last_len - data_len); si_ib(si)->i += (last_len - data_len); @@ -4935,7 +4935,7 @@ static void http_stats_io_handler(struct appctx *appctx) if (appctx->ctx.stats.flags & STAT_CHUNKED) { chunk_printf(&trash, "\r\n0\r\n\r\n"); if (bi_putchk(si_ic(si), &trash) == -1) { - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); goto out; } } @@ -5024,7 +5024,7 @@ static int stats_dump_full_sess_to_buffer(struct stream_interface *si, struct st /* stream 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) { - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); return 0; } appctx->ctx.sess.uid = 0; @@ -5307,7 +5307,7 @@ static int stats_dump_full_sess_to_buffer(struct stream_interface *si, struct st sess->res.buf->size); if (bi_putchk(si_ic(si), &trash) == -1) { - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); return 0; } @@ -5332,7 +5332,7 @@ static int stats_pats_list(struct stream_interface *si) chunk_reset(&trash); chunk_appendf(&trash, "# id (file) description\n"); if (bi_putchk(si_ic(si), &trash) == -1) { - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); return 0; } @@ -5362,7 +5362,7 @@ static int stats_pats_list(struct stream_interface *si) /* let's try again later from this stream. We add ourselves into * this stream's users so that it can remove us upon termination. */ - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); return 0; } @@ -5481,7 +5481,7 @@ static int stats_map_lookup(struct stream_interface *si) /* let's try again later from this stream. We add ourselves into * this stream's users so that it can remove us upon termination. */ - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); return 0; } @@ -5532,7 +5532,7 @@ static int stats_pat_list(struct stream_interface *si) /* let's try again later from this stream. We add ourselves into * this stream's users so that it can remove us upon termination. */ - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); return 0; } @@ -5737,7 +5737,7 @@ static int stats_dump_sess_to_buffer(struct stream_interface *si) /* let's try again later from this stream. We add ourselves into * this stream's users so that it can remove us upon termination. */ - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); LIST_ADDQ(&curr_sess->back_refs, &appctx->ctx.sess.bref.users); return 0; } @@ -5754,7 +5754,7 @@ static int stats_dump_sess_to_buffer(struct stream_interface *si) chunk_appendf(&trash, "Session not found.\n"); if (bi_putchk(si_ic(si), &trash) == -1) { - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); return 0; } @@ -6035,7 +6035,7 @@ static int stats_dump_errors_to_buffer(struct stream_interface *si) 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; + si_applet_cant_put(si); return 0; } @@ -6120,7 +6120,7 @@ static int stats_dump_errors_to_buffer(struct stream_interface *si) 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; + si_applet_cant_put(si); return 0; } appctx->ctx.errors.ptr = 0; @@ -6132,7 +6132,7 @@ static int stats_dump_errors_to_buffer(struct stream_interface *si) chunk_appendf(&trash, " WARNING! update detected on this snapshot, dump interrupted. Please re-check!\n"); if (bi_putchk(si_ic(si), &trash) == -1) { - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); return 0; } goto next; @@ -6150,7 +6150,7 @@ static int stats_dump_errors_to_buffer(struct stream_interface *si) 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; + si_applet_cant_put(si); return 0; } appctx->ctx.errors.ptr = newptr; diff --git a/src/peers.c b/src/peers.c index 5b6d81786..26b3e6fde 100644 --- a/src/peers.c +++ b/src/peers.c @@ -1046,7 +1046,7 @@ out: si_oc(si)->flags |= CF_READ_DONTWAIT; return; full: - si->flags |= SI_FL_WAIT_ROOM; + si_applet_cant_put(si); goto out; } diff --git a/src/stream.c b/src/stream.c index 77a67b808..12b6f9db8 100644 --- a/src/stream.c +++ b/src/stream.c @@ -200,7 +200,7 @@ struct stream *stream_new(struct session *sess, struct task *t, enum obj_type *o if (conn) conn_data_want_recv(conn); else if (appctx) - s->si[0].flags |= SI_FL_WAIT_DATA; + si_applet_want_get(&s->si[0]); if (sess->fe->accept && sess->fe->accept(s) < 0) goto out_fail_accept; diff --git a/src/stream_interface.c b/src/stream_interface.c index 55f0e2211..08946dfdf 100644 --- a/src/stream_interface.c +++ b/src/stream_interface.c @@ -393,7 +393,7 @@ struct appctx *stream_int_register_handler(struct stream_interface *si, struct a if (!appctx) return NULL; - si->flags |= SI_FL_WAIT_DATA; + si_applet_cant_get(si); appctx_wakeup(appctx); return si_appctx(si); } @@ -1433,14 +1433,9 @@ void si_applet_done(struct stream_interface *si) ic->rex = tick_add_ifset(now_ms, ic->rto); } - /* get away from the active list if we can't work anymore, that is - * we're blocked both for reads or writes or once both sides are closed. - * FIXME: we may have a problem here with bidirectional applets which - * might block on a single direction while the other one is still free. - */ - if ((si->flags & (SI_FL_WAIT_ROOM|SI_FL_WAIT_DATA)) || - (ic->flags & CF_DONT_READ) || - (ic->flags & CF_SHUTR && oc->flags & CF_SHUTW)) + /* get away from the active list if we can't work anymore. */ + if (((si->flags & (SI_FL_WANT_PUT|SI_FL_WAIT_ROOM)) != SI_FL_WANT_PUT) && + ((si->flags & (SI_FL_WANT_GET|SI_FL_WAIT_DATA)) != SI_FL_WANT_GET)) appctx_pause(si_appctx(si)); /* wake the task up only when needed */ @@ -1531,10 +1526,11 @@ void stream_int_update_applet(struct stream_interface *si) } } - if (!(si->flags & (SI_FL_WAIT_ROOM|SI_FL_WAIT_DATA)) && - !(ic->flags & CF_DONT_READ) && - (!(ic->flags & CF_SHUTR) || !(oc->flags & CF_SHUTW))) + if (((si->flags & (SI_FL_WANT_PUT|SI_FL_WAIT_ROOM)) == SI_FL_WANT_PUT) || + ((si->flags & (SI_FL_WANT_GET|SI_FL_WAIT_DATA)) == SI_FL_WANT_GET)) appctx_wakeup(si_appctx(si)); + else + appctx_pause(si_appctx(si)); } /*