11from typing import NamedTuple , Annotated
2- import resource
32from enum import Enum
3+ import resource
44
55
66class LimitType (Enum ):
@@ -11,6 +11,16 @@ class LimitType(Enum):
1111 Processes = resource .RLIMIT_NPROC
1212
1313
14+ REASONABLE_LIMITS : dict [LimitType , int ] = {
15+ LimitType .Files : 10
16+ * 10240 , # Minimum recommended for production servers handling multiple connections
17+ LimitType .Cores : 0 , # Disable core dumps to save disk space in production
18+ LimitType .CPU : 3600 , # 1 hour soft limit to prevent runaway processes
19+ LimitType .FileSize : int (1e12 ), # 1 TB to cap large file creations like logs
20+ LimitType .Processes : 4096 , # Supports multiple workers without risking overload
21+ }
22+
23+
1424class Limit (NamedTuple ):
1525 type : LimitType
1626 soft : int
@@ -29,10 +39,17 @@ def limit(scope: LimitType) -> Limit:
2939 return Limit (scope , * resource .getrlimit (scope .value ))
3040
3141
32- def unlimit (scope : LimitType , ratio : float = 1.0 ) -> int | bool :
42+ def unlimit (
43+ scope : LimitType , ratio : float = 1.0 , * , maximum : int | None = 0
44+ ) -> int | bool :
3345 lm = limit (scope )
3446 try :
3547 target = int (lm .soft + ratio * (lm .hard - lm .soft ))
48+ # We apply reasonable limits, as for instance Darwin has really high
49+ # limits that will lead to OverflowErrors.
50+ maximum = REASONABLE_LIMITS .get (scope ) if maximum == 0 else maximum
51+ if maximum :
52+ target = min (maximum , target )
3653 resource .setrlimit (scope .value , (target , lm .hard ))
3754 return target
3855 except ValueError :
0 commit comments