1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-11 16:42:21 -05:00

fix(runtime): event loop panics in classic workers (#11756)

Classic worker scripts are now executed in the context of a Tokio
runtime. This does mean we can not spawn more tokio runtimes in
"op_worker_sync_fetch". We instead spawn a new thread there, that can
create a new Tokio runtime that we can use to block the worker thread.
This commit is contained in:
Luca Casonato 2021-08-18 15:19:22 +02:00 committed by GitHub
parent 480cfda8d5
commit a66218d457
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 144 additions and 131 deletions

View file

@ -1109,6 +1109,13 @@ itest!(import_file_with_colon {
output: "import_file_with_colon.ts.out",
http_server: true,
});
itest!(classic_workers_event_loop {
args:
"run --enable-testing-features-do-not-use classic_workers_event_loop.js",
output: "classic_workers_event_loop.js.out",
});
// FIXME(bartlomieju): disabled, because this test is very flaky on CI
// itest!(local_sources_not_cached_in_memory {
// args: "run --allow-read --allow-write no_mem_cache.js",

View file

@ -0,0 +1,4 @@
new Worker(
"data:application/javascript,setTimeout(() => {console.log('done'); self.close()}, 1000)",
{ type: "classic" },
);

View file

@ -0,0 +1 @@
done

View file

@ -38,29 +38,31 @@ pub fn op_worker_sync_fetch(
let handle = state.borrow::<WebWorkerInternalHandle>().clone();
assert_eq!(handle.worker_type, WebWorkerType::Classic);
// TODO(andreubotella) Make the runtime into a resource and add a new op to
// block on each request, so a script can run while the next loads.
// TODO(andreubotella) It's not good to throw an exception related to blob
// URLs when none of the script URLs use the blob scheme.
// Also, in which contexts are blob URLs not supported?
let blob_store = state
.try_borrow::<BlobStore>()
.ok_or_else(|| type_error("Blob URLs are not supported in this context."))?
.clone();
// TODO(andreubotella): make the below thread into a resource that can be
// re-used. This would allow parallel fecthing of multiple scripts.
let thread = std::thread::spawn(move || {
let runtime = tokio::runtime::Builder::new_current_thread()
.enable_io()
.enable_time()
.build()
.unwrap();
// TODO(andreubotella) It's not good to throw an exception related to blob
// URLs when none of the script URLs use the blob scheme.
// Also, in which contexts are blob URLs not supported?
let blob_store = state.try_borrow::<BlobStore>().ok_or_else(|| {
type_error("Blob URLs are not supported in this context.")
})?;
let handles: Vec<_> = scripts
.into_iter()
.map(|script| -> JoinHandle<Result<SyncFetchScript, AnyError>> {
let blob_store = blob_store.clone();
runtime.spawn(async move {
let script_url =
Url::parse(&script).map_err(|_| type_error("Invalid script URL"))?;
let script_url = Url::parse(&script)
.map_err(|_| type_error("Invalid script URL"))?;
let (body, mime_type, res_url) = match script_url.scheme() {
"http" | "https" => {
@ -98,9 +100,10 @@ pub fn op_worker_sync_fetch(
(Bytes::from(body), Some(mime_type), script)
}
"blob" => {
let blob = blob_store
.get_object_url(script_url)?
.ok_or_else(|| type_error("Blob for the given URL not found."))?;
let blob =
blob_store.get_object_url(script_url)?.ok_or_else(|| {
type_error("Blob for the given URL not found.")
})?;
let mime_type = mime_type_essence(&blob.media_type);
@ -152,4 +155,7 @@ pub fn op_worker_sync_fetch(
ret.push(script);
}
Ok(ret)
});
thread.join().unwrap()
}

View file

@ -11,7 +11,6 @@ use deno_core::error::AnyError;
use deno_core::error::JsError;
use deno_core::futures::channel::mpsc;
use deno_core::futures::future::poll_fn;
use deno_core::futures::future::FutureExt;
use deno_core::futures::stream::StreamExt;
use deno_core::located_script_name;
use deno_core::serde::Deserialize;
@ -568,15 +567,14 @@ pub fn run_web_worker(
// TODO(bartlomieju): run following block using "select!"
// with terminate
let fut = async move {
// Execute provided source code immediately
let result = if let Some(source_code) = maybe_source_code {
worker.execute_script(&located_script_name!(), &source_code)
} else {
// TODO(bartlomieju): add "type": "classic", ie. ability to load
// script instead of module
let load_future = worker.execute_module(&specifier).boxed_local();
rt.block_on(load_future)
worker.execute_module(&specifier).await
};
let internal_handle = worker.internal_handle.clone();
@ -597,7 +595,10 @@ pub fn run_web_worker(
return Ok(());
}
let result = rt.block_on(worker.run_event_loop(true));
let result = worker.run_event_loop(true).await;
debug!("Worker thread shuts down {}", &name);
result
};
rt.block_on(fut)
}

View file

@ -16744,13 +16744,7 @@
"Cross-origin throw",
"Redirect-to-cross-origin syntax error",
"Redirect-to-Cross-origin throw"
],
"report-error-cross-origin.sub.any.worker.html": false,
"report-error-redirect-to-cross-origin.sub.any.worker.html": false,
"report-error-same-origin.sub.any.worker.html": false,
"report-error-setTimeout-cross-origin.sub.any.worker.html": false,
"report-error-setTimeout-redirect-to-cross-origin.sub.any.worker.html": false,
"report-error-setTimeout-same-origin.sub.any.worker.html": false
]
}
}
},