This is an automated email from the ASF dual-hosted git repository.

bneradt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new bbc6c12010 TransformTerminus::do_io_*: handle null buffer (#11859)
bbc6c12010 is described below

commit bbc6c1201094bc670c33dab79fc4e22f998d05f9
Author: Brian Neradt <[email protected]>
AuthorDate: Fri Dec 13 14:01:52 2024 -0600

    TransformTerminus::do_io_*: handle null buffer (#11859)
    
    This is a very similar change as #11789. With this patch,
    TransformTerminus properly supports a 0 byte read to cancel VIO. Without
    this patch, the logic naively scheduled an event which called the
    handler which would crash on what was often a canceled continuation or
    otherwise invalid continuation.
---
 include/proxy/TransformInternal.h |  7 +++
 src/proxy/Transform.cc            | 95 ++++++++++++++++++++++++++++-----------
 2 files changed, 76 insertions(+), 26 deletions(-)

diff --git a/include/proxy/TransformInternal.h 
b/include/proxy/TransformInternal.h
index 1aba6df1ad..78817073cb 100644
--- a/include/proxy/TransformInternal.h
+++ b/include/proxy/TransformInternal.h
@@ -31,6 +31,7 @@ class TransformTerminus : public VConnection
 {
 public:
   TransformTerminus(TransformVConnection *tvc);
+  ~TransformTerminus() override;
 
   int handle_event(int event, void *edata);
 
@@ -49,6 +50,12 @@ public:
   int                   m_deletable;
   int                   m_closed;
   int                   m_called_user;
+
+private:
+  Event *_read_event     = nullptr;
+  bool   _read_disabled  = true;
+  Event *_write_event    = nullptr;
+  bool   _write_disabled = true;
 };
 
 class TransformVConnection : public TransformVCChain
diff --git a/src/proxy/Transform.cc b/src/proxy/Transform.cc
index a19517135f..fd74f7e606 100644
--- a/src/proxy/Transform.cc
+++ b/src/proxy/Transform.cc
@@ -132,6 +132,18 @@ TransformTerminus::TransformTerminus(TransformVConnection 
*tvc)
   SET_HANDLER(&TransformTerminus::handle_event);
 }
 
+TransformTerminus::~TransformTerminus()
+{
+  if (_read_event != nullptr) {
+    _read_event->cancel();
+    _read_event = nullptr;
+  }
+  if (_write_event != nullptr) {
+    _write_event->cancel();
+    _write_event = nullptr;
+  }
+}
+
 #define RETRY()                                             \
   if (ink_atomic_increment((int *)&m_event_count, 1) < 0) { \
     ink_assert(!"not reached");                             \
@@ -140,8 +152,15 @@ TransformTerminus::TransformTerminus(TransformVConnection 
*tvc)
   return 0;
 
 int
-TransformTerminus::handle_event(int event, void * /* edata ATS_UNUSED */)
+TransformTerminus::handle_event(int event, void *edata)
 {
+  Event *event_p = reinterpret_cast<Event *>(edata);
+  if (event_p == _read_event) {
+    _read_event = nullptr;
+  } else if (event_p == _write_event) {
+    _write_event = nullptr;
+  }
+
   int val;
 
   m_deletable = ((m_closed != 0) && (m_tvc->m_closed != 0));
@@ -212,12 +231,14 @@ TransformTerminus::handle_event(int event, void * /* 
edata ATS_UNUSED */)
         }
       }
 
-      if (m_write_vio.ntodo() > 0) {
-        if (towrite > 0) {
-          m_write_vio.cont->handleEvent(VC_EVENT_WRITE_READY, &m_write_vio);
+      if (!_write_disabled) {
+        if (m_write_vio.ntodo() > 0) {
+          if (towrite > 0) {
+            m_write_vio.cont->handleEvent(VC_EVENT_WRITE_READY, &m_write_vio);
+          }
+        } else {
+          m_write_vio.cont->handleEvent(VC_EVENT_WRITE_COMPLETE, &m_write_vio);
         }
-      } else {
-        m_write_vio.cont->handleEvent(VC_EVENT_WRITE_COMPLETE, &m_write_vio);
       }
 
       // We could have closed on the write callback
@@ -225,14 +246,16 @@ TransformTerminus::handle_event(int event, void * /* 
edata ATS_UNUSED */)
         return 0;
       }
 
-      if (m_read_vio.ntodo() > 0) {
-        if (m_write_vio.ntodo() <= 0) {
-          m_read_vio.cont->handleEvent(VC_EVENT_EOS, &m_read_vio);
-        } else if (towrite > 0) {
-          m_read_vio.cont->handleEvent(VC_EVENT_READ_READY, &m_read_vio);
+      if (!_read_disabled) {
+        if (m_read_vio.ntodo() > 0) {
+          if (m_write_vio.ntodo() <= 0) {
+            m_read_vio.cont->handleEvent(VC_EVENT_EOS, &m_read_vio);
+          } else if (towrite > 0) {
+            m_read_vio.cont->handleEvent(VC_EVENT_READ_READY, &m_read_vio);
+          }
+        } else {
+          m_read_vio.cont->handleEvent(VC_EVENT_READ_COMPLETE, &m_read_vio);
         }
-      } else {
-        m_read_vio.cont->handleEvent(VC_EVENT_READ_COMPLETE, &m_read_vio);
       }
     }
   } else {
@@ -256,7 +279,7 @@ TransformTerminus::handle_event(int event, void * /* edata 
ATS_UNUSED */)
         if (!m_called_user) {
           m_called_user = 1;
           m_tvc->m_cont->handleEvent(ev, &m_read_vio);
-        } else {
+        } else if (!_read_disabled) {
           ink_assert(m_read_vio.cont != nullptr);
           m_read_vio.cont->handleEvent(ev, &m_read_vio);
         }
@@ -275,19 +298,29 @@ TransformTerminus::handle_event(int event, void * /* 
edata ATS_UNUSED */)
 VIO *
 TransformTerminus::do_io_read(Continuation *c, int64_t nbytes, MIOBuffer *buf)
 {
-  m_read_vio.set_writer(buf);
   m_read_vio.op = VIO::READ;
   m_read_vio.set_continuation(c);
   m_read_vio.nbytes    = nbytes;
   m_read_vio.ndone     = 0;
   m_read_vio.vc_server = this;
 
-  if (ink_atomic_increment(&m_event_count, 1) < 0) {
-    ink_assert(!"not reached");
-  }
-  Dbg(dbg_ctl_transform, "[TransformTerminus::do_io_read] event_count %d", 
m_event_count);
+  if (buf != nullptr) {
+    _read_disabled = false;
+    m_read_vio.set_writer(buf);
+    if (ink_atomic_increment(&m_event_count, 1) < 0) {
+      ink_assert(!"not reached");
+    }
+    Dbg(dbg_ctl_transform, "[TransformTerminus::do_io_read] event_count %d", 
m_event_count);
 
-  this_ethread()->schedule_imm_local(this);
+    _read_event = this_ethread()->schedule_imm_local(this);
+  } else {
+    _read_disabled = true;
+    if (_read_event != nullptr) {
+      _read_event->cancel();
+      _read_event = nullptr;
+    }
+    m_read_vio.buffer.clear();
+  }
 
   return &m_read_vio;
 }
@@ -300,19 +333,29 @@ TransformTerminus::do_io_write(Continuation *c, int64_t 
nbytes, IOBufferReader *
 {
   // In the process of eliminating 'owner' mode so asserting against it
   ink_assert(!owner);
-  m_write_vio.set_reader(buf);
   m_write_vio.op = VIO::WRITE;
   m_write_vio.set_continuation(c);
   m_write_vio.nbytes    = nbytes;
   m_write_vio.ndone     = 0;
   m_write_vio.vc_server = this;
 
-  if (ink_atomic_increment(&m_event_count, 1) < 0) {
-    ink_assert(!"not reached");
-  }
-  Dbg(dbg_ctl_transform, "[TransformTerminus::do_io_write] event_count %d", 
m_event_count);
+  if (buf != nullptr) {
+    _write_disabled = false;
+    m_write_vio.set_reader(buf);
+    if (ink_atomic_increment(&m_event_count, 1) < 0) {
+      ink_assert(!"not reached");
+    }
+    Dbg(dbg_ctl_transform, "[TransformTerminus::do_io_write] event_count %d", 
m_event_count);
 
-  this_ethread()->schedule_imm_local(this);
+    _write_event = this_ethread()->schedule_imm_local(this);
+  } else {
+    _write_disabled = true;
+    if (_write_event != nullptr) {
+      _write_event->cancel();
+      _write_event = nullptr;
+    }
+    m_write_vio.buffer.clear();
+  }
 
   return &m_write_vio;
 }

Reply via email to