Skip to content

Commit 0324c72

Browse files
gh-137044: Make resource.RLIM_INFINITY always positive (GH-137511)
It is now a positive integer larger larger than any limited resource value. This simplifies comparison of the resource values. Previously, it could be negative, such as -1 or -3, depending on platform. Deprecation warning is emitted if the old negative value is passed.
1 parent 138ed6d commit 0324c72

File tree

5 files changed

+45
-26
lines changed

5 files changed

+45
-26
lines changed

Doc/library/resource.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ this module for those platforms.
5050
.. data:: RLIM_INFINITY
5151

5252
Constant used to represent the limit for an unlimited resource.
53+
Its value is larger than any limited resource value.
54+
55+
.. versionchanged:: next
56+
It is now always positive.
57+
Previously, it could be negative, such as -1 or -3.
5358

5459

5560
.. function:: getrlimit(resource)

Doc/whatsnew/3.15.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,12 @@ Porting to Python 3.15
595595
The |pythoncapi_compat_project| can be used to get most of these new
596596
functions on Python 3.14 and older.
597597

598+
* :data:`resource.RLIM_INFINITY` is now always positive.
599+
Passing a negative integer value that corresponded to its old value
600+
(such as ``-1`` or ``-3``, depending on platform) to
601+
:func:`resource.setrlimit` and :func:`resource.prlimit` is now deprecated.
602+
(Contributed by Serhiy Storchaka in :gh:`137044`.)
603+
598604

599605
Deprecated C APIs
600606
-----------------

Lib/test/test_resource.py

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@ def test_fsize_ismax(self):
4040
# we need to test that the get/setrlimit functions properly convert
4141
# the number to a C long long and that the conversion doesn't raise
4242
# an error.
43+
self.assertGreater(resource.RLIM_INFINITY, 0)
4344
self.assertEqual(resource.RLIM_INFINITY, max)
45+
self.assertLessEqual(cur, max)
46+
resource.setrlimit(resource.RLIMIT_FSIZE, (max, max))
4447
resource.setrlimit(resource.RLIMIT_FSIZE, (cur, max))
4548

4649
@unittest.skipIf(sys.platform == "vxworks",
@@ -113,56 +116,53 @@ def test_fsize_not_too_big(self):
113116
self.addCleanup(resource.setrlimit, resource.RLIMIT_FSIZE, (cur, max))
114117

115118
def expected(cur):
116-
if resource.RLIM_INFINITY < 0:
117-
return [(cur, max), (resource.RLIM_INFINITY, max)]
118-
elif resource.RLIM_INFINITY < cur:
119-
return [(resource.RLIM_INFINITY, max)]
120-
else:
121-
return [(cur, max)]
119+
return (min(cur, resource.RLIM_INFINITY), max)
122120

123121
resource.setrlimit(resource.RLIMIT_FSIZE, (2**31-5, max))
124122
self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), (2**31-5, max))
123+
resource.setrlimit(resource.RLIMIT_FSIZE, (2**31, max))
124+
self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), expected(2**31))
125+
resource.setrlimit(resource.RLIMIT_FSIZE, (2**32-5, max))
126+
self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), expected(2**32-5))
125127

126128
try:
127129
resource.setrlimit(resource.RLIMIT_FSIZE, (2**32, max))
128130
except OverflowError:
129-
resource.setrlimit(resource.RLIMIT_FSIZE, (2**31, max))
130-
self.assertIn(resource.getrlimit(resource.RLIMIT_FSIZE), expected(2**31))
131-
resource.setrlimit(resource.RLIMIT_FSIZE, (2**32-5, max))
132-
self.assertIn(resource.getrlimit(resource.RLIMIT_FSIZE), expected(2**32-5))
131+
pass
133132
else:
134-
self.assertIn(resource.getrlimit(resource.RLIMIT_FSIZE), expected(2**32))
135-
resource.setrlimit(resource.RLIMIT_FSIZE, (2**31, max))
136-
self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), (2**31, max))
137-
resource.setrlimit(resource.RLIMIT_FSIZE, (2**32-5, max))
138-
self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), (2**32-5, max))
133+
self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), expected(2**32))
139134

