1{-# LANGUAGE CApiFFI #-} 2#if __GLASGOW_HASKELL__ >= 709 3{-# LANGUAGE Safe #-} 4#else 5{-# LANGUAGE Trustworthy #-} 6#endif 7----------------------------------------------------------------------------- 8-- | 9-- Module : System.Posix.Resource 10-- Copyright : (c) The University of Glasgow 2003 11-- License : BSD-style (see the file libraries/base/LICENSE) 12-- 13-- Maintainer : libraries@haskell.org 14-- Stability : provisional 15-- Portability : non-portable (requires POSIX) 16-- 17-- POSIX resource support 18-- 19----------------------------------------------------------------------------- 20 21module System.Posix.Resource ( 22 -- * Resource Limits 23 ResourceLimit(..), ResourceLimits(..), Resource(..), 24 getResourceLimit, 25 setResourceLimit, 26 ) where 27 28#include "HsUnix.h" 29 30import System.Posix.Types 31import Foreign 32import Foreign.C 33 34-- ----------------------------------------------------------------------------- 35-- Resource limits 36 37data Resource 38 = ResourceCoreFileSize 39 | ResourceCPUTime 40 | ResourceDataSize 41 | ResourceFileSize 42 | ResourceOpenFiles 43 | ResourceStackSize 44#ifdef RLIMIT_AS 45 | ResourceTotalMemory 46#endif 47 deriving Eq 48 49data ResourceLimits 50 = ResourceLimits { softLimit, hardLimit :: ResourceLimit } 51 deriving Eq 52 53data ResourceLimit 54 = ResourceLimitInfinity 55 | ResourceLimitUnknown 56 | ResourceLimit Integer 57 deriving Eq 58 59data {-# CTYPE "struct rlimit" #-} RLimit 60 61foreign import capi unsafe "HsUnix.h getrlimit" 62 c_getrlimit :: CInt -> Ptr RLimit -> IO CInt 63 64foreign import capi unsafe "HsUnix.h setrlimit" 65 c_setrlimit :: CInt -> Ptr RLimit -> IO CInt 66 67getResourceLimit :: Resource -> IO ResourceLimits 68getResourceLimit res = do 69 allocaBytes (#const sizeof(struct rlimit)) $ \p_rlimit -> do 70 throwErrnoIfMinus1_ "getResourceLimit" $ 71 c_getrlimit (packResource res) p_rlimit 72 soft <- (#peek struct rlimit, rlim_cur) p_rlimit 73 hard <- (#peek struct rlimit, rlim_max) p_rlimit 74 return (ResourceLimits { 75 softLimit = unpackRLimit soft, 76 hardLimit = unpackRLimit hard 77 }) 78 79setResourceLimit :: Resource -> ResourceLimits -> IO () 80setResourceLimit res ResourceLimits{softLimit=soft,hardLimit=hard} = do 81 allocaBytes (#const sizeof(struct rlimit)) $ \p_rlimit -> do 82 (#poke struct rlimit, rlim_cur) p_rlimit (packRLimit soft True) 83 (#poke struct rlimit, rlim_max) p_rlimit (packRLimit hard False) 84 throwErrnoIfMinus1_ "setResourceLimit" $ 85 c_setrlimit (packResource res) p_rlimit 86 return () 87 88packResource :: Resource -> CInt 89packResource ResourceCoreFileSize = (#const RLIMIT_CORE) 90packResource ResourceCPUTime = (#const RLIMIT_CPU) 91packResource ResourceDataSize = (#const RLIMIT_DATA) 92packResource ResourceFileSize = (#const RLIMIT_FSIZE) 93packResource ResourceOpenFiles = (#const RLIMIT_NOFILE) 94packResource ResourceStackSize = (#const RLIMIT_STACK) 95#ifdef RLIMIT_AS 96packResource ResourceTotalMemory = (#const RLIMIT_AS) 97#endif 98 99unpackRLimit :: CRLim -> ResourceLimit 100unpackRLimit (#const RLIM_INFINITY) = ResourceLimitInfinity 101unpackRLimit other 102#if defined(RLIM_SAVED_MAX) 103 | ((#const RLIM_SAVED_MAX) :: CRLim) /= (#const RLIM_INFINITY) && 104 other == (#const RLIM_SAVED_MAX) = ResourceLimitUnknown 105#endif 106#if defined(RLIM_SAVED_CUR) 107 | ((#const RLIM_SAVED_CUR) :: CRLim) /= (#const RLIM_INFINITY) && 108 other == (#const RLIM_SAVED_CUR) = ResourceLimitUnknown 109#endif 110 | otherwise = ResourceLimit (fromIntegral other) 111 112packRLimit :: ResourceLimit -> Bool -> CRLim 113packRLimit ResourceLimitInfinity _ = (#const RLIM_INFINITY) 114#ifdef RLIM_SAVED_CUR 115packRLimit ResourceLimitUnknown True = (#const RLIM_SAVED_CUR) 116#endif 117#ifdef RLIM_SAVED_MAX 118packRLimit ResourceLimitUnknown False = (#const RLIM_SAVED_MAX) 119#endif 120packRLimit (ResourceLimit other) _ = fromIntegral other 121 122 123-- ----------------------------------------------------------------------------- 124-- Test code 125 126{- 127import System.Posix 128import Control.Monad 129 130main = do 131 zipWithM_ (\r n -> setResourceLimit r ResourceLimits{ 132 hardLimit = ResourceLimit n, 133 softLimit = ResourceLimit n }) 134 allResources [1..] 135 showAll 136 mapM_ (\r -> setResourceLimit r ResourceLimits{ 137 hardLimit = ResourceLimit 1, 138 softLimit = ResourceLimitInfinity }) 139 allResources 140 -- should fail 141 142 143showAll = 144 mapM_ (\r -> getResourceLimit r >>= (putStrLn . showRLims)) allResources 145 146allResources = 147 [ResourceCoreFileSize, ResourceCPUTime, ResourceDataSize, 148 ResourceFileSize, ResourceOpenFiles, ResourceStackSize 149#ifdef RLIMIT_AS 150 , ResourceTotalMemory 151#endif 152 ] 153 154showRLims ResourceLimits{hardLimit=h,softLimit=s} 155 = "hard: " ++ showRLim h ++ ", soft: " ++ showRLim s 156 157showRLim ResourceLimitInfinity = "infinity" 158showRLim ResourceLimitUnknown = "unknown" 159showRLim (ResourceLimit other) = show other 160-} 161