Commit e5d479b06e

Andrew Kelley <andrew@ziglang.org>
2020-04-04 18:26:57
detect an endless loop when trying to detect native libc installation
closes #4810
1 parent 52db137
Changed files (4)
src/error.cpp
@@ -85,6 +85,7 @@ const char *err_str(Error err) {
         case ErrorInvalidOperatingSystemVersion: return "invalid operating system version";
         case ErrorUnknownClangOption: return "unknown Clang option";
         case ErrorNestedResponseFile: return "nested response file";
+        case ErrorZigIsTheCCompiler: return "Zig was not provided with libc installation information, and so it does not know where the libc paths are on the system. Zig attempted to use the system C compiler to find out where the libc paths are, but discovered that Zig is being used as the system C compiler.";
     }
     return "(invalid error)";
 }
src/stage2.h
@@ -107,6 +107,7 @@ enum Error {
     ErrorInvalidOperatingSystemVersion,
     ErrorUnknownClangOption,
     ErrorNestedResponseFile,
+    ErrorZigIsTheCCompiler,
 };
 
 // ABI warning
src-self-hosted/libc_installation.zig
@@ -32,6 +32,7 @@ pub const LibCInstallation = struct {
         LibCKernel32LibNotFound,
         UnsupportedArchitecture,
         WindowsSdkNotFound,
+        ZigIsTheCCompiler,
     };
 
     pub fn parse(
@@ -229,10 +230,19 @@ pub const LibCInstallation = struct {
             "-xc",
             dev_null,
         };
+        var env_map = try std.process.getEnvMap(allocator);
+        defer env_map.deinit();
+
+        // Detect infinite loops.
+        const inf_loop_env_key = "ZIG_IS_DETECTING_LIBC_PATHS";
+        if (env_map.get(inf_loop_env_key) != null) return error.ZigIsTheCCompiler;
+        try env_map.set(inf_loop_env_key, "1");
+
         const exec_res = std.ChildProcess.exec(.{
             .allocator = allocator,
             .argv = &argv,
             .max_output_bytes = 1024 * 1024,
+            .env_map = &env_map,
             // Some C compilers, such as Clang, are known to rely on argv[0] to find the path
             // to their own executable, without even bothering to resolve PATH. This results in the message:
             // error: unable to execute command: Executable "" doesn't exist!
@@ -518,10 +528,19 @@ fn ccPrintFileName(args: CCPrintFileNameOptions) ![:0]u8 {
     defer allocator.free(arg1);
     const argv = [_][]const u8{ cc_exe, arg1 };
 
+    var env_map = try std.process.getEnvMap(allocator);
+    defer env_map.deinit();
+
+    // Detect infinite loops.
+    const inf_loop_env_key = "ZIG_IS_DETECTING_LIBC_PATHS";
+    if (env_map.get(inf_loop_env_key) != null) return error.ZigIsTheCCompiler;
+    try env_map.set(inf_loop_env_key, "1");
+
     const exec_res = std.ChildProcess.exec(.{
         .allocator = allocator,
         .argv = &argv,
         .max_output_bytes = 1024 * 1024,
+        .env_map = &env_map,
         // Some C compilers, such as Clang, are known to rely on argv[0] to find the path
         // to their own executable, without even bothering to resolve PATH. This results in the message:
         // error: unable to execute command: Executable "" doesn't exist!
src-self-hosted/stage2.zig
@@ -115,6 +115,7 @@ const Error = extern enum {
     InvalidOperatingSystemVersion,
     UnknownClangOption,
     NestedResponseFile,
+    ZigIsTheCCompiler,
 };
 
 const FILE = std.c.FILE;
@@ -868,6 +869,7 @@ export fn stage2_libc_find_native(stage1_libc: *Stage2LibCInstallation) Error {
         error.LibCKernel32LibNotFound => return .LibCKernel32LibNotFound,
         error.UnsupportedArchitecture => return .UnsupportedArchitecture,
         error.WindowsSdkNotFound => return .WindowsSdkNotFound,
+        error.ZigIsTheCCompiler => return .ZigIsTheCCompiler,
     };
     stage1_libc.initFromStage2(libc);
     return .None;