diff --git a/System/Posix/Env.hsc b/System/Posix/Env.hsc
--- a/System/Posix/Env.hsc
+++ b/System/Posix/Env.hsc
@@ -50,7 +50,9 @@
 
 -- |'getEnv' looks up a variable in the environment.
 
-getEnv :: String -> IO (Maybe String)
+getEnv ::
+  String            {- ^ variable name  -} ->
+  IO (Maybe String) {- ^ variable value -}
 getEnv name = do
   litstring <- withFilePath name c_getenv
   if litstring /= nullPtr
@@ -61,7 +63,10 @@
 -- programmer can specify a fallback if the variable is not found
 -- in the environment.
 
-getEnvDefault :: String -> String -> IO String
+getEnvDefault ::
+  String    {- ^ variable name                    -} ->
+  String    {- ^ fallback value                   -} ->
+  IO String {- ^ variable value or fallback value -}
 getEnvDefault name fallback = liftM (fromMaybe fallback) (getEnv name)
 
 foreign import ccall unsafe "getenv"
@@ -94,7 +99,7 @@
 -- |'getEnvironment' retrieves the entire environment as a
 -- list of @(key,value)@ pairs.
 
-getEnvironment :: IO [(String,String)]
+getEnvironment :: IO [(String,String)] {- ^ @[(key,value)]@ -}
 getEnvironment = do
   env <- getEnvironmentPrim
   return $ map (dropEq.(break ((==) '='))) env
@@ -105,7 +110,9 @@
 -- |'setEnvironment' resets the entire environment to the given list of
 -- @(key,value)@ pairs.
 
-setEnvironment :: [(String,String)] -> IO ()
+setEnvironment ::
+  [(String,String)] {- ^ @[(key,value)]@ -} ->
+  IO ()
 setEnvironment env = do
   clearEnv
   forM_ env $ \(key,value) ->
@@ -114,7 +121,7 @@
 -- |The 'unsetEnv' function deletes all instances of the variable name
 -- from the environment.
 
-unsetEnv :: String -> IO ()
+unsetEnv :: String {- ^ variable name -} -> IO ()
 #if HAVE_UNSETENV
 # if !UNSETENV_RETURNS_VOID
 unsetEnv name = withFilePath name $ \ s ->
@@ -137,7 +144,7 @@
 -- |'putEnv' function takes an argument of the form @name=value@
 -- and is equivalent to @setEnv(key,value,True{-overwrite-})@.
 
-putEnv :: String -> IO ()
+putEnv :: String {- ^ "key=value" -} -> IO ()
 putEnv keyvalue = do s <- newFilePath keyvalue
                      -- Do not free `s` after calling putenv.
                      -- According to SUSv2, the string passed to putenv
@@ -159,7 +166,11 @@
      not reset, otherwise it is reset to the given value.
 -}
 
-setEnv :: String -> String -> Bool {-overwrite-} -> IO ()
+setEnv ::
+  String {- ^ variable name  -} ->
+  String {- ^ variable value -} ->
+  Bool   {- ^ overwrite      -} ->
+  IO ()
 #ifdef HAVE_SETENV
 setEnv key value ovrwrt = do
   withFilePath key $ \ keyP ->
diff --git a/System/Posix/Env/ByteString.hsc b/System/Posix/Env/ByteString.hsc
--- a/System/Posix/Env/ByteString.hsc
+++ b/System/Posix/Env/ByteString.hsc
@@ -45,7 +45,9 @@
 
 -- |'getEnv' looks up a variable in the environment.
 
-getEnv :: ByteString -> IO (Maybe ByteString)
+getEnv ::
+  ByteString            {- ^ variable name  -} ->
+  IO (Maybe ByteString) {- ^ variable value -}
 getEnv name = do
   litstring <- B.useAsCString name c_getenv
   if litstring /= nullPtr
@@ -56,7 +58,10 @@
 -- programmer can specify a fallback if the variable is not found
 -- in the environment.
 
-getEnvDefault :: ByteString -> ByteString -> IO ByteString
+getEnvDefault ::
+  ByteString    {- ^ variable name                    -} ->
+  ByteString    {- ^ fallback value                   -} ->
+  IO ByteString {- ^ variable value or fallback value -}
 getEnvDefault name fallback = liftM (fromMaybe fallback) (getEnv name)
 
 foreign import ccall unsafe "getenv"
@@ -86,7 +91,7 @@
 -- |'getEnvironment' retrieves the entire environment as a
 -- list of @(key,value)@ pairs.
 
-getEnvironment :: IO [(ByteString,ByteString)]
+getEnvironment :: IO [(ByteString,ByteString)] {- ^ @[(key,value)]@ -}
 getEnvironment = do
   env <- getEnvironmentPrim
   return $ map (dropEq.(BC.break ((==) '='))) env
@@ -98,7 +103,7 @@
 -- |The 'unsetEnv' function deletes all instances of the variable name
 -- from the environment.
 
