Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

osx_cc_wrapper: add workaround to get_realpath for some bash versions #20212

Conversation

boltzmannrain
Copy link

It looks like in some bash versions under some conditions with set -e bash may propagate sub-shell errors to parent shell, but it shouldn't as set -E is the setting about sub-shell error propagation.

This manifests itself as get_realpath returning empty string.

Let's add explicit || true to $(readlink ...) sub-shell. The loop uses empty string as stop signal and should keep working for both affected and unaffected bash versions.

EXTRA INFO

Adding set -x to debug it reveals that next is being set to empty string but after that echo "$previous" isn't called. Which in turn calls install_name_tool with missing argument and fails the build.

Example of the log
https://hydra.nixos.org/build/240805256/nixlog/1
it uses bazel-6.4.0 to run cpp tests from bazelbuild/examples in x86_64-darwin host.

Example of local run with set -x

++ get_otool_path bazel-out/darwin-fastbuild/bin/_solib_darwin/libexamples_Scpp_Slibhello-lib.dylib
++ get_realpath bazel-out/darwin-fastbuild/bin/_solib_darwin/libexamples_Scpp_Slibhello-lib.dylib
++ local previous=bazel-out/darwin-fastbuild/bin/_solib_darwin/libexamples_Scpp_Slibhello-lib.dylib
++ sed 's|^.*/bazel-out/|bazel-out/|'
+++ readlink bazel-out/darwin-fastbuild/bin/_solib_darwin/libexamples_Scpp_Slibhello-lib.dylib
++ local next=/private/tmp/nix-build-bazel-6.4.0.drv-1/_bazel__nixbld1/ff905cebe41cc2b7000dbd8f60c2df58/execroot/io_bazel/bazel-out/darwin-fastbuild/bin/_solib_darwin/libexamples_Scpp_Slibhello-lib.dylib
++ '[' -n /private/tmp/nix-build-bazel-6.4.0.drv-1/_bazel__nixbld1/ff905cebe41cc2b7000dbd8f60c2df58/execroot/io_bazel/bazel-out/darwin-fastbuild/bin/_solib_darwin/libexamples_Scpp_Slibhello-lib.dylib ']'
++ previous=/private/tmp/nix-build-bazel-6.4.0.drv-1/_bazel__nixbld1/ff905cebe41cc2b7000dbd8f60c2df58/execroot/io_bazel/bazel-out/darwin-fastbuild/bin/_solib_darwin/libexamples_Scpp_Slibhello-lib.dylib
+++ readlink /private/tmp/nix-build-bazel-6.4.0.drv-1/_bazel__nixbld1/ff905cebe41cc2b7000dbd8f60c2df58/execroot/io_bazel/bazel-out/darwin-fastbuild/bin/_solib_darwin/libexamples_Scpp_Slibhello-lib.dylib
++ next=/private/tmp/nix-build-bazel-6.4.0.drv-1/_bazel__nixbld1/ff905cebe41cc2b7000dbd8f60c2df58/execroot/io_bazel/bazel-out/darwin-fastbuild/bin/examples/cpp/libhello-lib.dylib
++ '[' -n /private/tmp/nix-build-bazel-6.4.0.drv-1/_bazel__nixbld1/ff905cebe41cc2b7000dbd8f60c2df58/execroot/io_bazel/bazel-out/darwin-fastbuild/bin/examples/cpp/libhello-lib.dylib ']'
++ previous=/private/tmp/nix-build-bazel-6.4.0.drv-1/_bazel__nixbld1/ff905cebe41cc2b7000dbd8f60c2df58/execroot/io_bazel/bazel-out/darwin-fastbuild/bin/examples/cpp/libhello-lib.dylib
+++ readlink /private/tmp/nix-build-bazel-6.4.0.drv-1/_bazel__nixbld1/ff905cebe41cc2b7000dbd8f60c2df58/execroot/io_bazel/bazel-out/darwin-fastbuild/bin/examples/cpp/libhello-lib.dylib
++ next=
+ /nix/store/hfwdjfb4203x8rl4s6q565016hi3m0d3-cctools-llvm-11.1.0-973.0.1/bin/install_name_tool -change @loader_path/../../_solib_darwin//libexamples_Scpp_Slibhello-lib.dylib bazel-out/darwin-fastbuild/bin/examples/cpp/hello-success_test

note that @loader_path... should've been the 2nd argument to -change

Local host bash version is

% bash -version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin21)
Copyright (C) 2007 Free Software Foundation, Inc.

