Skip to content

STDIN of child process is skipping some characters from user input #13978

@BrandonDR

Description

@BrandonDR

What version of Bun is running?

1.1.27

What platform is your computer?

Linux 6.5.0-44-generic x86_64 x86_64

What steps can reproduce the bug?

After I prompt the user for a confirmation e.g. "Do you wish to continue? [y/N]", I then spawn a SSH process which inherits the stdio.

To reproduce run the following JS
(You need to update the ssh command below to one that you have available, any command that echos user input back should also work.)

import { spawnSync } from 'child_process';

function confirmPrompt(message) {
  return new Promise((resolve) => {
    process.stdin.resume();
    process.stdin.setEncoding('utf8');
    process.stdout.write(`${message} [y/N] `);
    const onData = (data) => {
      const answer = data.trim().toLowerCase();
      process.stdin.removeListener('data', onData);
      process.stdin.pause();
      resolve(answer === 'y');
    };
    process.stdin.on('data', onData);
  });
}

async function main () {
  // If you comment out this prompt the issue doesnt happen
  if (!(await confirmPrompt('Do you wish to continue?'))) {
    process.exit(0);
  }

  const command = ['ssh', 'my-server'];

  spawnSync(command[0], command.slice(1), { stdio: 'inherit', shell: true });
  process.exit(0);
};
main();

I have tried a few variations and found Node has a similar issue but using spawnSync as in the example above worked in Node but not Bun. I have not found a way to make this work in Bun.
Other combinations I tried has this issue in both Node and Bun, but only with child_process.spawnSync in Node works.
Regardless of using spawn/spawnSync imported from bun or child_process resulted in the missing input issue.

What is the expected behavior?

child ssh process should allow me to type words without missing approximately every second character.

What do you see instead?

When I type exit, I only get ext and have to hit <enter> twice for it to register. The missing characters are not consistent but unusable. Commenting out my confirmPrompt, the ssh session works as expected not missing any input.

Additional information

Also tested script with node version:
v20.12.2

I also tried a version of the `confirmPrompt` function using `readline.createInterface` - same issue.
export async function confirmPrompt(message) {
    const rl = readline.createInterface({
        input: process.stdin,
        output: process.stdout
    });

    return new Promise(resolve => {
        rl.question(`${message} [y/N] `, (answer) => {
            rl.close();
            resolve(answer.toLowerCase() === 'y');
        });
    });
}

This resulted in the same missing input issue from Bun.

Perhaps I am missing something on how stdin/stdout or the encoding works. Do I need to reset stdio before spawning a child process?

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions