17f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 27f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# Module to allow connection and socket objects to be transferred 37f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# between processes 47f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 57f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# multiprocessing/reduction.py 67f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 779af245fb24a3608c341410ab9c782ce930401feR. David Murray# Copyright (c) 2006-2008, R Oudkerk 879af245fb24a3608c341410ab9c782ce930401feR. David Murray# All rights reserved. 979af245fb24a3608c341410ab9c782ce930401feR. David Murray# 1079af245fb24a3608c341410ab9c782ce930401feR. David Murray# Redistribution and use in source and binary forms, with or without 1179af245fb24a3608c341410ab9c782ce930401feR. David Murray# modification, are permitted provided that the following conditions 1279af245fb24a3608c341410ab9c782ce930401feR. David Murray# are met: 1379af245fb24a3608c341410ab9c782ce930401feR. David Murray# 1479af245fb24a3608c341410ab9c782ce930401feR. David Murray# 1. Redistributions of source code must retain the above copyright 1579af245fb24a3608c341410ab9c782ce930401feR. David Murray# notice, this list of conditions and the following disclaimer. 1679af245fb24a3608c341410ab9c782ce930401feR. David Murray# 2. Redistributions in binary form must reproduce the above copyright 1779af245fb24a3608c341410ab9c782ce930401feR. David Murray# notice, this list of conditions and the following disclaimer in the 1879af245fb24a3608c341410ab9c782ce930401feR. David Murray# documentation and/or other materials provided with the distribution. 1979af245fb24a3608c341410ab9c782ce930401feR. David Murray# 3. Neither the name of author nor the names of any contributors may be 2079af245fb24a3608c341410ab9c782ce930401feR. David Murray# used to endorse or promote products derived from this software 2179af245fb24a3608c341410ab9c782ce930401feR. David Murray# without specific prior written permission. 2279af245fb24a3608c341410ab9c782ce930401feR. David Murray# 2379af245fb24a3608c341410ab9c782ce930401feR. David Murray# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND 2479af245fb24a3608c341410ab9c782ce930401feR. David Murray# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2579af245fb24a3608c341410ab9c782ce930401feR. David Murray# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2679af245fb24a3608c341410ab9c782ce930401feR. David Murray# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2779af245fb24a3608c341410ab9c782ce930401feR. David Murray# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2879af245fb24a3608c341410ab9c782ce930401feR. David Murray# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2979af245fb24a3608c341410ab9c782ce930401feR. David Murray# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3079af245fb24a3608c341410ab9c782ce930401feR. David Murray# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3179af245fb24a3608c341410ab9c782ce930401feR. David Murray# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3279af245fb24a3608c341410ab9c782ce930401feR. David Murray# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3379af245fb24a3608c341410ab9c782ce930401feR. David Murray# SUCH DAMAGE. 347f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 357f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 367f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson__all__ = [] 377f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 387f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersonimport os 397f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersonimport sys 407f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersonimport socket 417f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersonimport threading 427f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 437f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersonimport _multiprocessing 447f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersonfrom multiprocessing import current_process 4513e9d582fd55c3f680cbe9d3d4c219722a484d92Jesse Nollerfrom multiprocessing.forking import Popen, duplicate, close, ForkingPickler 467f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersonfrom multiprocessing.util import register_after_fork, debug, sub_debug 477f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersonfrom multiprocessing.connection import Client, Listener 487f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 497f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 507f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 517f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 527f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 537f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 547f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersonif not(sys.platform == 'win32' or hasattr(_multiprocessing, 'recvfd')): 557f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson raise ImportError('pickling of connections not supported') 567f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 577f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 587f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# Platform specific definitions 597f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 607f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 617f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersonif sys.platform == 'win32': 627f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson import _subprocess 632f8c8f47c740cadee8c16e5e07657e4657f905ecJesse Noller from _multiprocessing import win32 647f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 657f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson def send_handle(conn, handle, destination_pid): 667f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson process_handle = win32.OpenProcess( 677f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson win32.PROCESS_ALL_ACCESS, False, destination_pid 687f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ) 697f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson try: 707f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson new_handle = duplicate(handle, process_handle) 717f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson conn.send(new_handle) 727f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson finally: 737f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson close(process_handle) 747f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 757f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson def recv_handle(conn): 767f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson return conn.recv() 777f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 787f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersonelse: 797f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson def send_handle(conn, handle, destination_pid): 807f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson _multiprocessing.sendfd(conn.fileno(), handle) 817f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 827f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson def recv_handle(conn): 837f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson return _multiprocessing.recvfd(conn.fileno()) 847f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 857f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 867f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# Support for a per-process server thread which caches pickled handles 877f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 887f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 897f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson_cache = set() 907f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 917f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersondef _reset(obj): 927f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson global _lock, _listener, _cache 937f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson for h in _cache: 947f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson close(h) 957f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson _cache.clear() 967f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson _lock = threading.Lock() 977f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson _listener = None 987f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 997f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson_reset(None) 1007f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersonregister_after_fork(_reset, _reset) 1017f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1027f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersondef _get_listener(): 1037f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson global _listener 1047f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1057f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson if _listener is None: 1067f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson _lock.acquire() 1077f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson try: 1087f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson if _listener is None: 1097f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson debug('starting listener and thread for sending handles') 1105bc9f4c09c99eb701dbee83fb9e26eed558e474fJesse Noller _listener = Listener(authkey=current_process().authkey) 1117f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson t = threading.Thread(target=_serve) 1125bc9f4c09c99eb701dbee83fb9e26eed558e474fJesse Noller t.daemon = True 1137f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson t.start() 1147f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson finally: 1157f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson _lock.release() 1167f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1177f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson return _listener 1187f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1197f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersondef _serve(): 1207f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson from .util import is_exiting, sub_warning 1217f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1227f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson while 1: 1237f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson try: 1247f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson conn = _listener.accept() 1257f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson handle_wanted, destination_pid = conn.recv() 1267f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson _cache.remove(handle_wanted) 1277f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson send_handle(conn, handle_wanted, destination_pid) 1287f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson close(handle_wanted) 1297f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson conn.close() 1307f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson except: 1317f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson if not is_exiting(): 1327f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson import traceback 1337f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson sub_warning( 1347f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 'thread for sharing handles raised exception :\n' + 1357f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson '-'*79 + '\n' + traceback.format_exc() + '-'*79 1367f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ) 1377f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1387f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 1397f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# Functions to be used for pickling/unpickling objects with handles 1407f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 1417f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1427f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersondef reduce_handle(handle): 1437f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson if Popen.thread_is_spawning(): 1447f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson return (None, Popen.duplicate_for_child(handle), True) 1457f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson dup_handle = duplicate(handle) 1467f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson _cache.add(dup_handle) 1477f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson sub_debug('reducing handle %d', handle) 1487f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson return (_get_listener().address, dup_handle, False) 1497f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1507f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersondef rebuild_handle(pickled_data): 1517f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson address, handle, inherited = pickled_data 1527f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson if inherited: 1537f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson return handle 1547f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson sub_debug('rebuilding handle %d', handle) 1555bc9f4c09c99eb701dbee83fb9e26eed558e474fJesse Noller conn = Client(address, authkey=current_process().authkey) 1567f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson conn.send((handle, os.getpid())) 1577f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson new_handle = recv_handle(conn) 1587f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson conn.close() 1597f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson return new_handle 1607f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1617f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 16213e9d582fd55c3f680cbe9d3d4c219722a484d92Jesse Noller# Register `_multiprocessing.Connection` with `ForkingPickler` 1637f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 1647f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1657f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersondef reduce_connection(conn): 1667f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson rh = reduce_handle(conn.fileno()) 1677f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson return rebuild_connection, (rh, conn.readable, conn.writable) 1687f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1697f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersondef rebuild_connection(reduced_handle, readable, writable): 1707f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson handle = rebuild_handle(reduced_handle) 1717f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson return _multiprocessing.Connection( 1727f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson handle, readable=readable, writable=writable 1737f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ) 1747f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 17513e9d582fd55c3f680cbe9d3d4c219722a484d92Jesse NollerForkingPickler.register(_multiprocessing.Connection, reduce_connection) 1767f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1777f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 17813e9d582fd55c3f680cbe9d3d4c219722a484d92Jesse Noller# Register `socket.socket` with `ForkingPickler` 1797f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 1807f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1817f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersondef fromfd(fd, family, type_, proto=0): 1827f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson s = socket.fromfd(fd, family, type_, proto) 1837f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson if s.__class__ is not socket.socket: 1847f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson s = socket.socket(_sock=s) 1857f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson return s 1867f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1877f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersondef reduce_socket(s): 1887f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson reduced_handle = reduce_handle(s.fileno()) 1897f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson return rebuild_socket, (reduced_handle, s.family, s.type, s.proto) 1907f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1917f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersondef rebuild_socket(reduced_handle, family, type_, proto): 1927f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson fd = rebuild_handle(reduced_handle) 1937f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson _sock = fromfd(fd, family, type_, proto) 1947f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson close(fd) 1957f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson return _sock 1967f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 19713e9d582fd55c3f680cbe9d3d4c219722a484d92Jesse NollerForkingPickler.register(socket.socket, reduce_socket) 1987f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1997f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 20013e9d582fd55c3f680cbe9d3d4c219722a484d92Jesse Noller# Register `_multiprocessing.PipeConnection` with `ForkingPickler` 2017f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 2027f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 2037f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersonif sys.platform == 'win32': 2047f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 2057f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson def reduce_pipe_connection(conn): 2067f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson rh = reduce_handle(conn.fileno()) 2077f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson return rebuild_pipe_connection, (rh, conn.readable, conn.writable) 2087f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 2097f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson def rebuild_pipe_connection(reduced_handle, readable, writable): 2107f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson handle = rebuild_handle(reduced_handle) 2117f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson return _multiprocessing.PipeConnection( 2127f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson handle, readable=readable, writable=writable 2137f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ) 2147f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 21513e9d582fd55c3f680cbe9d3d4c219722a484d92Jesse Noller ForkingPickler.register(_multiprocessing.PipeConnection, reduce_pipe_connection) 216