Skip to content

Commit 5589141

Browse files
Fix crash in handling IOBuffer for transform.
1 parent 8d8fcf5 commit 5589141

File tree

2 files changed

+35
-7
lines changed

2 files changed

+35
-7
lines changed

plugin/include/txn_box/Context.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,10 +429,22 @@ class Context
429429
* @param ptr Object to clean up.
430430
* @return @a this
431431
*
432-
* @a ptr is cleaned up by calling
432+
* @a ptr is cleaned up by calling @c delete.
433433
*/
434434
template <typename T> self_type &mark_for_cleanup(T *ptr);
435435

436+
/** Mark @a ptr for cleanup by @a clearner when @a this is destroyed.
437+
*
438+
* @tparam T Type of @a ptr
439+
* @param ptr Object to clean up.
440+
* @param cleaner Functor to clean up @a ptr.
441+
* @return @a this
442+
*
443+
* @a ptr is cleaned up by calling @a cleaner.
444+
*/
445+
template <typename T>
446+
self_type &mark_for_cleanup(T* ptr, void (*cleaner)(T*));
447+
436448
/** Get a reference to the configuration for @a this.
437449
*
438450
* @return The configuration.
@@ -617,6 +629,14 @@ Context::mark_for_cleanup(T *ptr)
617629
return *this;
618630
}
619631

632+
template <typename T>
633+
Context &
634+
Context::mark_for_cleanup(T* ptr, void (*cleaner)(T*))
635+
{
636+
_finalizers.append(_arena->make<Finalizer>(ptr, cleaner));
637+
return *this;
638+
}
639+
620640
template <typename T>
621641
swoc::MemSpan<T>
622642
Context::alloc_span(unsigned int count)

plugin/src/Machinery.cc

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2512,19 +2512,26 @@ const HookMask Do_upstream_rsp_body::HOOKS{MaskFor({Hook::URSP})};
25122512
Errata
25132513
Do_upstream_rsp_body::invoke(Context &ctx)
25142514
{
2515-
// State allocated in transaction memory.
2515+
/// State data for the transform continuation.
2516+
/// @internal Due to ugliness in the plugin API where the final event for the @c Continuation
2517+
/// can arrive after the transaction is destroyed, the @c IOBuffer needs to get cleaned up at
2518+
/// transaction termination, not the final transform event. Therefore the destructor here does
2519+
/// the cleanup, so that it can be marked for cleanup in the @c Context.
25162520
struct State {
25172521
TextView _view; ///< Source view for body.
25182522
TSIOBuffer _tsio_buff = nullptr; ///< Buffer used to write body.
2523+
/// Clean up the @c IOBuffer.
2524+
~State() {
2525+
if (_tsio_buff) {
2526+
TSIOBufferDestroy(_tsio_buff);
2527+
}
2528+
}
25192529
};
25202530

25212531
auto static transform = [](TSCont contp, TSEvent ev_code, void *) -> int {
25222532

2523-
if (TSVConnClosedGet(contp)) { // all done, time to clean up.
2524-
auto state = static_cast<State*>(TSContDataGet(contp));
2525-
if (state && state->_tsio_buff) {
2526-
TSIOBufferDestroy(state->_tsio_buff);
2527-
}
2533+
if (TSVConnClosedGet(contp)) {
2534+
// IOBuffer is cleaned up at transaction close, not here.
25282535
TSContDestroy(contp);
25292536
return 0;
25302537
}
@@ -2587,6 +2594,7 @@ Do_upstream_rsp_body::invoke(Context &ctx)
25872594
// The view contents are in the transaction data, but the view in the feature is not.
25882595
// Put a copy in the transform @a state.
25892596
auto state = ctx.make<State>();
2597+
ctx.mark_for_cleanup(state);
25902598
auto cont = TSTransformCreate(transform, ctx._txn);
25912599
state->_view = *content;
25922600
TSContDataSet(cont, state);

0 commit comments

Comments
 (0)