Fix process.spawn yielding issue

This commit is contained in:
Filip Tibell 2023-01-23 13:18:48 -05:00
parent 5839a7b021
commit c2ee188ad5
No known key found for this signature in database
2 changed files with 33 additions and 15 deletions

View file

@ -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/), 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). 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 ## `0.0.5` - January 22nd, 2023
### Added ### Added

View file

@ -1,11 +1,12 @@
use std::{ use std::{
env, env,
process::{exit, Stdio}, process::{exit, Stdio},
sync::Weak,
}; };
use mlua::prelude::*; use mlua::prelude::*;
use os_str_bytes::RawOsString; use os_str_bytes::RawOsString;
use smol::process::Command; use smol::{process::Command, LocalExecutor};
use crate::utils::table_builder::TableBuilder; use crate::utils::table_builder::TableBuilder;
@ -116,20 +117,30 @@ async fn process_spawn(
lua: &Lua, lua: &Lua,
(program, args): (String, Option<Vec<String>>), (program, args): (String, Option<Vec<String>>),
) -> LuaResult<LuaTable> { ) -> LuaResult<LuaTable> {
// Create and spawn a child process, and let exec = lua
// wait for it to terminate with output .app_data_ref::<Weak<LocalExecutor>>()
let mut cmd = Command::new(program); .unwrap()
if let Some(args) = args { .upgrade()
cmd.args(args); .unwrap();
} // Create and spawn a child process in a new task to prevent
let child = cmd // issues with yielding across the metamethod/c-call boundary
.current_dir(env::current_dir().map_err(LuaError::external)?) let output = exec
.stdin(Stdio::null()) .spawn(async move {
.stdout(Stdio::piped()) let mut cmd = Command::new(program);
.stderr(Stdio::piped()) if let Some(args) = args {
.spawn() cmd.args(args);
.map_err(LuaError::external)?; }
let output = child.output().await.map_err(LuaError::external)?; 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, // NOTE: If an exit code was not given by the child process,
// we default to 1 if it yielded any error output, otherwise 0 // we default to 1 if it yielded any error output, otherwise 0
let code = output let code = output