-unsetEnv :: ByteString -> IO ()
+unsetEnv :: ByteString {- ^ variable name -} -> IO ()
 #if HAVE_UNSETENV
 # if !UNSETENV_RETURNS_VOID
 unsetEnv name = B.useAsCString name $ \ s ->
@@ -121,7 +126,7 @@
 -- |'putEnv' function takes an argument of the form @name=value@
 -- and is equivalent to @setEnv(key,value,True{-overwrite-})@.
 
-putEnv :: ByteString -> IO ()
+putEnv :: ByteString {- ^ "key=value" -} -> IO ()
 putEnv keyvalue = B.useAsCString keyvalue $ \s ->
   throwErrnoIfMinus1_ "putenv" (c_putenv s)
 
@@ -135,7 +140,11 @@
      not reset, otherwise it is reset to the given value.
 -}
 
-setEnv :: ByteString -> ByteString -> Bool {-overwrite-} -> IO ()
+setEnv ::
+  ByteString {- ^ variable name  -} ->
+  ByteString {- ^ variable value -} ->
+  Bool       {- ^ overwrite      -} ->
+  IO ()
 #ifdef HAVE_SETENV
 setEnv key value ovrwrt = do
   B.useAsCString key $ \ keyP ->
diff --git a/cbits/HsUnix.c b/cbits/HsUnix.c
--- a/cbits/HsUnix.c
+++ b/cbits/HsUnix.c
@@ -37,12 +37,29 @@
 }
 
 /*
+ * GNU glibc 2.23 and later deprecate `readdir_r` in favour of plain old
+ * `readdir` which in some upcoming POSIX standard is going to required to be
+ * re-entrant.
+ * Eventually we want to drop `readder_r` all together, but want to be
+ * compatible with older unixen which may not have a re-entrant `readdir`.
+ * Solution is to make systems with *known* re-entrant `readir` use that and use
+ * `readdir_r` whereever we have it and don't *know* that `readdir` is
+ * re-entrant.
+ */
+
+#if defined (__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 23)
+#define USE_READDIR_R 0
+#else
+#define USE_READDIR_R 1
+#endif
+
+/*
  * read an entry from the directory stream; opt for the
  * re-entrant friendly way of doing this, if available.
  */
 int __hscore_readdir( DIR *dirPtr, struct dirent **pDirEnt )
 {
-#if HAVE_READDIR_R
+#if HAVE_READDIR_R && USE_READDIR_R
   struct dirent* p;
   int res;
   static unsigned int nm_max = (unsigned int)-1;
@@ -93,7 +110,7 @@
 
 void __hscore_free_dirent(struct dirent *dEnt)
 {
-#if HAVE_READDIR_R
+#if HAVE_READDIR_R && USE_READDIR_R
   free(dEnt);
 #endif
 }
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,11 @@
 # Changelog for [`unix` package](http://hackage.haskell.org/package/unix)
 
+## 2.7.2.1  *Nov 2016*
+
+  * Don't use `readdir_r` if its deprecated.
+
+  * Add argument documentation for Env modules
+
 ## 2.7.2.0  *Apr 2016*
 
   * Bundled with GHC 8.0.1
diff --git a/configure b/configure
--- a/configure
+++ b/configure
@@ -667,6 +667,7 @@
 docdir
 oldincludedir
 includedir
+runstatedir
 localstatedir
 sharedstatedir
 sysconfdir
@@ -738,6 +739,7 @@
 sysconfdir='${prefix}/etc'
 sharedstatedir='${prefix}/com'
 localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
 includedir='${prefix}/include'
 oldincludedir='/usr/include'
 docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
@@ -990,6 +992,15 @@
   | -silent | --silent | --silen | --sile | --sil)
     silent=yes ;;
 
+  -runstatedir | --runstatedir | --runstatedi | --runstated \
+  | --runstate | --runstat | --runsta | --runst | --runs \
+  | --run | --ru | --r)
+    ac_prev=runstatedir ;;
+  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+  | --run=* | --ru=* | --r=*)
+    runstatedir=$ac_optarg ;;
+
   -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
     ac_prev=sbindir ;;
   -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@@ -1127,7 +1138,7 @@
 for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
 		datadir sysconfdir sharedstatedir localstatedir includedir \
 		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
-		libdir localedir mandir
+		libdir localedir mandir runstatedir
 do
   eval ac_val=\$$ac_var
   # Remove trailing slashes.
@@ -1280,6 +1291,7 @@
   --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
   --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
   --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
   --libdir=DIR            object code libraries [EPREFIX/lib]
   --includedir=DIR        C header files [PREFIX/include]
   --oldincludedir=DIR     C header files for non-gcc [/usr/include]
diff --git a/unix.cabal b/unix.cabal
--- a/unix.cabal
+++ b/unix.cabal
@@ -1,5 +1,5 @@
 name:           unix
-version:        2.7.2.0
+version:        2.7.2.1
 -- NOTE: Don't forget to update ./changelog.md
 license:        BSD3
 license-file:   LICENSE
