Improve panic safety and queue performance

This commit is contained in:
Filip Tibell 2024-02-06 15:19:54 +01:00
parent 5eddd99422
commit 63ecbf7b61
No known key found for this signature in database
2 changed files with 38 additions and 16 deletions

View file

@ -46,6 +46,7 @@ impl ThreadQueue {
Ok(id) Ok(id)
} }
#[inline]
pub fn drain_items<'outer, 'lua>( pub fn drain_items<'outer, 'lua>(
&'outer self, &'outer self,
lua: &'lua Lua, lua: &'lua Lua,
@ -56,11 +57,17 @@ impl ThreadQueue {
self.queue.try_iter().map(|stored| stored.into_inner(lua)) self.queue.try_iter().map(|stored| stored.into_inner(lua))
} }
#[inline]
pub async fn wait_for_item(&self) { pub async fn wait_for_item(&self) {
if self.queue.is_empty() { if self.queue.is_empty() {
self.event.listen().await; self.event.listen().await;
} }
} }
#[inline]
pub fn is_empty(&self) -> bool {
self.queue.is_empty()
}
} }
/** /**

View file

@ -5,6 +5,7 @@ use std::{
process::ExitCode, process::ExitCode,
rc::{Rc, Weak as WeakRc}, rc::{Rc, Weak as WeakRc},
sync::{Arc, Weak as WeakArc}, sync::{Arc, Weak as WeakArc},
thread::panicking,
}; };
use futures_lite::prelude::*; use futures_lite::prelude::*;
@ -417,7 +418,10 @@ impl<'lua> Runtime<'lua> {
// Empty executor = we didn't spawn any new Lua tasks // Empty executor = we didn't spawn any new Lua tasks
// above, and there are no remaining tasks to run later // above, and there are no remaining tasks to run later
if local_exec.is_empty() { if local_exec.is_empty()
&& self.queue_spawn.is_empty()
&& self.queue_defer.is_empty()
{
break; break;
} }
} }
@ -445,6 +449,16 @@ impl<'lua> Runtime<'lua> {
impl Drop for Runtime<'_> { impl Drop for Runtime<'_> {
fn drop(&mut self) { fn drop(&mut self) {
if panicking() {
// Do not cause further panics if already panicking, as
// this may abort the program instead of safely unwinding
self.lua.remove_app_data::<SpawnedThreadQueue>();
self.lua.remove_app_data::<DeferredThreadQueue>();
self.lua.remove_app_data::<ThreadErrorCallback>();
self.lua.remove_app_data::<ThreadResultMap>();
self.lua.remove_app_data::<Exit>();
} else {
// In any other case we panic if metadata was removed incorrectly
self.lua self.lua
.remove_app_data::<SpawnedThreadQueue>() .remove_app_data::<SpawnedThreadQueue>()
.expect(ERR_METADATA_REMOVED); .expect(ERR_METADATA_REMOVED);
@ -462,3 +476,4 @@ impl Drop for Runtime<'_> {
.expect(ERR_METADATA_REMOVED); .expect(ERR_METADATA_REMOVED);
} }
} }
}