The following program does the following things:
- Parent process creates an inter-process shared value of data type
SHARED_DTYPE
- Parent process creates inter-process queue to pass object from child process to parent process.
- Parent process spawns child process (and waits for object to arrive via the inter-process queue).
- Child process modifies the value of the inter-process shared value
- Child process creates an object of data type
TRAVELLER_DTYPE
- Child process passes the created object via the inter-process queue.
- Parent process receives the object via the inter-process queue.
from multiprocessing import Value, Process, Queue
import ctypes
SHARED_DTYPE = ctypes.c_int
TRAVELLER_DTYPE = ctypes.c_float
shared_value = Value(SHARED_DTYPE, 0)
print('type of shared_value =', type(shared_value))
print('shared_value =', shared_value.value)
def child_proc():
try:
shared_value.value = 1
obj = TRAVELLER_DTYPE(5)
print('send into queue =', obj)
q.put(obj)
except BaseException as e:
print(e)
finally:
print('child_proc process is finished')
if __name__ == "__main__":
try:
q = Queue()
cp = Process(target=child_proc)
cp.start()
cp.join()
print('shared_value =', shared_value.value)
obj = q.get()
print('recv from queue =', obj)
except BaseException as e:
print(e)
finally:
print('__main__ process is finished')
Now, if the above program is run, it works correctly, giving the following output:
type of shared_value = <class 'multiprocessing.sharedctypes.Synchronized'>
shared_value = 0
send into queue = c_float(5.0)
child_proc process is finished
shared_value = 1
recv from queue = c_float(5.0)
__main__ process is finished
But if we change the TRAVELLER_DTYPE
to ctypes.c_int
at the top of the program, it no longer works correctly.
Sometimes, it gives the following output:
type of shared_value = <class 'multiprocessing.sharedctypes.Synchronized'>
shared_value = 0
send into queue = c_int(5)
child_proc process is finished
shared_value = 1
^C <-- Pressed ctrl-C here, was hung indefinitely.
__main__ process is finished
While other times, it gives this output:
type of shared_value = <class 'multiprocessing.sharedctypes.Synchronized'>
shared_value = 0
send into queue = c_int(5)
child_proc process is finished
Traceback (most recent call last):
File "/usr/lib/python3.8/multiprocessing/queues.py", line 239, in _feed
obj = _ForkingPickler.dumps(obj)
File "/usr/lib/python3.8/multiprocessing/reduction.py", line 51, in dumps
cls(buf, protocol).dump(obj)
File "/usr/lib/python3.8/multiprocessing/sharedctypes.py", line 129, in reduce_ctype
assert_spawning(obj)
File "/usr/lib/python3.8/multiprocessing/context.py", line 359, in assert_spawning
raise RuntimeError(
RuntimeError: c_int objects should only be shared between processes through inheritance
shared_value = 1
^C <-- Pressed ctrl-C here, was hung indefinitely.
__main__ process is finished
Why?
In general, the program works correctly if and only if SHARED_DTYPE != TRAVELLER_DTYPE
Is some explicit locking object required?
The Python multiprocessing doc page does not mention any such issue.
Searching online the error message does not give any relevant info/lead:
- Some SO question
- Some SO question: no shared value and queue together, although suggests using a
multiprocessing.Manager()
andmultiprocessing.Manager().Queue()
- A python bug report: Is there something relevant in this which can give some hints?