Fix environ enumeration on Apple platforms
authorMatt Glazar <strager@fb.com>
Sat, 4 Feb 2017 00:59:31 +0000 (16:59 -0800)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Sat, 4 Feb 2017 01:03:06 +0000 (17:03 -0800)
Summary:
environ is documented to not work very well from .dylib-s (dynamic libraries) on macOS. Use the _NSGetEnviron function instead to get a pointer to environ.

<crt_externs.h> is missing from some iOS SDKs, so forward-declare _NSGetEnviron in such cases.

Reviewed By: Orvid, mzlee

Differential Revision: D4491044

fbshipit-source-id: 886d19bdd63dea14225992446b7ba132faf35054

folly/portability/Stdlib.h

index c3bf734075e0401c2454da7215b2da3c5645a8b2..333453da781d450ca6fa52afed858b26f9fb49c9 100644 (file)
 
 #include <cstdlib>
 
+#if defined(__APPLE__)
+#if __has_include(<crt_externs.h>)
+#include <crt_externs.h>
+#endif
+#endif
+
 extern "C" {
 #ifdef _WIN32
 // These are technically supposed to be defined linux/limits.h and
@@ -35,6 +41,10 @@ char* realpath(const char* path, char* resolved_path);
 int setenv(const char* name, const char* value, int overwrite);
 int unsetenv(const char* name);
 #elif defined(__APPLE__)
-extern char** environ;
+// environ doesn't work well with dylibs, so use _NSGetEnviron instead.
+#if !__has_include(<crt_externs.h>)
+char*** _NSGetEnviron(void);
+#endif
+#define environ (*_NSGetEnviron())
 #endif
 }