diff --git a/CHANGELOG.md b/CHANGELOG.md index 89b2b53..0657944 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ 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 + +- Potential fix for spawned processes that yield erroring + with "attempt to yield across metamethod/c-call boundary" + ## `0.0.5` - January 22nd, 2023 ### Added diff --git a/src/lib/globals/process.rs b/src/lib/globals/process.rs index bff727c..0b06e01 100644 --- a/src/lib/globals/process.rs +++ b/src/lib/globals/process.rs @@ -1,11 +1,12 @@ use std::{ env, process::{exit, Stdio}, + sync::Weak, }; use mlua::prelude::*; use os_str_bytes::RawOsString; -use smol::process::Command; +use smol::{process::Command, LocalExecutor}; use crate::utils::table_builder::TableBuilder; @@ -116,20 +117,30 @@ async fn process_spawn( lua: &Lua, (program, args): (String, Option>), ) -> LuaResult { - // Create and spawn a child process, and - // wait for it to terminate with output - let mut cmd = Command::new(program); - if let Some(args) = args { - cmd.args(args); - } - let child = cmd - .current_dir(env::current_dir().map_err(LuaError::external)?) - .stdin(Stdio::null()) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .spawn() - .map_err(LuaError::external)?; - let output = child.output().await.map_err(LuaError::external)?; + let exec = lua + .app_data_ref::>() + .unwrap() + .upgrade() + .unwrap(); + // Create and spawn a child process in a new task to prevent + // issues with yielding across the metamethod/c-call boundary + let output = exec + .spawn(async move { + let mut cmd = Command::new(program); + if let Some(args) = args { + cmd.args(args); + } + let child = cmd + .current_dir(env::current_dir().map_err(LuaError::external)?) + .stdin(Stdio::null()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .map_err(LuaError::external)?; + let output = child.output().await.map_err(LuaError::external)?; + Ok::<_, LuaError>(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