Fix scripts that terminate instantly hanging forever

This commit is contained in:
Filip Tibell 2023-01-24 20:30:47 -05:00
parent 530d01fc9d
commit 915dbf7bd9
No known key found for this signature in database
4 changed files with 41 additions and 49 deletions

View file

@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
### Fixed
- Fixed scripts that terminate instantly sometimes hanging
## `0.1.1` - January 24th, 2023
### Fixed

View file

@ -1,12 +1,8 @@
use std::{
env,
process::{Command, Stdio},
sync::Weak,
};
use std::{env, process::Stdio, sync::Weak};
use mlua::prelude::*;
use os_str_bytes::RawOsString;
use smol::{channel::Sender, unblock};
use smol::{channel::Sender, process::Command};
use crate::{utils::table::TableBuilder, LuneMessage};
@ -120,24 +116,19 @@ async fn process_spawn(
lua: &Lua,
(program, args): (String, Option<Vec<String>>),
) -> LuaResult<LuaTable> {
// Create and spawn a **blocking** child process to prevent
// issues with yielding across the metamethod/c-call boundary
// Create and spawn our child process
let pwd = env::current_dir()?;
let output = unblock(move || {
let mut cmd = Command::new(program);
if let Some(args) = args {
cmd.args(args);
}
let child = cmd
.current_dir(pwd)
.stdin(Stdio::null())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()?;
child.wait_with_output()
})
.await
.map_err(LuaError::external)?;
let mut cmd = Command::new(program);
if let Some(args) = args {
cmd.args(args);
}
let output = cmd
.current_dir(pwd)
.stdin(Stdio::null())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.output()
.await?;
// NOTE: If an exit code was not given by the child process,
// we default to 1 if it yielded any error output, otherwise 0
let code = output

View file

@ -1,6 +1,6 @@
use std::{collections::HashSet, process::ExitCode, sync::Arc};
use anyhow::{anyhow, bail, Result};
use anyhow::{bail, Result};
use mlua::prelude::*;
use smol::LocalExecutor;
@ -12,9 +12,6 @@ use crate::{
utils::formatting::pretty_format_luau_error,
};
#[cfg(not(test))]
use crate::utils::formatting::format_label;
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum LuneGlobal {
Console,
@ -43,7 +40,6 @@ pub(crate) enum LuneMessage {
Exit(u8),
Spawned,
Finished,
Error(anyhow::Error),
LuaError(mlua::Error),
}
@ -97,28 +93,21 @@ impl Lune {
}
}
// Spawn the main thread from our entrypoint script
let script_lua = lua.clone();
let script_name = name.to_string();
let script_chunk = chunk.to_string();
sender.send(LuneMessage::Spawned).await?;
exec.spawn(async move {
sender.send(LuneMessage::Spawned).await?;
let result = lua
let result = script_lua
.load(&script_chunk)
.set_name(&format!("={}", script_name))
.unwrap()
.call_async::<_, LuaMultiValue>(LuaMultiValue::new())
.eval_async::<LuaValue>()
.await;
let message = match result {
Ok(_) => LuneMessage::Finished,
#[cfg(test)]
Err(e) => LuneMessage::Error(anyhow!("{}", pretty_format_luau_error(&e))),
#[cfg(not(test))]
Err(e) => LuneMessage::Error(anyhow!(
"\n{}\n{}",
format_label("ERROR"),
pretty_format_luau_error(&e)
)),
};
sender.send(message).await
match result {
Err(e) => sender.send(LuneMessage::LuaError(e)).await,
Ok(_) => sender.send(LuneMessage::Finished).await,
}
})
.detach();
// Run the executor until there are no tasks left,
@ -153,11 +142,6 @@ impl Lune {
}
LuneMessage::Spawned => task_count += 1,
LuneMessage::Finished => task_count -= 1,
LuneMessage::Error(e) => {
eprintln!("{}", e);
got_error = true;
task_count += 1;
}
LuneMessage::LuaError(e) => {
eprintln!("{}", pretty_format_luau_error(&e));
got_error = true;
@ -166,6 +150,7 @@ impl Lune {
};
// If there are no tasks left running, it is now
// safe to close the receiver and end execution
println!("{}", task_count);
if task_count == 0 {
receiver.close();
}

View file

@ -1,4 +1,4 @@
use std::fmt::Debug;
use std::fmt::{self, Debug};
use std::sync::Weak;
use mlua::prelude::*;
@ -14,6 +14,16 @@ pub enum TaskRunMode {
Deferred,
}
impl fmt::Display for TaskRunMode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Blocking => write!(f, "Blocking"),
Self::Instant => write!(f, "Instant"),
Self::Deferred => write!(f, "Deferred"),
}
}
}
pub async fn run_registered_task<T>(
lua: &Lua,
mode: TaskRunMode,