mirror of
https://github.com/python/cpython.git
synced 2025-11-24 20:30:18 +00:00
Issue #14310: inter-process socket duplication for windows
This commit is contained in:
parent
0f9eec19ee
commit
10f383a937
5 changed files with 208 additions and 8 deletions
|
|
@ -26,6 +26,10 @@ try:
|
|||
import fcntl
|
||||
except ImportError:
|
||||
fcntl = False
|
||||
try:
|
||||
import multiprocessing
|
||||
except ImportError:
|
||||
multiprocessing = False
|
||||
|
||||
HOST = support.HOST
|
||||
MSG = 'Michael Gilfix was here\u1234\r\n'.encode('utf-8') ## test unicode string and carriage return
|
||||
|
|
@ -4643,6 +4647,106 @@ class NonblockConstantTest(unittest.TestCase):
|
|||
socket.setdefaulttimeout(t)
|
||||
|
||||
|
||||
@unittest.skipUnless(os.name == "nt", "Windows specific")
|
||||
@unittest.skipUnless(multiprocessing, "need multiprocessing")
|
||||
class TestSocketSharing(SocketTCPTest):
|
||||
# This must be classmethod and not staticmethod or multiprocessing
|
||||
# won't be able to bootstrap it.
|
||||
@classmethod
|
||||
def remoteProcessServer(cls, q):
|
||||
# Recreate socket from shared data
|
||||
sdata = q.get()
|
||||
message = q.get()
|
||||
|
||||
s = socket.fromshare(sdata)
|
||||
s2, c = s.accept()
|
||||
|
||||
# Send the message
|
||||
s2.sendall(message)
|
||||
s2.close()
|
||||
s.close()
|
||||
|
||||
def testShare(self):
|
||||
# Transfer the listening server socket to another process
|
||||
# and service it from there.
|
||||
|
||||
# Create process:
|
||||
q = multiprocessing.Queue()
|
||||
p = multiprocessing.Process(target=self.remoteProcessServer, args=(q,))
|
||||
p.start()
|
||||
|
||||
# Get the shared socket data
|
||||
data = self.serv.share(p.pid)
|
||||
|
||||
# Pass the shared socket to the other process
|
||||
addr = self.serv.getsockname()
|
||||
self.serv.close()
|
||||
q.put(data)
|
||||
|
||||
# The data that the server will send us
|
||||
message = b"slapmahfro"
|
||||
q.put(message)
|
||||
|
||||
# Connect
|
||||
s = socket.create_connection(addr)
|
||||
# listen for the data
|
||||
m = []
|
||||
while True:
|
||||
data = s.recv(100)
|
||||
if not data:
|
||||
break
|
||||
m.append(data)
|
||||
s.close()
|
||||
received = b"".join(m)
|
||||
self.assertEqual(received, message)
|
||||
p.join()
|
||||
|
||||
def testShareLength(self):
|
||||
data = self.serv.share(os.getpid())
|
||||
self.assertRaises(ValueError, socket.fromshare, data[:-1])
|
||||
self.assertRaises(ValueError, socket.fromshare, data+b"foo")
|
||||
|
||||
def compareSockets(self, org, other):
|
||||
# socket sharing is expected to work only for blocking socket
|
||||
# since the internal python timout value isn't transfered.
|
||||
self.assertEqual(org.gettimeout(), None)
|
||||
self.assertEqual(org.gettimeout(), other.gettimeout())
|
||||
|
||||
self.assertEqual(org.family, other.family)
|
||||
self.assertEqual(org.type, other.type)
|
||||
# If the user specified "0" for proto, then
|
||||
# internally windows will have picked the correct value.
|
||||
# Python introspection on the socket however will still return
|
||||
# 0. For the shared socket, the python value is recreated
|
||||
# from the actual value, so it may not compare correctly.
|
||||
if org.proto != 0:
|
||||
self.assertEqual(org.proto, other.proto)
|
||||
|
||||
def testShareLocal(self):
|
||||
data = self.serv.share(os.getpid())
|
||||
s = socket.fromshare(data)
|
||||
try:
|
||||
self.compareSockets(self.serv, s)
|
||||
finally:
|
||||
s.close()
|
||||
|
||||
def testTypes(self):
|
||||
families = [socket.AF_INET, socket.AF_INET6]
|
||||
types = [socket.SOCK_STREAM, socket.SOCK_DGRAM]
|
||||
for f in families:
|
||||
for t in types:
|
||||
source = socket.socket(f, t)
|
||||
try:
|
||||
data = source.share(os.getpid())
|
||||
shared = socket.fromshare(data)
|
||||
try:
|
||||
self.compareSockets(source, shared)
|
||||
finally:
|
||||
shared.close()
|
||||
finally:
|
||||
source.close()
|
||||
|
||||
|
||||
def test_main():
|
||||
tests = [GeneralModuleTests, BasicTCPTest, TCPCloserTest, TCPTimeoutTest,
|
||||
TestExceptions, BufferIOTest, BasicTCPTest2, BasicUDPTest, UDPTimeoutTest ]
|
||||
|
|
@ -4699,6 +4803,7 @@ def test_main():
|
|||
# These are slow when setitimer() is not available
|
||||
InterruptedRecvTimeoutTest,
|
||||
InterruptedSendTimeoutTest,
|
||||
TestSocketSharing,
|
||||
])
|
||||
|
||||
thread_info = support.threading_setup()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue