github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/build/node-run.sh (about)

     1  #!/usr/bin/env bash
     2  
     3  # node-run.sh runs a command installed by NPM/Yarn. It looks for COMMAND in
     4  # ./node_modules/bin, where NPM/Yarn install commands by default, then invokes
     5  # it with the specified ARGS, if any.
     6  #
     7  # The reason for this script's existence is somewhat arcane. NodeJS strongly
     8  # prefers non-blocking I/O, so if it detects that stdout or stderr is a Unix
     9  # pipe, it will enable non-blocking I/O on that file descriptor [0]. The
    10  # non-blocking I/O mode applies to every process that has a reference to that
    11  # open file description [1]. Normally, this is not a problem: if stdout or
    12  # stderr is a pipe, it is typically a single-purpose pipe created by a shell
    13  # pipeline that is not shared with any other processes. In Docker, however, the
    14  # stdout and stderr streams are named FIFOs, which look like anonymous pipes but
    15  # are shared by all processes launched by the same shell. Launching a NodeJS
    16  # process in Docker will thus make stdout and stderr non-blocking for all other
    17  # processes invoked by the same shell.
    18  #
    19  # In CI, because we run NodeJS and `go test` in the same Docker shell, `go test`
    20  # will intermittently drop output on the floor when a write fails with EAGAIN.
    21  # `go-test-teamcity` interprets this missing output as an indication that the
    22  # test panicked. Note that dropping output is reasonable behavior from `go
    23  # test`--most programs simply cannot and should not handle non-blocking stdio
    24  # streams [2]--and is arguably a bug in NodeJS [3].
    25  #
    26  # As a workaround, this script pipes NodeJS's stdout and stderr through `cat`,
    27  # which prevents the actual stdout and stderr streams from being infected with
    28  # non-blocking I/O.
    29  #
    30  # TODO(benesch): see if we can propagate isatty from the true stdout and stderr
    31  # so that colors, etc. are supported.
    32  
    33  # [0]: https://nodejs.org/docs/latest-v8.x/api/process.html#process_a_note_on_process_i_o
    34  # [1]: See `man 2 open` for details on the difference between a file
    35  #      descriptor, an open file description, and a file.
    36  # [2]: https://jdebp.eu/FGA/dont-set-shared-file-descriptors-to-non-blocking-mode.html
    37  # [3]: https://github.com/nodejs/node/issues/14752
    38  
    39  set -euo pipefail
    40  
    41  [[ "${1-}" ]] || { echo "usage: $0 [-C CWD] COMMAND [ARGS...]" >&2; exit 1; }
    42  
    43  while getopts "C:" opt; do
    44    case $opt in
    45       C) cd "$OPTARG" ;;
    46      \?) exit 1;
    47    esac
    48  done
    49  shift $((OPTIND-1))
    50  
    51  "$@" > >(cat) 2> >(cat >&2)