Skip to content

Commit

Permalink
Test pipes.
Browse files Browse the repository at this point in the history
  • Loading branch information
milesj committed Dec 1, 2023
1 parent 364051f commit 3ba6211
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 28 deletions.
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/cli-shim/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ path = "src/main.rs"
[dependencies]
ctrlc = "3.4.1"
shared_child = "1.0.0"
sigpipe = "0.1.3"
16 changes: 8 additions & 8 deletions crates/cli-shim/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Results

| | `args[0]` | `args_os[0]` | `current_exe` | Ctrl+C |
| ------------------------- | --------- | ------------ | ------------- | ------ |
| Unix non-link: `node` | `node` | `node` | `node` | Yes |
| Unix soft-link: `node` | `node` | `node` | `node` | Yes |
| Unix hard-link: `node` | `node` | `node` | `node` | Yes |
| Windows no-link: `node` | `node` | `node` | `node` | Yes |
| Windows soft-link: `node` | N/A | N/A | N/A | N/A |
| Windows hard-link: `node` | `node` | `node` | `node` | Yes |
| | `args[0]` | `current_exe` | Ctrl+C | Piped data |
| ------------------------- | --------- | ------------- | ------ | ---------- |
| Unix non-link: `node` | `node` | `node` | Yes | Yes |
| Unix soft-link: `node` | `node` | `node` | Yes | Yes |
| Unix hard-link: `node` | `node` | `node` | Yes | Yes |
| Windows no-link: `node` | `node` | `node` | Yes | |
| Windows soft-link: `node` | N/A | N/A | N/A | N/A |
| Windows hard-link: `node` | `node` | `node` | Yes | |
67 changes: 49 additions & 18 deletions crates/cli-shim/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,40 +1,71 @@
use shared_child::SharedChild;
use std::process::Command;
use std::collections::VecDeque;
use std::io::{IsTerminal, Read, Write};
use std::process::{Command, Stdio};
use std::sync::Arc;
use std::{env, process};
use std::{env, io, process};

pub fn main() {
dbg!("Args", env::args().collect::<Vec<_>>());
dbg!("Args OS", env::args_os().collect::<Vec<_>>());
sigpipe::reset();

// Extract arguments to pass-through
let mut args = env::args().collect::<VecDeque<_>>();
let shim_name = args.pop_front().unwrap();

dbg!("Args", &args);
dbg!("Shim name", shim_name);
dbg!("Exec with", env::current_exe().unwrap());

let mut command = Command::new("node");
command.arg("-e");
command.arg(
r#"
console.log('start');
// Capture any piped input
let input = {
let mut stdin = io::stdin();
let mut buffer = String::new();

// Only read piped data when stdin is not a TTY,
// otherwise the process will hang indefinitely waiting for EOF
if !stdin.is_terminal() {
stdin.read_to_string(&mut buffer).unwrap();
}

process.on('SIGINT', function() {
console.log('killed');
process.exit(1);
});
buffer
};
let has_piped_stdin = !input.is_empty();

setTimeout(() => { console.log('stop'); }, 5000);"#,
);
dbg!("Input", &input);

// The actual command to execute
let mut command = Command::new("node");
command.arg("./docs/shim-test.mjs");
command.args(args);

if has_piped_stdin {
command.stdin(Stdio::piped());
}

// Spawn a shareable child process
let shared_child = SharedChild::spawn(&mut command).unwrap();
let child = Arc::new(shared_child);
let child_clone = Arc::clone(&child);

// Handle CTRL+C and kill the child
ctrlc::set_handler(move || {
println!("Ctrl-C!");
child_clone.kill().unwrap();
})
.unwrap();

// If we have piped data, pass it through
if has_piped_stdin {
if let Some(mut stdin) = child.take_stdin() {
stdin.write_all(input.as_bytes()).unwrap();
drop(stdin);
}
}

// Wait for the process to finish or be killed
let status = child.wait().unwrap();
let code = status.code().unwrap_or(0);

println!("Status = {}", status);
println!("status code = {}", code);

process::exit(status.code().unwrap_or(0))
process::exit(code);
}
39 changes: 39 additions & 0 deletions docs/shim-test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
console.log("start");

// Test CTRL+C handling
process.on("SIGINT", () => {
console.log("killed");
process.exit(1);
});

// Test piping input
async function getStdinBuffer() {
if (process.stdin.isTTY) {
return Buffer.alloc(0);
}

const result = [];
let length = 0;

for await (const chunk of process.stdin) {
result.push(chunk);
length += chunk.length;
}

return Buffer.concat(result, length);
}

getStdinBuffer().then((buffer) => {
let data = buffer.toString("utf8");

if (data) {
console.log("piped data =", data.trim());
}
});

// Start a timer so we can ensure "stop" is never logged
setTimeout(() => {
console.log("stop");
}, 5000);

console.log("running");
4 changes: 2 additions & 2 deletions justfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
set shell := ["pwsh.exe", "-c"]
# set shell := ["pwsh.exe", "-c"]

init:
cargo install cargo-binstall
Expand Down Expand Up @@ -40,4 +40,4 @@ setup-shims-win:
New-Item -ItemType Directory -Force -ErrorAction SilentlyContinue shims
New-Item -ItemType HardLink -Force -Name "shims\node-hard.exe" -Value "target\debug\proto-shim.exe"
New-Item -ItemType SymbolicLink -Force -Name "shims\node-soft.exe" -Value "target\debug\proto-shim.exe"
Copy-Item "target\debug\proto-shim.exe" -Destination "shims\node.exe"
Copy-Item "target\debug\proto-shim.exe" -Destination "shims\node.exe"

0 comments on commit 3ba6211

Please sign in to comment.