From bd872b4a778d36c3f1fdd8dd123673c84b68fe36 Mon Sep 17 00:00:00 2001 From: Ivan Trubach Date: Mon, 29 Jul 2024 11:30:40 +0300 Subject: [PATCH] stdenv: fix unbound NIX_LOG_FD in `nix develop` When running `nix develop` for a package, Nix records the stdenv environment with NIX_LOG_FD set. That is, when the actual development shell runs, it uses the functions that attempt to log to NIX_LOG_FD, but this variable is not actually set. As a workaround, check whether NIX_LOG_FD is set at runtime. Example (before this change): ```console $ nix develop --file . bash $ echo "${NIX_LOG_FD-unset}" unset $ runPhase unpackPhase bash: "$NIX_LOG_FD": Bad file descriptor Running phase: unpackPhase unpacking source archive /nix/store/v28dv6l0qk3j382kp40bksa1v6h7dx9p-bash-5.2.tar.gz bash: "$NIX_LOG_FD": Bad file descriptor source root is bash-5.2 bash: "$NIX_LOG_FD": Bad file descriptor setting SOURCE_DATE_EPOCH to timestamp 1663942708 of file bash-5.2/y.tab.h ``` After this change: ```console $ nix develop --file . bash $ runPhase unpackPhase Running phase: unpackPhase unpacking source archive /nix/store/v28dv6l0qk3j382kp40bksa1v6h7dx9p-bash-5.2.tar.gz source root is bash-5.2 setting SOURCE_DATE_EPOCH to timestamp 1663942708 of file bash-5.2/y.tab.h ``` --- pkgs/stdenv/generic/setup.sh | 102 +++++++++++++++++------------------ 1 file changed, 48 insertions(+), 54 deletions(-) diff --git a/pkgs/stdenv/generic/setup.sh b/pkgs/stdenv/generic/setup.sh index 40bf6554183c6..c1de5b97d2d6a 100644 --- a/pkgs/stdenv/generic/setup.sh +++ b/pkgs/stdenv/generic/setup.sh @@ -47,63 +47,57 @@ getAllOutputNames() { fi } -if [[ -n "${NIX_LOG_FD:-}" ]]; then - # Logs arguments to $NIX_LOG_FD, if it exists, no-op if it does not. - nixLog() { - echo "$@" >&"$NIX_LOG_FD" - } +# Logs arguments to $NIX_LOG_FD, if it exists, no-op if it does not. +nixLog() { + if [[ -z ${NIX_LOG_FD-} ]]; then + return + fi + echo "$@" >&"$NIX_LOG_FD" +} - # Log a hook, to be run before the hook is actually called. - # logging for "implicit" hooks -- the ones specified directly - # in derivation's arguments -- is done in _callImplicitHook instead. - _logHook() { - local hookKind="$1" - local hookExpr="$2" - shift 2 - - if declare -F "$hookExpr" > /dev/null 2>&1; then - nixLog "calling '$hookKind' function hook '$hookExpr'" "$@" - elif type -p "$hookExpr" > /dev/null; then - nixLog "sourcing '$hookKind' script hook '$hookExpr'" - elif [[ "$hookExpr" != "_callImplicitHook"* ]]; then - # Here we have a string hook to eval. - # Join lines onto one with literal \n characters unless NIX_DEBUG >= 2. - local exprToOutput - if (( "${NIX_DEBUG:-0}" >= 2 )); then - exprToOutput="$hookExpr" - else - # We have `r'\n'.join([line.lstrip() for lines in text.split('\n')])` at home. - local hookExprLine - while IFS= read -r hookExprLine; do - # These lines often have indentation, - # so let's remove leading whitespace. - hookExprLine="${hookExprLine#"${hookExprLine%%[![:space:]]*}"}" - # If this line wasn't entirely whitespace, - # then add it to our output - if [[ -n "$hookExprLine" ]]; then - exprToOutput+="$hookExprLine\\n " - fi - done <<< "$hookExpr" +# Log a hook, to be run before the hook is actually called. +# logging for "implicit" hooks -- the ones specified directly +# in derivation's arguments -- is done in _callImplicitHook instead. +_logHook() { + # Fast path in case nixLog is no-op. + if [[ -z ${NIX_LOG_FD-} ]]; then + return + fi - # And then remove the final, unnecessary, \n - exprToOutput="${exprToOutput%%\\n }" - fi - nixLog "evaling '$hookKind' string hook '$exprToOutput'" - fi - } -else - nixLog() { - # Stub. - # Note: because bash syntax, this colon is load bearing. Removing it - # will turn this function into a syntax error. - : - } + local hookKind="$1" + local hookExpr="$2" + shift 2 - _logHook() { - # Load-bearing colon; same as above. - : - } -fi + if declare -F "$hookExpr" > /dev/null 2>&1; then + nixLog "calling '$hookKind' function hook '$hookExpr'" "$@" + elif type -p "$hookExpr" > /dev/null; then + nixLog "sourcing '$hookKind' script hook '$hookExpr'" + elif [[ "$hookExpr" != "_callImplicitHook"* ]]; then + # Here we have a string hook to eval. + # Join lines onto one with literal \n characters unless NIX_DEBUG >= 2. + local exprToOutput + if (( "${NIX_DEBUG:-0}" >= 2 )); then + exprToOutput="$hookExpr" + else + # We have `r'\n'.join([line.lstrip() for lines in text.split('\n')])` at home. + local hookExprLine + while IFS= read -r hookExprLine; do + # These lines often have indentation, + # so let's remove leading whitespace. + hookExprLine="${hookExprLine#"${hookExprLine%%[![:space:]]*}"}" + # If this line wasn't entirely whitespace, + # then add it to our output + if [[ -n "$hookExprLine" ]]; then + exprToOutput+="$hookExprLine\\n " + fi + done <<< "$hookExpr" + + # And then remove the final, unnecessary, \n + exprToOutput="${exprToOutput%%\\n }" + fi + nixLog "evaling '$hookKind' string hook '$exprToOutput'" + fi +} ###################################################################### # Hook handling.