shell: set created pipeline pgid

This commit is contained in:
Mark Poliakov 2025-02-13 17:01:36 +02:00
parent de16799908
commit a0cdc39f30
5 changed files with 36 additions and 9 deletions

View File

@ -2,7 +2,7 @@ pub use abi::io::{
TerminalInputOptions, TerminalLineOptions, TerminalOptions, TerminalOutputOptions, TerminalSize, TerminalInputOptions, TerminalLineOptions, TerminalOptions, TerminalOutputOptions, TerminalSize,
}; };
use abi::{error::Error, io::RawFd}; use abi::{error::Error, io::RawFd, process::ProcessGroupId};
use super::device::{self, device_request}; use super::device::{self, device_request};
@ -33,6 +33,11 @@ pub fn set_terminal_size(fd: RawFd, size: &TerminalSize) -> Result<(), Error> {
device_request::<device::SetTerminalSize>(fd, &mut buffer, size) device_request::<device::SetTerminalSize>(fd, &mut buffer, size)
} }
pub fn set_terminal_group(fd: RawFd, group: ProcessGroupId) -> Result<(), Error> {
let mut buffer = [0; 8];
device_request::<device::SetTerminalGroup>(fd, &mut buffer, &group)
}
pub fn is_terminal(fd: RawFd) -> bool { pub fn is_terminal(fd: RawFd) -> bool {
let mut buffer = [0; 0]; let mut buffer = [0; 0];
device_request::<device::IsTerminal>(fd, &mut buffer, &()).is_ok() device_request::<device::IsTerminal>(fd, &mut buffer, &()).is_ok()

1
userspace/Cargo.lock generated
View File

@ -1396,6 +1396,7 @@ dependencies = [
"clap", "clap",
"cross", "cross",
"nom", "nom",
"runtime",
"thiserror", "thiserror",
] ]

View File

@ -11,5 +11,11 @@ thiserror.workspace = true
nom = "7.1.3" nom = "7.1.3"
[target.'cfg(target_os = "yggdrasil")'.dependencies]
runtime.workspace = true
[dev-dependencies]
runtime.workspace = true
[lints] [lints]
workspace = true workspace = true

View File

@ -1,14 +1,22 @@
use std::{ use std::{
fmt, fmt,
fs::File, fs::File,
io::{self, BufRead, BufReader, Stderr, Stdout, Write}, io::{self, stdin, BufRead, BufReader, Stderr, Stdout, Write},
marker::PhantomData, marker::PhantomData,
os::fd::{FromRawFd, IntoRawFd}, os::{
fd::{FromRawFd, IntoRawFd},
yggdrasil::{
io::terminal::set_terminal_group,
process::{create_process_group, CommandExt},
},
},
pipe::{PipeReader, PipeWriter}, pipe::{PipeReader, PipeWriter},
process::{self, Child, ExitCode, ExitStatus, Stdio}, process::{self, Child, ExitCode, ExitStatus, Stdio},
thread::{self, JoinHandle}, thread::{self, JoinHandle},
}; };
use runtime::rt::process::ProcessGroupId;
use crate::{builtin, env::Command, Error}; use crate::{builtin, env::Command, Error};
pub enum Outcome { pub enum Outcome {
@ -150,7 +158,7 @@ impl Outcome {
} }
// TODO move pipelines into process groups // TODO move pipelines into process groups
fn spawn_command(execution: Execution) -> Result<Child, Error> { fn spawn_command(execution: Execution, pgid: ProcessGroupId) -> Result<Child, Error> {
let mut command = process::Command::new(execution.program); let mut command = process::Command::new(execution.program);
command command
@ -159,6 +167,9 @@ fn spawn_command(execution: Execution) -> Result<Child, Error> {
.stdout(execution.stdout) .stdout(execution.stdout)
.stderr(execution.stderr); .stderr(execution.stderr);
#[cfg(any(target_os = "yggdrasil", rust_analyzer))]
command.process_group(pgid);
for (key, value) in execution.envs { for (key, value) in execution.envs {
command.env(key, value); command.env(key, value);
} }
@ -168,10 +179,10 @@ fn spawn_command(execution: Execution) -> Result<Child, Error> {
Ok(child) Ok(child)
} }
pub fn exec_pipeline<I: IntoIterator<Item = Execution>>( pub fn exec_pipeline<I: IntoIterator<Item = Execution>>(pipeline: I) -> Result<Vec<Handle>, Error> {
pipeline: I,
) -> Result<Vec<Handle>, Error> {
let mut handles = vec![]; let mut handles = vec![];
#[cfg(any(target_os = "yggdrasil", rust_analyzer))]
let pgid = create_process_group();
for element in pipeline.into_iter() { for element in pipeline.into_iter() {
let handle = if let Some(builtin) = builtin::get(&element.program) { let handle = if let Some(builtin) = builtin::get(&element.program) {
let io = builtin::Io { let io = builtin::Io {
@ -184,13 +195,17 @@ pub fn exec_pipeline<I: IntoIterator<Item = Execution>>(
builtin(io, element.arguments, element.envs.into()) builtin(io, element.arguments, element.envs.into())
})) }))
} else { } else {
let child = spawn_command(element)?; let child = spawn_command(element, pgid)?;
Handle::Process(child) Handle::Process(child)
}; };
handles.push(handle); handles.push(handle);
} }
#[cfg(any(target_os = "yggdrasil", rust_analyzer))]
unsafe {
set_terminal_group(&stdin(), pgid)?;
}
Ok(handles) Ok(handles)
} }

View File

@ -5,7 +5,7 @@
trait_alias, trait_alias,
exitcode_exit_method exitcode_exit_method
)] )]
#![cfg_attr(target_os = "yggdrasil", feature(yggdrasil_os))] #![cfg_attr(target_os = "yggdrasil", feature(yggdrasil_os, rustc_private))]
#![allow(clippy::new_without_default, clippy::should_implement_trait)] #![allow(clippy::new_without_default, clippy::should_implement_trait)]
use std::{ use std::{