vcl: fix error state switch for vcl_handle_mq_event 44/39344/4
authorwanghanlin <wanghanlin@corp.netease.com>
Tue, 8 Aug 2023 02:40:04 +0000 (10:40 +0800)
committerFlorin Coras <florin.coras@gmail.com>
Tue, 15 Aug 2023 18:06:10 +0000 (18:06 +0000)
When a listen session receives an ACCEPTED message, but then
receives either a RESET or DISCONNECTED message from VPP before the
session is accepted, the listen session state is switched to
VPP_CLOSING or DISCONNECT.
The subsequent CLEANUP message handler attempts to send a
disconneted or reset reply message to VPP, but since the vpp_evt_q
for the listen session is null, this leads to a crash.

Type: fix
Change-Id: Ic51f78f631fe8d15bf8c56b795f4a900c3e2f724
Signed-off-by: wanghanlin <wanghanlin@corp.netease.com>
src/vcl/vppcom.c

index 1791b1b..6bdeb5a 100644 (file)
@@ -1054,7 +1054,15 @@ vcl_handle_mq_event (vcl_worker_t * wrk, session_event_t * e)
        break;
       if (s->session_state == VCL_STATE_CLOSED)
        break;
-      if (vcl_session_has_attr (s, VCL_SESS_ATTR_NONBLOCK))
+      /* We do not postpone for blocking sessions or listen sessions because:
+       * 1. Blocking sessions are not part of epoll instead they're used in a
+       *    synchronous manner, such as read/write and etc.
+       * 2. Listen sessions that have not yet been accepted can't change to
+       *    VPP_CLOSING state instead can been marked as ACCEPTED_F_CLOSED.
+       */
+      if (vcl_session_has_attr (s, VCL_SESS_ATTR_NONBLOCK) &&
+         !(s->session_state == VCL_STATE_LISTEN ||
+           s->session_state == VCL_STATE_LISTEN_NO_MQ))
        {
          s->session_state = VCL_STATE_VPP_CLOSING;
          s->flags |= VCL_SESSION_F_PENDING_DISCONNECT;
@@ -1075,7 +1083,15 @@ vcl_handle_mq_event (vcl_worker_t * wrk, session_event_t * e)
        break;
       if (s->session_state == VCL_STATE_CLOSED)
        break;
-      if (vcl_session_has_attr (s, VCL_SESS_ATTR_NONBLOCK))
+      /* We do not postpone for blocking sessions or listen sessions because:
+       * 1. Blocking sessions are not part of epoll instead they're used in a
+       *    synchronous manner, such as read/write and etc.
+       * 2. Listen sessions that have not yet been accepted can't change to
+       *    DISCONNECT state instead can been marked as ACCEPTED_F_RESET.
+       */
+      if (vcl_session_has_attr (s, VCL_SESS_ATTR_NONBLOCK) &&
+         !(s->session_state == VCL_STATE_LISTEN ||
+           s->session_state == VCL_STATE_LISTEN_NO_MQ))
        {
          s->flags |= VCL_SESSION_F_PENDING_DISCONNECT;
          s->session_state = VCL_STATE_DISCONNECT;