I went into a problem while working on a PHP extension. Because PHP dlopens extensions with the RTLD_DEEPBIND flag, std.c.environ would be null since it’s linked to a dormant copy of the variable instead of the one used by the main program.
The following appears to fix the issue:
if (@intFromPtr(std.c.environ) == 0) {
if (std.c.dlopen(null, .{ .LAZY = true, .NOLOAD = true })) |handle| {
defer _ = std.c.dlclose(handle);
if (std.c.dlsym(handle, "environ")) |symbol| {
const environ_ptr: @TypeOf(&std.c.environ) = @ptrCast(@alignCast(symbol));
std.c.environ = environ_ptr.*;
}
}
}
// this would segfault without the fix above
const env_map = try std.process.getEnvMap(al);
var env_iter = env_map.iterator();
while (env_iter.next()) |entry| {
std.debug.print("{s} = {s}\n", .{ entry.key_ptr.*, entry.value_ptr.* });
}
I was wondering whether the workaround belongs in std. On one hand, it prevents baffling crashes in multiple places. On the other, the feature in question is working as advertised. I don’t know what its purpose is, but it must have one I imagine.