Though notably aarch64 host with

% bash -version
GNU bash, version 3.2.57(1)-release (arm64-apple-darwin22)
Copyright (C) 2007 Free Software Foundation, Inc.

doesn't hit the issue, so it may be sensitive to some other things too.

Bash changelogs do have mentions of bugs around set -e https://github.com/bminor/bash/blob/master/CHANGES though I haven't identified the exact version and bug entry.

Copy link

google-cla bot commented Nov 15, 2023

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

It looks like in some bash versions under some conditions
with `set -e` bash may propagate sub-shell errors to parent shell,
but it shouldn't as `set -E` is the setting about sub-shell error propagation.

This manifests itself as `get_realpath` returning empty string.

Let's add explicit `|| true` to `$(readlink ...)` sub-shell. The loop
uses empty string as stop signal and should keep working for both
affected and unaffected bash versions.

EXTRA INFO

Adding `set -x` to debug it reveals that `next` is being set to empty
string but after that `echo "$previous"` isn't called. Which in turn
calls `install_name_tool` with missing argument and fails the build.

Example of the log
https://hydra.nixos.org/build/240805256/nixlog/1
it uses `bazel-6.4.0` to run cpp tests from `bazelbuild/examples`
in `x86_64-darwin` host.

Example of local run with `set -x`
```
++ get_otool_path bazel-out/darwin-fastbuild/bin/_solib_darwin/libexamples_Scpp_Slibhello-lib.dylib
++ get_realpath bazel-out/darwin-fastbuild/bin/_solib_darwin/libexamples_Scpp_Slibhello-lib.dylib
++ local previous=bazel-out/darwin-fastbuild/bin/_solib_darwin/libexamples_Scpp_Slibhello-lib.dylib
++ sed 's|^.*/bazel-out/|bazel-out/|'
+++ readlink bazel-out/darwin-fastbuild/bin/_solib_darwin/libexamples_Scpp_Slibhello-lib.dylib
++ local next=/private/tmp/nix-build-bazel-6.4.0.drv-1/_bazel__nixbld1/ff905cebe41cc2b7000dbd8f60c2df58/execroot/io_bazel/bazel-out/darwin-fastbuild/bin/_solib_darwin/libexamples_Scpp_Slibhello-lib.dylib
++ '[' -n /private/tmp/nix-build-bazel-6.4.0.drv-1/_bazel__nixbld1/ff905cebe41cc2b7000dbd8f60c2df58/execroot/io_bazel/bazel-out/darwin-fastbuild/bin/_solib_darwin/libexamples_Scpp_Slibhello-lib.dylib ']'
++ previous=/private/tmp/nix-build-bazel-6.4.0.drv-1/_bazel__nixbld1/ff905cebe41cc2b7000dbd8f60c2df58/execroot/io_bazel/bazel-out/darwin-fastbuild/bin/_solib_darwin/libexamples_Scpp_Slibhello-lib.dylib
+++ readlink /private/tmp/nix-build-bazel-6.4.0.drv-1/_bazel__nixbld1/ff905cebe41cc2b7000dbd8f60c2df58/execroot/io_bazel/bazel-out/darwin-fastbuild/bin/_solib_darwin/libexamples_Scpp_Slibhello-lib.dylib
++ next=/private/tmp/nix-build-bazel-6.4.0.drv-1/_bazel__nixbld1/ff905cebe41cc2b7000dbd8f60c2df58/execroot/io_bazel/bazel-out/darwin-fastbuild/bin/examples/cpp/libhello-lib.dylib
++ '[' -n /private/tmp/nix-build-bazel-6.4.0.drv-1/_bazel__nixbld1/ff905cebe41cc2b7000dbd8f60c2df58/execroot/io_bazel/bazel-out/darwin-fastbuild/bin/examples/cpp/libhello-lib.dylib ']'
++ previous=/private/tmp/nix-build-bazel-6.4.0.drv-1/_bazel__nixbld1/ff905cebe41cc2b7000dbd8f60c2df58/execroot/io_bazel/bazel-out/darwin-fastbuild/bin/examples/cpp/libhello-lib.dylib
+++ readlink /private/tmp/nix-build-bazel-6.4.0.drv-1/_bazel__nixbld1/ff905cebe41cc2b7000dbd8f60c2df58/execroot/io_bazel/bazel-out/darwin-fastbuild/bin/examples/cpp/libhello-lib.dylib
++ next=
+ /nix/store/hfwdjfb4203x8rl4s6q565016hi3m0d3-cctools-llvm-11.1.0-973.0.1/bin/install_name_tool -change @loader_path/../../_solib_darwin//libexamples_Scpp_Slibhello-lib.dylib bazel-out/darwin-fastbuild/bin/examples/cpp/hello-success_test
```
note that `@loader_path...` should've been the 2nd argument to `-change`

