I have this code that calls a libc function:
import sys
import ctypes
libc = ctypes.CDLL('libc.so.6')
class CpuSet(ctypes.Structure):
_fields_ = [('bits', ctypes.c_ulonglong * 16)]
print(ctypes.sizeof(CpuSet))
cpu_set = CpuSet()
tid = int(sys.argv[1])
rc = libc.sched_getaffinity(int(tid), ctypes.sizeof(CpuSet), ctypes.addressof(cpu_set))
print(rc)
When I run this with Python 2, I get a success rc "0", and when run it with Python 3 the printed rc is -1. The errno value is set to EFAULT, which according to the docs, means "A supplied memory address is invalid". However, ctypes.addressof(cpu_set)
seems to return a valid pointer. I printed the sizeof value, just to be safe, and it's 128 on both pythons.
# python3 /tmp/test.py 2740
128
-1
# python2 /tmp/test.py 2740
128
0
# python2 -V
Python 2.6.6
# python3 -V
Python 3.8.1
I run the code under root on both cases.
Any idea why this happens, or what further tests I can perform?
UPDATE: I ran both pythons with strace, and there is a difference:
# strace python2 /tmp/test.py 17526 2>&1 | grep sched_getaffinity
sched_getaffinity(17526, 128, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) = 8
# strace python3 /tmp/test.py 17526 2>&1 | grep sched_getaffinity
sched_getaffinity(17526, 128, 0x1da22030) = -1 EFAULT (Bad address)
It looks like python 3 passes the wrong pointer? Or maybe the struct doesn't get initialized? Still not sure.