]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: connection: make it possible for data->wake to return an error
authorWilly Tarreau <w@1wt.eu>
Wed, 3 Oct 2012 19:12:16 +0000 (21:12 +0200)
committerWilly Tarreau <w@1wt.eu>
Thu, 4 Oct 2012 20:26:10 +0000 (22:26 +0200)
Just like ->init(), ->wake() may now be used to return an error and
abort the connection. Currently this is not used but will be with
embryonic sessions.

include/types/connection.h
src/connection.c
src/stream_interface.c

index 44fdb0d6c851da8156da2b26c7438f32b139b961..3219309dbb88808ad54c2393e45705de22228dd9 100644 (file)
@@ -180,12 +180,13 @@ struct xprt_ops {
  * at the transport layer, which can be a connection opening/close, or any
  * data movement. The <init> callback may be called by the connection handler
  * at the end of a transport handshake, when it is about to transfer data and
- * the data layer is not ready yet.
+ * the data layer is not ready yet. Both <wake> and <init> may abort a connection
+ * by returning < 0.
  */
 struct data_cb {
        void (*recv)(struct connection *conn);  /* data-layer recv callback */
        void (*send)(struct connection *conn);  /* data-layer send callback */
-       void (*wake)(struct connection *conn);  /* data-layer callback to report activity */
+       int  (*wake)(struct connection *conn);  /* data-layer callback to report activity */
        int  (*init)(struct connection *conn);  /* data-layer initialization */
 };
 
index 949e9ccd3e7bb9037b8eee273de8995d56d25c1e..e156366f2b924a6b495d0b7aae6eb6fc102516c3 100644 (file)
@@ -123,8 +123,14 @@ int conn_fd_handler(int fd)
                return 0;
        }
 
-       if ((conn->flags & CO_FL_WAKE_DATA) && ((conn->flags ^ flags) & CO_FL_CONN_STATE))
-               conn->data->wake(conn);
+       /* The wake callback may be used to process a critical error and abort the
+        * connection. If so, we don't want to go further as the connection will
+        * have been released and the FD destroyed.
+        */
+       if ((conn->flags & CO_FL_WAKE_DATA) &&
+           ((conn->flags ^ flags) & CO_FL_CONN_STATE) &&
+           conn->data->wake(conn) < 0)
+               return 0;
 
        /* Last check, verify if the connection just established */
        if (unlikely(!(conn->flags & (CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN | CO_FL_CONNECTED))))
index 83e085920cd6f92e3205894b8093da99a2fa08d2..8bc5bbbb253cb82e7d6d5e0ec58c71ab2c863fdb 100644 (file)
@@ -46,7 +46,7 @@ static void stream_int_chk_rcv_conn(struct stream_interface *si);
 static void stream_int_chk_snd_conn(struct stream_interface *si);
 static void si_conn_recv_cb(struct connection *conn);
 static void si_conn_send_cb(struct connection *conn);
-static void si_conn_wake_cb(struct connection *conn);
+static int si_conn_wake_cb(struct connection *conn);
 
 /* stream-interface operations for embedded tasks */
 struct si_ops si_embedded_ops = {
@@ -561,9 +561,9 @@ int conn_si_send_proxy(struct connection *conn, unsigned int flag)
  * the update function in that it is designed to be called by lower layers after I/O
  * events have been completed. It will also try to wake the associated task up if
  * an important event requires special handling. It relies on the connection handler
- * to commit any polling updates.
+ * to commit any polling updates. The function always returns 0.
  */
-static void si_conn_wake_cb(struct connection *conn)
+static int si_conn_wake_cb(struct connection *conn)
 {
        struct stream_interface *si = conn->owner;
 
@@ -659,6 +659,7 @@ static void si_conn_wake_cb(struct connection *conn)
        }
        if (si->ib->flags & CF_READ_ACTIVITY)
                si->ib->flags &= ~CF_READ_DONTWAIT;
+       return 0;
 }
 
 /*