1515#if TCL_MAJOR_VERSION >= 9 && !defined(USE_TCL_RUNFILE_INIT)
1616#include " bazel/tcl_resources_zip_data.h"
1717#else
18+ #ifdef __linux__
19+ #include < linux/limits.h>
20+ #include < unistd.h>
21+ #endif
22+
1823#include < memory>
1924
2025#include " rules_cc/cc/runfiles/runfiles.h"
@@ -36,8 +41,26 @@ static std::optional<std::string> TclLibraryMountPoint(Tcl_Interp* interp)
3641#else
3742 using rules_cc::cc::runfiles::Runfiles;
3843 std::string error;
39- std::unique_ptr<Runfiles> runfiles (Runfiles::Create (
40- Tcl_GetNameOfExecutable (), BAZEL_CURRENT_REPOSITORY , &error));
44+ // Use /proc/self/exe to resolve the real binary path, as argv[0] may
45+ // point into a sandbox where the .runfiles tree does not exist.
46+ std::string exe_path;
47+ #ifdef __linux__
48+ char buf[PATH_MAX + 1 ];
49+ ssize_t len = readlink (" /proc/self/exe" , buf, PATH_MAX );
50+ if (len > 0 && len < PATH_MAX ) {
51+ exe_path.assign (buf, len);
52+ } else {
53+ if (len >= PATH_MAX ) {
54+ std::cerr << " [Error] /proc/self/exe path too long (>= PATH_MAX); "
55+ " falling back to Tcl_GetNameOfExecutable()\n " ;
56+ }
57+ exe_path = Tcl_GetNameOfExecutable ();
58+ }
59+ #else
60+ exe_path = Tcl_GetNameOfExecutable ();
61+ #endif
62+ std::unique_ptr<Runfiles> runfiles (
63+ Runfiles::Create (exe_path, BAZEL_CURRENT_REPOSITORY , &error));
4164 if (!runfiles) {
4265 std::cerr << " [Warning] Failed to create bazel runfiles: " << error << " \n " ;
4366 return std::nullopt ;
0 commit comments