Local host bash version is
```
% bash -version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin21)
Copyright (C) 2007 Free Software Foundation, Inc.
```
Though notably aarch64 host with
```
% bash -version
GNU bash, version 3.2.57(1)-release (arm64-apple-darwin22)
Copyright (C) 2007 Free Software Foundation, Inc.
```
doesn't hit the issue, so it may be sensitive to some other things too.

Bash changelogs do have mentions of bugs around `set -e`
https://github.com/bminor/bash/blob/master/CHANGES
though I haven't identified the exact version and bug entry.
boltzmannrain added a commit to boltzmannrain/nixpkgs that referenced this pull request Nov 15, 2023
Submitting upstream here
bazelbuild/bazel#20212

Looks like with some bash versions and under some conditions
sub-shell would propagate errors to parent shell under `set -e`
even though it shouldn't.

https://hydra.nixos.org/build/240805256/nixlog/1
https://hydra.nixos.org/build/240805170/nixlog/2

Was able to reproduce the Hydra issue on `x86_64-darwin` with `bazel_6`,
but not with `aarch64-darwin` having same numeric bash version.

ZHF: NixOS#265948
@boltzmannrain boltzmannrain marked this pull request as ready for review November 15, 2023 14:56
@github-actions github-actions bot added team-Rules-CPP Issues for C++ rules awaiting-review PR is awaiting review from an assigned reviewer labels Nov 15, 2023
@uri-canva
Copy link
Contributor

Is this a difference in behaviour between gnu readlink and bsd readlink maybe?

@boltzmannrain
Copy link
Author

Is this a difference in behaviour between gnu readlink and bsd readlink maybe?

Looks like that's more likely bash version or something other host-specific to blame, potentially some of recent system upgrades.
On my machines both BSD and GNU readlink prints nothing when hits non-symlink and sets exit code to 0.
set -x trace also shows that readlink did resolve up to the final path (also did extra debug validations via pwd, find and ls), but echo "$previous" line is missing and get_otool_path

function get_otool_path() {
    # the lib path is the path of the original lib relative to the workspace
    get_realpath $1 | sed 's|^.*/bazel-out/|bazel-out/|'
}

