nodejs / nodejs/node

Background node process corrupts terminal state with tcsetattr() on exit

Open
#35,536 9 comments 6 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

confirmed-bug process
Dominant language
JavaScript
Stars
122k
Forks
37.3k
Avg merge
4d 2h
Merged PRs (30d)
283

Description

  • Version: v14.9.0
  • Platform: NixOS 21.03, Linux 5.8.11 x86_64
  • Subsystem: ResetStdio in src/node.cc

In Bash, run the following:

node -e 'setTimeout(() => {}, 2000)' & sleep 1

This launches node -e 'setTimeout(() => {}, 2000)' in the background and sleep 1 in the foreground. After 1 second, control returns to Bash. After 2 seconds, Node exits and corrupts Bash’s terminal state:

  • the ↑, ↓, →, ← arrow keys start printing ^[[A, ^[[B, ^[[C, ^[[D instead of scrolling through the Bash history or moving the insert point,
  • the Tab key starts moving the cursor 8 spaces forward instead of Tab-completing the command,
  • Ctrl+A and Ctrl+E print ^A and ^E instead of jumping to the beginning and end of the command, etc.

This happens when the ResetStdio handler uses tcsetattr to “restore” the terminal to the state it was in when Node started (#24260). This interferes with Bash, which uses and expects a different terminal state than sleep 1.

(The bug is sometimes reproducible without the sleep 1 depending on whether Node records the initial terminal state before Bash updates it, but the sleep 1 makes it reliable.)

Normally, the terminal state would be protected from such undesired modifications by a background process: the kernel generates SIGTTOU to suspend the process until it’s brought to the foreground. But ResetStdio now deliberately overrides this protection by blocking SIGTTOU (#28535).

IMO, both #24260 and #28535 should be reverted. Node is a programming language; it should never make changes to the terminal state that programs did not request.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/node.cc at the ResetStdio handler and reproduce the issue with the Bash command in the report. Read the context from #24260 and #28535, including the SIGTTOU handling and tcsetattr call. Done means a background Node process exits without changing Bash’s terminal behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, linux, nodejs
Domain
operating-systems
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.