Skip to content

Commit ce1a1a6

Browse files
[3.13] gh-126303: Fix pickling and copying of os.sched_param objects (GH-126336) (GH-126423)
(cherry picked from commit d384050) Co-authored-by: Serhiy Storchaka <[email protected]>
1 parent 05da4ee commit ce1a1a6

File tree

5 files changed

+46
-0
lines changed

5 files changed

+46
-0
lines changed

Include/internal/pycore_typeobject.h

+1
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ extern PyObject* _PyType_GetFullyQualifiedName(PyTypeObject *type, char sep);
230230
// self->tp_flags = (self->tp_flags & ~mask) | flags;
231231
extern void _PyType_SetFlags(PyTypeObject *self, unsigned long mask,
232232
unsigned long flags);
233+
extern int _PyType_AddMethod(PyTypeObject *, PyMethodDef *);
233234

234235
// Like _PyType_SetFlags(), but apply the operation to self and any of its
235236
// subclasses without Py_TPFLAGS_IMMUTABLETYPE set.

Lib/test/test_posix.py

+21
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@
66
from test.support import warnings_helper
77
from test.support.script_helper import assert_python_ok
88

9+
import copy
910
import errno
1011
import sys
1112
import signal
1213
import time
1314
import os
1415
import platform
16+
import pickle
1517
import stat
1618
import tempfile
1719
import unittest
@@ -1317,6 +1319,25 @@ def test_get_and_set_scheduler_and_param(self):
13171319
param = posix.sched_param(sched_priority=-large)
13181320
self.assertRaises(OverflowError, posix.sched_setparam, 0, param)
13191321

1322+
@requires_sched
1323+
def test_sched_param(self):
1324+
param = posix.sched_param(1)
1325+
for proto in range(pickle.HIGHEST_PROTOCOL+1):
1326+
newparam = pickle.loads(pickle.dumps(param, proto))
1327+
self.assertEqual(newparam, param)
1328+
newparam = copy.copy(param)
1329+
self.assertIsNot(newparam, param)
1330+
self.assertEqual(newparam, param)
1331+
newparam = copy.deepcopy(param)
1332+
self.assertIsNot(newparam, param)
1333+
self.assertEqual(newparam, param)
1334+
newparam = copy.replace(param)
1335+
self.assertIsNot(newparam, param)
1336+
self.assertEqual(newparam, param)
1337+
newparam = copy.replace(param, sched_priority=0)
1338+
self.assertNotEqual(newparam, param)
1339+
self.assertEqual(newparam.sched_priority, 0)
1340+
13201341
@unittest.skipUnless(hasattr(posix, "sched_rr_get_interval"), "no function")
13211342
def test_sched_rr_get_interval(self):
13221343
try:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix pickling and copying of :class:`os.sched_param` objects.

Modules/posixmodule.c

+17
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "pycore_pystate.h" // _PyInterpreterState_GET()
2525
#include "pycore_signal.h" // Py_NSIG
2626
#include "pycore_time.h" // _PyLong_FromTime_t()
27+
#include "pycore_typeobject.h" // _PyType_AddMethod()
2728

2829
#ifdef HAVE_UNISTD_H
2930
# include <unistd.h> // symlink()
@@ -8172,6 +8173,16 @@ os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
81728173
return res;
81738174
}
81748175

8176+
static PyObject *
8177+
os_sched_param_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
8178+
{
8179+
return Py_BuildValue("(O(N))", Py_TYPE(self), PyStructSequence_GetItem(self, 0));
8180+
}
8181+
8182+
static PyMethodDef os_sched_param_reduce_method = {
8183+
"__reduce__", (PyCFunction)os_sched_param_reduce, METH_NOARGS|METH_COEXIST, NULL,
8184+
};
8185+
81758186
PyDoc_VAR(os_sched_param__doc__);
81768187

81778188
static PyStructSequence_Field sched_param_fields[] = {
@@ -17980,6 +17991,12 @@ posixmodule_exec(PyObject *m)
1798017991
return -1;
1798117992
}
1798217993
((PyTypeObject *)state->SchedParamType)->tp_new = os_sched_param;
17994+
if (_PyType_AddMethod((PyTypeObject *)state->SchedParamType,
17995+
&os_sched_param_reduce_method) < 0)
17996+
{
17997+
return -1;
17998+
}
17999+
PyType_Modified((PyTypeObject *)state->SchedParamType);
1798318000
#endif
1798418001

1798518002
/* initialize TerminalSize_info */

Objects/typeobject.c

+6
Original file line numberDiff line numberDiff line change
@@ -7332,6 +7332,12 @@ type_add_method(PyTypeObject *type, PyMethodDef *meth)
73327332
return 0;
73337333
}
73347334

7335+
int
7336+
_PyType_AddMethod(PyTypeObject *type, PyMethodDef *meth)
7337+
{
7338+
return type_add_method(type, meth);
7339+
}
7340+
73357341

73367342
/* Add the methods from tp_methods to the __dict__ in a type object */
73377343
static int

0 commit comments

Comments
 (0)