From 27725504b04e0e74450795298286a1c7c83e774f Mon Sep 17 00:00:00 2001 From: mlevkov Date: Sat, 1 Aug 2026 19:31:30 -0700 Subject: [PATCH] fix(connectors): hand off SDK worker during blocking send callbacks The send callback runs synchronously inside the SDK's polling task, on a tokio runtime shared by every connector instance loaded from the same plugin library. A callback that blocks for backpressure pins one worker for the duration, and with enough saturated instances iggy_source_close for a sibling waits behind them, since the close blocks on the sibling's polling task getting scheduled to observe its shutdown signal. Wrap the callback in tokio::task::block_in_place so the worker is handed off before the callback runs. The SDK runtime is multi-threaded, which block_in_place requires. No FFI or ABI change; plugins pick this up when rebuilt against the updated SDK. Fixes #3796. Co-authored-by: Claude --- core/connectors/sdk/src/source.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/core/connectors/sdk/src/source.rs b/core/connectors/sdk/src/source.rs index 713e00c6ae..e26301f0ac 100644 --- a/core/connectors/sdk/src/source.rs +++ b/core/connectors/sdk/src/source.rs @@ -196,7 +196,15 @@ async fn handle_messages( } }; - callback(plugin_id, messages.as_ptr(), messages.len()); + // The callback can block for backpressure (the runtime parks + // it while its bounded forwarding channel is full), and this + // task runs on the runtime shared by every instance loaded + // from this library. Hand the worker off so a saturated + // instance cannot pin it and stall a sibling's close, which + // waits on this task exiting. + tokio::task::block_in_place(|| { + callback(plugin_id, messages.as_ptr(), messages.len()); + }); } } }