Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose as_command API on CommandBuilder #4767

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

mehulkar
Copy link

@mehulkar mehulkar commented Jan 9, 2024

I am interested in using portable_pty to spawn tasks so that the pty can pipe stdin from the parent. I want access to the a std lib version of this command so I can get it to play nicely with other crates (like command-group and tokio).

@wez
Copy link
Owner

wez commented Jan 9, 2024

What's your goal here? In case it isn't clear, the object this returns is not connected to a PTY. This method is an implementation detail that is used by internal logic that is used to setup a child process.

What do you gain from exposing it outside the crate compared to using std::process::Command directly?

@mehulkar
Copy link
Author

mehulkar commented Jan 9, 2024

I'm still at experimental phase, but I'm essentially wanting to use our existing implementation to set a process group. Currently that looks something like this:

let command = tokio::process::Command::new();
let std_cmd = command.as_std();
let child = std_cmd.group.spawn()

The .group() implementation is just CommandGroupBuilder::new(std_cmd), so I was hoping to do this:

let pty_system = portable_pty::NativePtySystem::default();
let pair = pty_system.openpty(PtySize::default()).unwrap();
let cmd = portable_pty::CommandBuilder::new();
let group = CommandGroupBuilder::new(cmd.as_command()); // ← new API from this PR
group.spawn();

After typing this up and understanding your reply I see how this won't work, since:

the object this returns is not connected to a PTY

Maybe what needs to happen instead is some kind of option to spawn_command() that can set the group instead? (and then I can remove command-group?

@wez
Copy link
Owner

wez commented Jan 10, 2024

Can you expand on the group thing a bit more?
What are you trying to do?
The default behavior for a new pty is tied up with the use of the setsid(2) system call that happens here:

wezterm/pty/src/unix.rs

Lines 255 to 258 in 1c09019

// Establish ourselves as a session leader.
if libc::setsid() == -1 {
return Err(io::Error::last_os_error());
}

@mehulkar
Copy link
Author

In turborepo, we spawn child processes for a bunch of scripts (provided by the user) in parallel. We use a process group so we can kill all these process (i.e. forward signals).

I want to keep this behavior. Is establishing as a session leader necessary for this pty? Is it possible to spawn a child process with a connected pty that can be part of a process group set from the outside?

@wez
Copy link
Owner

wez commented Jan 11, 2024

Perhaps what you want is to add a unix specific set_process_group method to CommandBuilder that stores an optional process group id in the builder, then, in the code I pointed to, do something like:

// process_group is pre-extracted from the builder in the same was as controlling_tty
if let Some(pgrp) = process_group {
   if libc::setpgrp(pgrp) == -1 {
      return Err(io::Error::last_os_error());
   }
} else {
  if libc::setsid() == -1 {
      return Err(io::Error::last_os_error());
   }
}

@wez wez marked this pull request as draft January 21, 2024 20:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants