Skip to content

Commit 5b2b5d5

Browse files
committed
Fix runtime handle access in V8 blocking threads
Capture tokio runtime handle before entering spawn_blocking context in both StatelessService and StatefulService. This prevents EOF errors that occur when trying to access Handle::current() from within blocking threads where the runtime context is not available. The runtime handle is now passed as a parameter to execute_stateless() and execute_stateful() functions, ensuring async resource operations can be bridged correctly from V8 callbacks.
1 parent c2da397 commit 5b2b5d5

File tree

1 file changed

+6
-6
lines changed

1 file changed

+6
-6
lines changed

server/src/mcp.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -246,11 +246,10 @@ fn create_context_with_resources<'s>(
246246
}
247247

248248
// Execute JS in a stateless isolate (no snapshot creation)
249-
fn execute_stateless(code: String, resource_storage: Arc<dyn ResourceStorage>) -> Result<String, String> {
249+
fn execute_stateless(code: String, resource_storage: Arc<dyn ResourceStorage>, runtime_handle: tokio::runtime::Handle) -> Result<String, String> {
250250
let isolate = &mut v8::Isolate::new(Default::default());
251251

252252
// Set up isolate data for resource callbacks
253-
let runtime_handle = tokio::runtime::Handle::current();
254253
let isolate_data = Arc::new(IsolateData {
255254
runtime_handle,
256255
resource_storage,
@@ -269,7 +268,7 @@ fn execute_stateless(code: String, resource_storage: Arc<dyn ResourceStorage>) -
269268
}
270269

271270
// Execute JS with snapshot support (preserves heap state)
272-
fn execute_stateful(code: String, snapshot: Option<Vec<u8>>, resource_storage: Arc<dyn ResourceStorage>) -> Result<(String, Vec<u8>), String> {
271+
fn execute_stateful(code: String, snapshot: Option<Vec<u8>>, resource_storage: Arc<dyn ResourceStorage>, runtime_handle: tokio::runtime::Handle) -> Result<(String, Vec<u8>), String> {
273272
let mut snapshot_creator = match snapshot {
274273
Some(snapshot) => {
275274
eprintln!("creating isolate from snapshot...");
@@ -282,7 +281,6 @@ fn execute_stateful(code: String, snapshot: Option<Vec<u8>>, resource_storage: A
282281
};
283282

284283
// Set up isolate data for resource callbacks
285-
let runtime_handle = tokio::runtime::Handle::current();
286284
let isolate_data = Arc::new(IsolateData {
287285
runtime_handle,
288286
resource_storage,
@@ -405,7 +403,8 @@ impl StatelessService {
405403
#[tool(description = include_str!("run_js_tool_stateless.md"))]
406404
pub async fn run_js(&self, #[tool(param)] code: String) -> RunJsStatelessResponse {
407405
let resource_storage = self.resource_storage.clone();
408-
let v8_result = tokio::task::spawn_blocking(move || execute_stateless(code, resource_storage)).await;
406+
let runtime_handle = tokio::runtime::Handle::current();
407+
let v8_result = tokio::task::spawn_blocking(move || execute_stateless(code, resource_storage, runtime_handle)).await;
409408

410409
match v8_result {
411410
Ok(Ok(output)) => RunJsStatelessResponse { output },
@@ -431,7 +430,8 @@ impl StatefulService {
431430
pub async fn run_js(&self, #[tool(param)] code: String, #[tool(param)] heap: String) -> RunJsStatefulResponse {
432431
let snapshot = self.heap_storage.get(&heap).await.ok();
433432
let resource_storage = self.resource_storage.clone();
434-
let v8_result = tokio::task::spawn_blocking(move || execute_stateful(code, snapshot, resource_storage)).await;
433+
let runtime_handle = tokio::runtime::Handle::current();
434+
let v8_result = tokio::task::spawn_blocking(move || execute_stateful(code, snapshot, resource_storage, runtime_handle)).await;
435435

436436
match v8_result {
437437
Ok(Ok((output, startup_data))) => {

0 commit comments

Comments
 (0)