vcl: fix error state switch for vcl_handle_mq_event
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>
diff --git a/src/vcl/vppcom.c b/src/vcl/vppcom.c
index 1791b1b..6bdeb5a 100644
--- a/src/vcl/vppcom.c
+++ b/src/vcl/vppcom.c
@@ -1054,7 +1054,15 @@
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 @@
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;