Skip to content

Commit d384050

Browse files
gh-126303: Fix pickling and copying of os.sched_param objects (GH-126336)
1 parent d960226 commit d384050

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
@@ -243,6 +243,7 @@ extern PyObject* _PyType_GetFullyQualifiedName(PyTypeObject *type, char sep);
243243
// self->tp_flags = (self->tp_flags & ~mask) | flags;
244244
extern void _PyType_SetFlags(PyTypeObject *self, unsigned long mask,
245245
unsigned long flags);
246+
extern int _PyType_AddMethod(PyTypeObject *, PyMethodDef *);
246247

247248
// Like _PyType_SetFlags(), but apply the operation to self and any of its
248249
// 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()
@@ -8210,6 +8211,16 @@ os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
82108211
return res;
82118212
}
82128213

8214+
static PyObject *
8215+
os_sched_param_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
8216+
{
8217+
return Py_BuildValue("(O(N))", Py_TYPE(self), PyStructSequence_GetItem(self, 0));
8218+
}
8219+
8220+
static PyMethodDef os_sched_param_reduce_method = {
8221+
"__reduce__", (PyCFunction)os_sched_param_reduce, METH_NOARGS|METH_COEXIST, NULL,
8222+
};
8223+
82138224
PyDoc_VAR(os_sched_param__doc__);
82148225

82158226
static PyStructSequence_Field sched_param_fields[] = {
@@ -18033,6 +18044,12 @@ posixmodule_exec(PyObject *m)
1803318044
return -1;
1803418045
}
1803518046
((PyTypeObject *)state->SchedParamType)->tp_new = os_sched_param;
18047+
if (_PyType_AddMethod((PyTypeObject *)state->SchedParamType,
18048+
&os_sched_param_reduce_method) < 0)
18049+
{
18050+
return -1;
18051+
}
18052+
PyType_Modified((PyTypeObject *)state->SchedParamType);
1803618053
#endif
1803718054

1803818055
/* initialize TerminalSize_info */

Objects/typeobject.c

+6
Original file line numberDiff line numberDiff line change
@@ -7656,6 +7656,12 @@ type_add_method(PyTypeObject *type, PyMethodDef *meth)
76567656
return 0;
76577657
}
76587658

7659+
int
7660+
_PyType_AddMethod(PyTypeObject *type, PyMethodDef *meth)
7661+
{
7662+
return type_add_method(type, meth);
7663+
}
7664+
76597665

76607666
/* Add the methods from tp_methods to the __dict__ in a type object */
76617667
static int

0 commit comments

Comments
 (0)