140135
resource.setrlimit(resource.RLIMIT_FSIZE, (2**63-5, max))
141-
self.assertIn(resource.getrlimit(resource.RLIMIT_FSIZE), expected(2**63-5))
136+
self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), expected(2**63-5))
142137
try:
143138
resource.setrlimit(resource.RLIMIT_FSIZE, (2**63, max))
144139
except ValueError:
145140
# There is a hard limit on macOS.
146141
pass
147142
else:
148-
self.assertIn(resource.getrlimit(resource.RLIMIT_FSIZE), expected(2**63))
143+
self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), expected(2**63))
149144
resource.setrlimit(resource.RLIMIT_FSIZE, (2**64-5, max))
150-
self.assertIn(resource.getrlimit(resource.RLIMIT_FSIZE), expected(2**64-5))
145+
self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), expected(2**64-5))
151146

152147
@unittest.skipIf(sys.platform == "vxworks",
153148
"setting RLIMIT_FSIZE is not supported on VxWorks")
154149
@unittest.skipUnless(hasattr(resource, 'RLIMIT_FSIZE'), 'requires resource.RLIMIT_FSIZE')
155150
def test_fsize_negative(self):
151+
self.assertGreater(resource.RLIM_INFINITY, 0)
156152
(cur, max) = resource.getrlimit(resource.RLIMIT_FSIZE)
157153
for value in -5, -2**31, -2**32-5, -2**63, -2**64-5, -2**1000:
158154
with self.subTest(value=value):
159-
# This test assumes that the values don't map to RLIM_INFINITY,
160-
# though Posix doesn't guarantee it.
161-
self.assertNotEqual(value, resource.RLIM_INFINITY)
162-
163155
self.assertRaises(ValueError, resource.setrlimit, resource.RLIMIT_FSIZE, (value, max))
164156
self.assertRaises(ValueError, resource.setrlimit, resource.RLIMIT_FSIZE, (cur, value))
165157

158+
if resource.RLIM_INFINITY in (2**32-3, 2**32-1, 2**64-3, 2**64-1):
159+
value = (resource.RLIM_INFINITY & 0xffff) - 0x10000
160+
with self.assertWarnsRegex(DeprecationWarning, "RLIM_INFINITY"):
161+
resource.setrlimit(resource.RLIMIT_FSIZE, (value, max))
162+
with self.assertWarnsRegex(DeprecationWarning, "RLIM_INFINITY"):
163+
resource.setrlimit(resource.RLIMIT_FSIZE, (cur, value))
164+
165+
166166
@unittest.skipUnless(hasattr(resource, "getrusage"), "needs getrusage")
167167
def test_getrusage(self):
168168
self.assertRaises(TypeError, resource.getrusage)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
:data:`resource.RLIM_INFINITY` is now always a positive integer larger than
2+
any limited resource value. This simplifies comparison of the resource
3+
values. Previously, it could be negative, such as -1 or -3, depending on
4+
platform.

Modules/resource.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,14 @@ py2rlim(PyObject *obj, rlim_t *out)
164164
if (bytes < 0) {
165165
return -1;
166166
}
167-
else if (neg && (*out != RLIM_INFINITY || bytes > (Py_ssize_t)sizeof(*out))) {
167+
else if (neg && *out == RLIM_INFINITY && bytes <= (Py_ssize_t)sizeof(*out)) {
168+
if (PyErr_WarnEx(PyExc_DeprecationWarning,
169+
"Use RLIM_INFINITY instead of negative limit value.", 1))
170+
{
171+
return -1;
172+
}
173+
}
174+
else if (neg) {
168175
PyErr_SetString(PyExc_ValueError,
169176
"Cannot convert negative int");
170177
return -1;
@@ -210,9 +217,6 @@ py2rlimit(PyObject *limits, struct rlimit *rl_out)
210217
static PyObject*
211218
rlim2py(rlim_t value)
212219
{
213-
if (value == RLIM_INFINITY) {
214-
return PyLong_FromNativeBytes(&value, sizeof(value), -1);
215-
}
216220
return PyLong_FromUnsignedNativeBytes(&value, sizeof(value), -1);
217221
}
218222

0 commit comments

Comments
 (0)