]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: tevt/mux-fcgi: Report termination events for the FCGI connect/stream
authorChristopher Faulet <cfaulet@haproxy.com>
Wed, 5 Feb 2025 14:45:39 +0000 (15:45 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Thu, 6 Feb 2025 10:19:32 +0000 (11:19 +0100)
Termination events are now reported for the FCGI connections and the FCGI
streams. In addition, all available termination events logs are reported in
the "show-fd" callback function. The .ctl and .sctl callback functions were
also update to support, respectively, MUX_CTL_TEVTS and MUX_SCTL_TEVTS
commands.

src/mux_fcgi.c

index 7a8ceef5bc1875be2ac10bf14b42f10747a1227e..ea56184fa2be0d0239dd28e6310816a0188f1c19 100644 (file)
@@ -68,6 +68,8 @@ struct fcgi_conn {
        unsigned int nb_reserved;            /* number of reserved streams */
        unsigned int stream_cnt;             /* total number of streams seen */
 
+       uint32_t term_evts_log;              /* Termination events log: first 4 events reported */
+
        struct proxy *proxy;                 /* the proxy this connection was created for */
        struct fcgi_app *app;                /* FCGI application used by this mux */
        struct task *task;                   /* timeout management task */
@@ -690,6 +692,7 @@ static int fcgi_init(struct connection *conn, struct proxy *px, struct session *
        fconn->nb_sc = 0;
        fconn->nb_reserved = 0;
        fconn->stream_cnt = 0;
+       fconn->term_evts_log = 0;
 
        fconn->dbuf = *input;
        fconn->dsi = -1;
@@ -729,6 +732,14 @@ static int fcgi_init(struct connection *conn, struct proxy *px, struct session *
        return -1;
 }
 
+
+static inline void fcgi_conn_report_term_evt(struct fcgi_conn *fconn, enum muxc_term_event_type type)
+{
+       enum term_event_loc loc = tevt_loc_muxc + 8; /* Always on backend side for now */
+
+       fconn->term_evts_log = tevt_report_event(fconn->term_evts_log, loc, type);
+}
+
 /* Returns the next allocatable outgoing stream ID for the FCGI connection, or
  * -1 if no more is allocatable.
  */
@@ -758,7 +769,6 @@ static inline struct fcgi_strm *fcgi_conn_st_by_id(struct fcgi_conn *fconn, int
        return container_of(node, struct fcgi_strm, by_id);
 }
 
-
 /* Release function. This one should be called to free all resources allocated
  * to the mux.
  */
@@ -779,9 +789,12 @@ static void fcgi_release(struct fcgi_conn *fconn)
                fconn->task = NULL;
        }
        tasklet_free(fconn->wait_event.tasklet);
-       if (conn && fconn->wait_event.events != 0)
-               conn->xprt->unsubscribe(conn, conn->xprt_ctx, fconn->wait_event.events,
-                                       &fconn->wait_event);
+       if (conn) {
+               if (fconn->wait_event.events != 0)
+                       conn->xprt->unsubscribe(conn, conn->xprt_ctx, fconn->wait_event.events,
+                                               &fconn->wait_event);
+               fcgi_conn_report_term_evt(fconn, muxc_tevt_type_shutw);
+       }
 
        pool_free(pool_head_fcgi_conn, fconn);
 
@@ -941,16 +954,22 @@ static inline void fcgi_strm_propagate_term_flags(struct fcgi_conn *fconn, struc
        if (fstrm->h1m.state == H1_MSG_DONE) {
                se_fl_set(fstrm->sd, SE_FL_EOI);
                /* Add EOS flag for tunnel */
-               if (!(fstrm->h1m.flags & (H1_MF_VER_11|H1_MF_XFER_LEN)))
+               if (!(fstrm->h1m.flags & (H1_MF_VER_11|H1_MF_XFER_LEN))) {
                        se_fl_set(fstrm->sd, SE_FL_EOS);
+                       se_report_term_evt(fstrm->sd, (fconn->flags & FCGI_CF_ERROR ? se_tevt_type_rcv_err : se_tevt_type_eos));
+               }
        }
-       if (fcgi_conn_read0_pending(fconn) || fstrm->st == FCGI_SS_CLOSED) {
+       if (fcgi_conn_read0_pending(fconn) || fstrm->state == FCGI_SS_CLOSED) {
                se_fl_set(fstrm->sd, SE_FL_EOS);
-               if (!se_fl_test(fstrm->sd, SE_FL_EOI))
+               if (!se_fl_test(fstrm->sd, SE_FL_EOI)) {
                        se_fl_set(fstrm->sd, SE_FL_ERROR);
+                       se_report_term_evt(fstrm->sd, (fconn->flags & FCGI_CF_ERROR ? se_tevt_type_truncated_rcv_err : se_tevt_type_truncated_eos));
+               }
+               else
+                       se_report_term_evt(fstrm->sd, (fconn->flags & FCGI_CF_ERROR ? se_tevt_type_rcv_err : se_tevt_type_eos));
        }
        if (se_fl_test(fstrm->sd, SE_FL_ERR_PENDING))
-               se_fl_set(strm->sd, SE_FL_ERROR);
+               se_fl_set(fstrm->sd, SE_FL_ERROR);
 }
 
 /* Detaches a FCGI stream from its FCGI connection and releases it to the
@@ -1666,6 +1685,7 @@ static int fcgi_conn_send_aborts(struct fcgi_conn *fconn)
                        return 0;
        }
        fconn->flags |= FCGI_CF_ABRTS_SENT;
+       fcgi_conn_report_term_evt(fconn, muxc_tevt_type_graceful_shut);
        TRACE_STATE("aborts sent to all fstrms", FCGI_EV_TX_RECORD, fconn->conn);
        TRACE_LEAVE(FCGI_EV_TX_RECORD, fconn->conn);
        return 1;
@@ -1842,6 +1862,7 @@ static int fcgi_strm_send_abort(struct fcgi_conn *fconn, struct fcgi_strm *fstrm
        ret = fcgi_strm_send_empty_record(fconn, fstrm, FCGI_ABORT_REQUEST);
        if (ret) {
                fstrm->flags |= FCGI_SF_ABRT_SENT;
+               se_report_term_evt(fstrm->sd, se_tevt_type_cancelled);
                TRACE_PROTO("FCGI ABORT record xferred", FCGI_EV_TX_RECORD|FCGI_EV_TX_ABORT, fconn->conn, fstrm, 0, (size_t[]){0});
                TRACE_USER("FCGI request aborted", FCGI_EV_TX_RECORD|FCGI_EV_TX_ABORT, fconn->conn, fstrm);
                TRACE_STATE("abort sent", FCGI_EV_TX_RECORD|FCGI_EV_TX_ABORT, fconn->conn, fstrm);
@@ -2671,6 +2692,15 @@ static void fcgi_process_demux(struct fcgi_conn *fconn)
                        fconn->flags |= FCGI_CF_END_REACHED;
        }
 
+       if (fconn->flags & FCGI_CF_ERROR)
+               fcgi_conn_report_term_evt(fconn, ((eb_is_empty(&fconn->streams_by_id) && (fconn->state == FCGI_CS_RECORD_H))
+                                                 ? muxc_tevt_type_rcv_err
+                                                 : muxc_tevt_type_truncated_rcv_err));
+       else if (fconn->flags & FCGI_CF_END_REACHED)
+               fcgi_conn_report_term_evt(fconn, ((eb_is_empty(&fconn->streams_by_id) && (fconn->state == FCGI_CS_RECORD_H))
+                                                 ? muxc_tevt_type_shutr
+                                                 : muxc_tevt_type_truncated_shutr));
+
        /* Make sure to clear DFULL if contents were deleted */
        if (!b_full(&fconn->dbuf))
                fconn->flags &= ~FCGI_CF_DEM_DFULL;
@@ -2944,6 +2974,7 @@ static int fcgi_send(struct fcgi_conn *fconn)
 
        if (conn->flags & CO_FL_ERROR) {
                fconn->flags |= FCGI_CF_ERR_PENDING;
+               fcgi_conn_report_term_evt(fconn, muxc_tevt_type_snd_err);
                if (fconn->flags & FCGI_CF_EOS)
                        fconn->flags |= FCGI_CF_ERROR;
                b_reset(br_tail(fconn->mbuf));
@@ -3191,6 +3222,8 @@ static int fcgi_ctl(struct connection *conn, enum mux_ctl_type mux_ctl, void *ou
                return fconn->nb_streams;
        case MUX_CTL_GET_MAXSTRM:
                return fconn->streams_limit;
+       case MUX_CTL_TEVTS:
+               return fconn->term_evts_log;
        default:
                return -1;
        }
@@ -3206,7 +3239,8 @@ static int fcgi_sctl(struct stconn *sc, enum mux_sctl_type mux_sctl, void *outpu
                if (output)
                        *((int64_t *)output) = fstrm->id;
                return ret;
-
+       case MUX_SCTL_TEVTS:
+               return fstrm->sd->term_evts_log;
        default:
                return -1;
        }
@@ -3250,6 +3284,8 @@ struct task *fcgi_timeout_task(struct task *t, void *context, unsigned int state
                        conn_delete_from_tree(fconn->conn);
 
                HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
+
+               fcgi_conn_report_term_evt(fconn, muxc_tevt_type_tout);
        }
 
 do_leave:
@@ -4147,6 +4183,7 @@ static size_t fcgi_snd_buf(struct stconn *sc, struct buffer *buf, size_t count,
        if (fstrm->state == FCGI_SS_ERROR) {
                TRACE_DEVEL("reporting error to the app-layer stream", FCGI_EV_STRM_SEND|FCGI_EV_FSTRM_ERR|FCGI_EV_STRM_ERR, fconn->conn, fstrm);
                se_fl_set_error(fstrm->sd);
+               se_report_term_evt(fstrm->sd, se_tevt_type_snd_err);
                if (!(fstrm->flags & FCGI_SF_BEGIN_SENT) || fcgi_strm_send_abort(fconn, fstrm))
                        fcgi_strm_close(fstrm);
        }
@@ -4200,7 +4237,7 @@ static int fcgi_show_fd(struct buffer *msg, struct connection *conn)
        tmbuf = br_tail(fconn->mbuf);
        chunk_appendf(msg, " fconn.st0=%d .maxid=%d .flg=0x%04x .nbst=%u"
                      " .nbcs=%u .send_cnt=%d .tree_cnt=%d .orph_cnt=%d .sub=%d "
-                     ".dsi=%d .dbuf=%u@%p+%u/%u .mbuf=[%u..%u|%u],h=[%u@%p+%u/%u],t=[%u@%p+%u/%u]",
+                     ".dsi=%d .dbuf=%u@%p+%u/%u .mbuf=[%u..%u|%u],h=[%u@%p+%u/%u],t=[%u@%p+%u/%u] .evts=%s",
                      fconn->state, fconn->max_id, fconn->flags,
                      fconn->nb_streams, fconn->nb_sc, send_cnt, tree_cnt, orph_cnt,
                      fconn->wait_event.events, fconn->dsi,
@@ -4210,7 +4247,8 @@ static int fcgi_show_fd(struct buffer *msg, struct connection *conn)
                      (unsigned int)b_data(hmbuf), b_orig(hmbuf),
                      (unsigned int)b_head_ofs(hmbuf), (unsigned int)b_size(hmbuf),
                      (unsigned int)b_data(tmbuf), b_orig(tmbuf),
-                     (unsigned int)b_head_ofs(tmbuf), (unsigned int)b_size(tmbuf));
+                     (unsigned int)b_head_ofs(tmbuf), (unsigned int)b_size(tmbuf),
+                     tevt_evts2str(fconn->term_evts_log));
 
        if (fstrm) {
                chunk_appendf(msg, " last_fstrm=%p .id=%d .flg=0x%04x .rxbuf=%u@%p+%u/%u .sc=%p",
@@ -4219,10 +4257,10 @@ static int fcgi_show_fd(struct buffer *msg, struct connection *conn)
                              (unsigned int)b_head_ofs(&fstrm->rxbuf), (unsigned int)b_size(&fstrm->rxbuf),
                              fcgi_strm_sc(fstrm));
 
-               chunk_appendf(msg, " .sd.flg=0x%08x", se_fl_get(fstrm->sd));
+               chunk_appendf(msg, " .sd.flg=0x%08x .sd.evts=%s", se_fl_get(fstrm->sd), tevt_evts2str(fstrm->sd->term_evts_log));
                if (!se_fl_test(fstrm->sd, SE_FL_ORPHAN))
-                       chunk_appendf(msg, " .sc.flg=0x%08x .sc.app=%p",
-                                     fcgi_strm_sc(fstrm)->flags, fcgi_strm_sc(fstrm)->app);
+                       chunk_appendf(msg, " .sc.flg=0x%08x .sc.app=%p .sc.evts=%s",
+                                     fcgi_strm_sc(fstrm)->flags, fcgi_strm_sc(fstrm)->app, tevt_evts2str(fcgi_strm_sc(fstrm)->term_evts_log));
 
                chunk_appendf(msg, " .subs=%p", fstrm->subs);
                if (fstrm->subs) {