Node: tty.isatty(1) and process.stdout.isTTY in worker_threads worker return different values

Created on 22 Jun 2019  ·  12Comments  ·  Source: nodejs/node

  • Version: 12.4.0
  • Platform: Darwin C02WJ0U4HTDG 17.7.0 Darwin Kernel Version 17.7.0: Wed Apr 24 21:17:24 PDT 2019; root:xnu-4570.71.45~1/RELEASE_X86_64 x86_64
  • Subsystem: tty

I found out recently that in a worker which is run with worker_threads, tty.isatty(1) returns True whereas process.stdout.isTTY returns False.

This led to a weird issue in mocha - a popular library for testing: https://github.com/mochajs/mocha/pull/3955

tty worker

Most helpful comment

You're welcome to open a documentation pull request but where would you add it? There are tens if not hundreds of core methods that accept a file descriptor. It'd be incongruent to single out tty.isatty().

Its behavior also isn't the least bit surprising to me but maybe that's just me.

All 12 comments

Thanks for the link, interesting. But it doesn't say anything about tty.isatty API, does it?

@1999 This still seems like expected behaviour – fd’s are per-process, so fd 1 is going to be a TTY in one thread if it is a TTY for any thread. The problem is that in Workers, process.stdout does not refer to fd 1.

@addaleax I didn't know that tty.isatty(fd) is talking about the whole process. Maybe it's worth it to add a note about it do the documentation?

You're welcome to open a documentation pull request but where would you add it? There are tens if not hundreds of core methods that accept a file descriptor. It'd be incongruent to single out tty.isatty().

Its behavior also isn't the least bit surprising to me but maybe that's just me.

For me as a Node.JS developer, it's not clear if I should use tty.isatty(fd) or process.stdout.isTTY - they look the same from the documentation and also the documentation doesn't explicitly say that one is about the process even when we create a thread within this process and another is talking about a thread.

I’m having the same issue as Ben here – I don’t see a good place in the documentation that isn’t “everywhere”…

For me as a Node.JS developer, it's not clear if I should use tty.isatty(fd) or process.stdout.isTTY

We could document that tty.isatty(fd) should be used when dealing with a file descriptor, and process.stdout.isTTY when dealing with process.stdout, but that seems somewhat redundant? But that’s kind of the answer to the question of which function to use…

i think the question is more like (@1999 correct me if i'm wrong) when should someone be dealing with fd 1 vs when should someone be dealing with process.stdout.

Exactly.

I would think of the fd-handling functions as low-level primitives that are there for when you really need them, but generally dealing with the corresponding JS objects makes more sense when available (e.g. 99 % of the time using fs.createReadStream() makes more sense then manually reading data using fs.read()).

In the case of isatty(), I think the use cases are very limited. I could see somebody using it for detecting TTY-ness for non-stdio fd’s (e.g. for native openpty() or tcgetattr()/tcsetattr() wrappers), or maybe when the goal is to intentionally test the per-process state, including when process.stdout has been overridden or when you’re in a Worker. But here too, I think 99 % of the time you’d want to use the convenience JS objects.

Is that helpful? Is that something that we could or should document in some way?

it's also worth noting that accessing process.std{out, in, err} can change their modes and that node will start processing data (which may or may not be a good thing depending on your use case)

Related to this, we may want to properly publicly (think, docs) expose process.stdout.fd?

Was this page helpful?
0 / 5 - 0 ratings