Skip to content
This repository was archived by the owner on Apr 24, 2025. It is now read-only.

Commit dff2a62

Browse files
authored
Do not call callbacks for deleted contexts. (#270)
Signed-off-by: Takeshi Yoneda <[email protected]>
1 parent 0dc1df1 commit dff2a62

File tree

2 files changed

+50
-26
lines changed

2 files changed

+50
-26
lines changed

proxywasm/internal/abi_callback_l7.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,18 @@ func proxyOnHttpCallResponse(pluginContextID, calloutID uint32, numHeaders, body
9191
panic("invalid callout id")
9292
}
9393

94-
ProxySetEffectiveContext(cb.callerContextID)
95-
currentState.setActiveContextID(cb.callerContextID)
94+
ctxID := cb.callerContextID
95+
currentState.setActiveContextID(ctxID)
9696
delete(root.httpCallbacks, calloutID)
97-
cb.callback(numHeaders, bodySize, numTrailers)
97+
98+
// Check if the context is already deleted.
99+
// For example, if the connection expired before the call response arrival,
100+
// proxy_on_http_call_response is called AFTER ProxyOnDelete is called for the context id.
101+
// In that case, if the callback continues response or make local reply, then the subsequent
102+
// callbacks (for example OnHttpResponseHeaders) would follow and result in calling callback
103+
// for already-deleted context id. See https://github.com/tetratelabs/proxy-wasm-go-sdk/issues/261 for detail.
104+
if _, ok := currentState.contextIDToRootID[ctxID]; ok {
105+
ProxySetEffectiveContext(ctxID)
106+
cb.callback(numHeaders, bodySize, numTrailers)
107+
}
98108
}

proxywasm/internal/abi_callback_l7_test.go

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -96,33 +96,47 @@ func Test_proxyOnHttpCallResponse(t *testing.T) {
9696

9797
var (
9898
pluginContextID uint32 = 1
99+
callerContextID uint32 = 100
99100
callOutID uint32 = 10
100101
)
101102

102103
currentStateMux.Lock()
103104
defer currentStateMux.Unlock()
104105

105-
ctx := &l7Context{}
106-
currentState = &state{
107-
pluginContexts: map[uint32]*pluginContextState{pluginContextID: {
108-
httpCallbacks: map[uint32]*httpCallbackAttribute{callOutID: {callback: ctx.OnHttpCallResponse}},
109-
}},
110-
}
111-
112-
proxyOnHttpCallResponse(pluginContextID, callOutID, 0, 0, 0)
113-
_, ok := currentState.pluginContexts[pluginContextID].httpCallbacks[callOutID]
114-
require.False(t, ok)
115-
require.True(t, ctx.onHttpCallResponse)
116-
117-
ctx = &l7Context{}
118-
currentState = &state{
119-
pluginContexts: map[uint32]*pluginContextState{pluginContextID: {
120-
httpCallbacks: map[uint32]*httpCallbackAttribute{callOutID: {callback: ctx.OnHttpCallResponse}},
121-
}},
122-
}
123-
124-
proxyOnHttpCallResponse(pluginContextID, callOutID, 0, 0, 0)
125-
_, ok = currentState.pluginContexts[pluginContextID].httpCallbacks[callOutID]
126-
require.False(t, ok)
127-
require.True(t, ctx.onHttpCallResponse)
106+
t.Run("normal", func(t *testing.T) {
107+
ctx := &l7Context{}
108+
currentState = &state{
109+
pluginContexts: map[uint32]*pluginContextState{pluginContextID: {
110+
httpCallbacks: map[uint32]*httpCallbackAttribute{callOutID: {callback: ctx.OnHttpCallResponse, callerContextID: callerContextID}},
111+
}},
112+
contextIDToRootID: map[uint32]uint32{callerContextID: pluginContextID},
113+
}
114+
115+
proxyOnHttpCallResponse(pluginContextID, callOutID, 0, 0, 0)
116+
_, ok := currentState.pluginContexts[pluginContextID].httpCallbacks[callOutID]
117+
require.False(t, ok)
118+
require.True(t, ctx.onHttpCallResponse)
119+
})
120+
121+
t.Run("delete before callback", func(t *testing.T) {
122+
ctx := &l7Context{}
123+
currentState = &state{
124+
pluginContexts: map[uint32]*pluginContextState{pluginContextID: {
125+
httpCallbacks: map[uint32]*httpCallbackAttribute{callOutID: {callback: ctx.OnHttpCallResponse, callerContextID: callerContextID}},
126+
}},
127+
httpContexts: map[uint32]types.HttpContext{callerContextID: nil},
128+
contextIDToRootID: map[uint32]uint32{callerContextID: pluginContextID},
129+
}
130+
131+
proxyOnDelete(callerContextID)
132+
133+
proxyOnHttpCallResponse(pluginContextID, callOutID, 0, 0, 0)
134+
_, ok := currentState.pluginContexts[pluginContextID].httpCallbacks[callOutID]
135+
require.False(t, ok)
136+
137+
// If the caller context is deleted before callback is called, then
138+
// the callback shouldn't be called.
139+
require.False(t, ctx.onHttpCallResponse)
140+
})
141+
128142
}

0 commit comments

Comments
 (0)