]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: stream-int: return the allocated appctx in stream_int_register_handler()
authorWilly Tarreau <w@1wt.eu>
Sun, 1 Dec 2013 08:35:41 +0000 (09:35 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 9 Dec 2013 14:40:23 +0000 (15:40 +0100)
The task returned by stream_int_register_handler() is never used, however we
always need to access the appctx afterwards. So make it return the appctx
instead. We already plan for it to fail, which is the reason for the addition
of a few tests and the possibility for the HTTP analyser to return a status
code 500.

include/proto/stream_interface.h
src/dumpstats.c
src/peers.c
src/proto_http.c
src/stream_interface.c

index 41a29adda8c60d5f692205e2fd7d7d24e97989d0..4c4a6a864bd23bdd79e0b524baabd4d49250d527 100644 (file)
@@ -42,8 +42,7 @@ extern struct si_ops si_embedded_ops;
 extern struct si_ops si_conn_ops;
 extern struct data_cb si_conn_cb;
 
-struct task *stream_int_register_handler(struct stream_interface *si,
-                                        struct si_applet *app);
+struct appctx *stream_int_register_handler(struct stream_interface *si, struct si_applet *app);
 void stream_int_unregister_handler(struct stream_interface *si);
 
 /* initializes a stream interface in the SI_ST_INI state. It's detached from
index cb5b25623e5fc6689b3153c53d3b83aafcf20044..1b6fe3d343a4d9ca3ccc56af964675a23bddc88b 100644 (file)
@@ -159,8 +159,9 @@ static int stats_accept(struct session *s)
        struct appctx *appctx;
 
        s->target = &cli_applet.obj_type;
-       stream_int_register_handler(&s->si[1], objt_applet(s->target));
-       appctx = si_appctx(&s->si[1]);
+       appctx = stream_int_register_handler(&s->si[1], objt_applet(s->target));
+       if (!appctx)
+               return -1;
        appctx->st1 = 0;
        appctx->st0 = STAT_CLI_INIT;
 
index c1d85f2b8b3c1a4e122be38fa6ab1fba0391f950..e56bdfcb53ed466fe305d33a4c4126a728394a30 100644 (file)
@@ -1097,8 +1097,9 @@ int peer_accept(struct session *s)
        struct appctx *appctx;
 
        s->target = &peer_applet.obj_type;
-       stream_int_register_handler(&s->si[1], objt_applet(s->target));
-       appctx = si_appctx(&s->si[1]);
+       appctx = stream_int_register_handler(&s->si[1], objt_applet(s->target));
+       if (!appctx)
+               return -1;
        appctx->st0 = PEER_SESSION_ACCEPT;
        appctx->ctx.peers.ptr = s;
 
@@ -1175,8 +1176,9 @@ static struct session *peer_session_create(struct peer *peer, struct peer_sessio
        if (s->fe->options2 & PR_O2_INDEPSTR)
                s->si[0].flags |= SI_FL_INDEP_STR;
 
-       stream_int_register_handler(&s->si[0], &peer_applet);
-       appctx = si_appctx(&s->si[0]);
+       appctx = stream_int_register_handler(&s->si[0], &peer_applet);
+       if (!appctx)
+               goto out_fail_conn1;
        appctx->st0 = PEER_SESSION_CONNECT;
        appctx->ctx.peers.ptr = (void *)ps;
 
index 1c5ae3d6663346291d13b1898ef1b8c9a3a736e5..a06b0ec8ec9455f1c0c7d1a7fef0f97031b79cb4 100644 (file)
@@ -3461,8 +3461,15 @@ int http_process_req_common(struct session *s, struct channel *req, int an_bit,
        if (!http_req_last_rule) {
                if (stats_check_uri(s->rep->prod, txn, px)) {
                        s->target = &http_stats_applet.obj_type;
-                       stream_int_register_handler(s->rep->prod, objt_applet(s->target));
+                       if (unlikely(!stream_int_register_handler(s->rep->prod, objt_applet(s->target)))) {
+                               txn->status = 500;
+                               s->logs.tv_request = now;
+                               stream_int_retnclose(req->prod, http_error_message(s, HTTP_ERR_500));
 
+                               if (!(s->flags & SN_ERR_MASK))
+                                       s->flags |= SN_ERR_RESOURCE;
+                               goto return_prx_cond;
+                       }
                        /* parse the whole stats request and extract the relevant information */
                        http_handle_stats(s, req);
                        http_req_last_rule = http_req_get_intercept_rule(px, &px->uri_auth->http_req_rules, s, txn);
index 1c13d42ced3b706324903a724e39f782bbb8fedf..397076005b3327cbe948c38040c258db87b8f13c 100644 (file)
@@ -342,21 +342,21 @@ static void stream_int_chk_snd(struct stream_interface *si)
                task_wakeup(si->owner, TASK_WOKEN_IO);
 }
 
-/* Register an applet to handle a stream_interface as part of the stream
- * interface's owner task, which is returned. The SI will wake it up everytime
- * it is solicited. The task's processing function must call the applet's
- * function before returning. It must be deleted by the task handler using
- * stream_int_unregister_handler(), possibly from within the function itself.
- * It also pre-initializes applet.state to zero and the connection context
- * to NULL.
+/* Register an applet to handle a stream_interface as part of the
+ * stream interface's owner task. The SI will wake it up everytime it
+ * is solicited.  The task's processing function must call the applet's
+ * function before returning. It must be deleted by the task handler
+ * using stream_int_unregister_handler(), possibly from within the
+ * function itself. It also pre-initializes the applet's context and
+ * returns it (or NULL in case it could not be allocated).
  */
-struct task *stream_int_register_handler(struct stream_interface *si, struct si_applet *app)
+struct appctx *stream_int_register_handler(struct stream_interface *si, struct si_applet *app)
 {
        DPRINTF(stderr, "registering handler %p for si %p (was %p)\n", app, si, si->owner);
 
        si_attach_applet(si, app);
        si->flags |= SI_FL_WAIT_DATA;
-       return si->owner;
+       return si_appctx(si);
 }
 
 /* Unregister a stream interface handler. This must be called by the handler task