returns empty string (and sed shouldn't be a problem with the paths from trace)

@boltzmannrain
Copy link
Author

What's weird is that M1 system doesn't hit it but x86-64 does, despite showing same bash numeric version.
Didn't try to reproduce the underlying issue outside of bazel build&test yet, that might help to pin it down but don't know how much effort it would take.

@boltzmannrain
Copy link
Author

boltzmannrain commented Nov 16, 2023

UPDATE: script below actually uses fixed || true version and only because of that it works

Generally get_realpath seems to be working on the host, so there's some triggering factor somewhere
With symlink chain g->f->e->d->c->b->a and script

set -eu

function get_realpath() {
    local previous="$1"
    local next="$1" #$(readlink "${previous}")
    while [ -n "${next}" ]; do
        previous="${next}"
        next=$(readlink "${previous}" || true)
    done
    echo "${previous}"
}

get_realpath g | cat -

It does traverse it and print the final path

% sh -x abc.sh
+ set -eu
+ get_realpath g
+ local previous=g
+ local next=g
+ '[' -n g ']'
+ previous=g
+ cat -
++ readlink g
+ next=f
+ '[' -n f ']'
+ previous=f
++ readlink f
+ next=e
+ '[' -n e ']'
+ previous=e
++ readlink e
+ next=d
+ '[' -n d ']'
+ previous=d
++ readlink d
+ next=c
+ '[' -n c ']'
+ previous=c
++ readlink c
+ next=b
+ '[' -n b ']'
+ previous=b
++ readlink b
+ next=a
+ '[' -n a ']'
+ previous=a
++ readlink a
++ true
+ next=
+ '[' -n '' ']'
+ echo a
a

@boltzmannrain
Copy link
Author

boltzmannrain commented Nov 17, 2023

UPDATE: comment below isn't fully correct, diff uses trap "echo \"...$?...\" " but it should also escape \$

Interesting, something really weird happens here

diff --git a/tools/cpp/osx_cc_wrapper.sh.tpl b/tools/cpp/osx_cc_wrapper.sh.tpl
index 8264090c29..3620fffa77 100644
--- a/tools/cpp/osx_cc_wrapper.sh.tpl
+++ b/tools/cpp/osx_cc_wrapper.sh.tpl
@@ -76,14 +76,29 @@ function get_library_path() {
     done
 }
 
+
+echo $BASH_VERSION >&2
+set -o >&2
+shopt -o >&2
+PS4="+(prior-exit:$?) "
+trap "echo \"prior-exit:$?\" >&2" DEBUG
+trap "echo \"exit:$?\" >&2" EXIT
+set -x
+
+
 # A convenient method to return the actual path even for non symlinks
 # and multi-level symlinks.
 function get_realpath() {
+    echo $BASH_VERSION >&2
+    set -o >&2
+    shopt -o >&2
+    trap "echo \"prior-exit:$?\" >&2" DEBUG
+    trap "echo \"exit:$?\" >&2" EXIT
     local previous="$1"
     local next=$(readlink "${previous}")
     while [ -n "${next}" ]; do
         previous="${next}"
-        next=$(readlink "${previous}")
+        next=$(echo $BASH_VERSION >&2; set -o >&2; shopt -o >&2; trap "echo \"prior-exit:$?\" >&2" DEBUG; trap "echo \"exit:$?\" >&2" EXIT; readlink "${previous}" >&2 || true; readlink "${previous}")
     done
     echo "${previous}"
 }

with such debug added it seems that

  • last readlink prints nothing
  • it also seems to set exit code to 0
  • after that next= assigns empty string
  • after that there's no attempt to evaluate [ -n and no echo "${previous}" issued either

Adding || true to readlink though still seems to fix the issue

Failing run log ends with following

++(prior-exit:0) next=/private/tmp/nix-build-bazel-6.4.0.drv-3/_bazel__nixbld1/ca2e187ab10356ea20e714dca48cb05c/execroot/io_bazel/bazel-out/darwin-fastbuild/bin/examples/cpp/libhello-lib.dylib
+++(prior-exit:0) echo prior-exit:0
prior-exit:0
++(prior-exit:0) '[' -n /private/tmp/nix-build-bazel-6.4.0.drv-3/_bazel__nixbld1/ca2e187ab10356ea20e714dca48cb05c/execroot/io_bazel/bazel-out/darwin-fastbuild/bin/examples/cpp/libhello-lib.dylib ']'
+++(prior-exit:0) echo prior-exit:0
prior-exit:0
++(prior-exit:0) previous=/private/tmp/nix-build-bazel-6.4.0.drv-3/_bazel__nixbld1/ca2e187ab10356ea20e714dca48cb05c/execroot/io_bazel/bazel-out/darwin-fastbuild/bin/examples/cpp/libhello-lib.dylib
+++(prior-exit:0) echo prior-exit:0
prior-exit:0
+++(prior-exit:0) echo '3.2.57(1)-release'
3.2.57(1)-release
+++(prior-exit:0) set -o
allexport       off
braceexpand     on
emacs           off
errexit         on
errtrace        off
functrace       off
hashall         on
histexpand      off
history         off
ignoreeof       off
interactive-comments    on
keyword         off
monitor         off
noclobber       off
noexec          off
noglob          off
nolog           off
notify          off
nounset         on
onecmd          off
physical        off
pipefail        off
posix           on
privileged      off
verbose         off
vi              off
xtrace          on
+++(prior-exit:0) shopt -o
allexport       off
braceexpand     on
emacs           off
errexit         on
errtrace        off
functrace       off
hashall         on
histexpand      off
history         off
ignoreeof       off
interactive-comments    on
keyword         off
monitor         off
noclobber       off
noexec          off
noglob          off
nolog           off
notify          off
nounset         on
onecmd          off
physical        off
pipefail        off
posix           on
privileged      off
verbose         off
vi              off
xtrace          on
+++(prior-exit:0) trap 'echo "prior-exit:0" >&2' DEBUG
++++(prior-exit:0) echo prior-exit:0
prior-exit:0
+++(prior-exit:0) trap 'echo "exit:0" >&2' EXIT
++++(prior-exit:0) echo prior-exit:0
prior-exit:0
+++(prior-exit:0) readlink /private/tmp/nix-build-bazel-6.4.0.drv-3/_bazel__nixbld1/ca2e187ab10356ea20e714dca48cb05c/execroot/io_bazel/bazel-out/darwin-fastbuild/bin/examples/cpp/libhello-lib.dylib
++++(prior-exit:0) echo prior-exit:0
prior-exit:0
+++(prior-exit:0) true
++++(prior-exit:0) echo prior-exit:0
prior-exit:0
+++(prior-exit:0) readlink /private/tmp/nix-build-bazel-6.4.0.drv-3/_bazel__nixbld1/ca2e187ab10356ea20e714dca48cb05c/execroot/io_bazel/bazel-out/darwin-fastbuild/bin/examples/cpp/libhello-lib.dylib
++++(prior-exit:0) echo prior-exit:0
prior-exit:0
+++(prior-exit:0) echo exit:0
exit:0
++(prior-exit:0) next=
+++(prior-exit:0) echo prior-exit:0
prior-exit:0
++(prior-exit:0) echo exit:0
exit:0
+(prior-exit:0) /nix/store/hfwdjfb4203x8rl4s6q565016hi3m0d3-cctools-llvm-11.1.0-973.0.1/bin/install_name_tool -change @loader_path/../../_solib_darwin//libexamples_Scpp_Slibhello-lib.dylib bazel-out/darwin-fastbuild/bin/examples/cpp/hello-success_test
Usage: /nix/store/hfwdjfb4203x8rl4s6q565016hi3m0d3-cctools-llvm-11.1.0-973.0.1/bin/install_name_tool [-change old new] ... [-rpath old new] ... [-add_rpath new] ... [-delete_rpath old] ... [-id name] input
++(prior-exit:0) echo prior-exit:0
prior-exit:0
+(prior-exit:0) echo exit:0
exit:0

I think it'd be fair to draft the PR for now as it is too puzzling atm why the patch helps

@boltzmannrain boltzmannrain marked this pull request as draft November 17, 2023 01:14
@boltzmannrain
Copy link
Author

New run with more extensive debug prints shows that

  • last readlink returns non-zero exit code and empty output (expected)
  • sub-shell with readlink exits immediately (not sure if expected, -e shouldn't be propagated there)
  • after that next= empty assignment happens (expected)
  • while loop exits without right after that (unexpected, should've continued to end of body and to check the condition)
  • get_realpath exits without echo "${previous}"

So looks like we're back to bash issue hypothesis that for some reason decided to propagate subshell failure (maybe sporadic activation of -E/errtrace behavior?)

diff --git a/tools/cpp/osx_cc_wrapper.sh.tpl b/tools/cpp/osx_cc_wrapper.sh.tpl
index 8264090c29..c2de847981 100644
--- a/tools/cpp/osx_cc_wrapper.sh.tpl
+++ b/tools/cpp/osx_cc_wrapper.sh.tpl
@@ -76,15 +76,33 @@ function get_library_path() {
     done
 }
 
+
+ulimit -a >&2
+echo $BASH_VERSION >&2
+set -o >&2
+shopt -o >&2
+PS4="+(prior-exit:$?) "
+trap "echo \"prior-exit:\$?\" >&2" DEBUG
+trap "echo \"exit:\$?\" >&2" EXIT
+set -x
+
+
 # A convenient method to return the actual path even for non symlinks
 # and multi-level symlinks.
 function get_realpath() {
+    echo $BASH_VERSION >&2
+    set -o >&2
+    shopt -o >&2
+    trap "echo \"prior-exit:\$?\" >&2" DEBUG
+    trap "echo \"exit:\$?\" >&2" EXIT
     local previous="$1"
     local next=$(readlink "${previous}")
-    while [ -n "${next}" ]; do
+    while echo "while start" >&2; [ -n "${next}" ]; do
         previous="${next}"
-        next=$(readlink "${previous}")
+        next=$(ulimit -a >&2; echo $BASH_VERSION >&2; set -o >&2; shopt -o >&2; trap "echo \"prior-exit:\$?\" >&2" DEBUG; trap "echo \"exit:\$?\" >&2" EXIT; readlink "${previous}" >&2 || true; readlink "${previous}"; echo "after readlink $?" >&2)
+        echo "after next" >&2
     done
+    echo "after while" >&2
     echo "${previous}"
 }

logs

+++(prior-exit:0) readlink /private/tmp/nix-build-bazel-6.4.0.drv-4/_bazel__nixbld1/28750aefb4827f6009387cd4b2525548/execroot/io_bazel/bazel-out/darwin-fastbuild/bin/examples/cpp/libhello-lib.dylib
++++(prior-exit:0) echo prior-exit:1
prior-exit:1
+++(prior-exit:0) echo exit:1
exit:1
++(prior-exit:0) next=
+++(prior-exit:0) echo prior-exit:1
prior-exit:1
++(prior-exit:0) echo exit:1
exit:1
+(prior-exit:0) /nix/store/hfwdjfb4203x8rl4s6q565016hi3m0d3-cctools-llvm-11.1.0-973.0.1/bin/install_name_tool -change @loader_path/../../_solib_darwin//libexamples_Scpp_Slibhello-lib.dylib bazel-out/darwin-fastbuild/bin/examples/cpp/hello-success_test
Usage: /nix/store/hfwdjfb4203x8rl4s6q565016hi3m0d3-cctools-llvm-11.1.0-973.0.1/bin/install_name_tool [-change old new] ... [-rpath old new] ... [-add_rpath new] ... [-delete_rpath old] ... [-id name] input

@boltzmannrain
Copy link
Author

boltzmannrain commented Nov 18, 2023

And now I'm confused even more

$ touch a
$ ln -s a b
$ bash -c -x 'set -eu; a=1; a=$(readlink a); echo ok'
+ set -eu
+ a=1
++ readlink a
+ a=

$ bash -c -x 'set -eu; function f() { local a=1; a=$(readlink a); }; f; echo ok' 
+ set -eu
+ f
+ local a=1
++ readlink a
+ a=

$ bash -c -x 'set -e; function f() { local a=b; while [ -n "$a" ]; do a=$(readlink "$a"); done;}; f; echo ok' 
+ set -e
+ f
+ local a=b
+ '[' -n b ']'
++ readlink b
+ a=a
+ '[' -n a ']'
++ readlink a
+ a=

$ bash -c -x 'set -e; a=1; a=$(false); echo ok'
+ set -e
+ a=1
++ false
+ a=

This seems to actually be broken everywhere

$ bash --version
GNU bash, version 5.2.15(1)-release (x86_64-pc-linux-gnu)
% bash --version
GNU bash, version 3.2.57(1)-release (arm64-apple-darwin22)
% bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin21)

But it seems that is was working sometimes on macos 🤔

@boltzmannrain
Copy link
Author

boltzmannrain commented Nov 18, 2023

The very first readlink doesn't trigger exit because apparently local a= masks subshell exit code (local is a "command") but subsequent a= doesn't.

$ bash -c -x 'set -e; function f() { local a=$(readlink a); while [ -n "$a" ]; do a=$(readlink "$a"); done;}; f; echo ok' 
+ set -e
+ f
++ readlink a
+ local a=
+ '[' -n '' ']'
+ echo ok
ok

$ bash -c -x 'set -e; function f() { local a=$(readlink b); while [ -n "$a" ]; do a=$(readlink "$a"); done;}; f; echo ok' 
+ set -e
+ f
++ readlink b
+ local a=a
+ '[' -n a ']'
++ readlink a
+ a=

So refined hypothesis is it never worked with symlinks. But still not quite clear what determines presence of symlink hops and when did it change / why did it work most of the time so far.

Or alternatively, it did work with very old bash version on macos but some of recent upgrades broke it (need to see if can get hold of older bash versions and confirm them vs macos upgrades to test)

@boltzmannrain
Copy link
Author

get_otool_path "${libpath}" on x86_64-darwin on NixOS ends up being called for bazel-out/darwin-fastbuild/bin/_solib_darwin/libexamples_Scpp_Slibhello-lib.dylib which is a symlink there, to execroot/io_bazel/bazel-out/darwin-fastbuild/bin/_solib_darwin/libexamples_Scpp_Slibhello-lib.dylib (a little suspicious-looking path?) and continues few symlinks further.
On aarch-64-darwin this libpath seems to be the normal file and doesn't go into symlink following loop.

@boltzmannrain
Copy link
Author

Turns out not exactly bazel or bash fault here. The problem is in NixOS shebang replacement that used non-binary interpreter and that isn't guaranteed to work (XNU kernel can deny execution of scripts and calling shell or env don't necessarily have code to handle interpreter that is a script itself)

@github-actions github-actions bot removed the awaiting-review PR is awaiting review from an assigned reviewer label Nov 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
team-Rules-CPP Issues for C++ rules
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants