Commit e394cb3d authored by Vincent Pelletier's avatar Vincent Pelletier

Work around random port double allocations.

Roughly once every 40 tries on ClusterTests.testElectionWithManyMasters I
get a "port already in use" because runner assigned two master to the same
port.
parent c5e79374
...@@ -68,6 +68,10 @@ class PortAllocator(object): ...@@ -68,6 +68,10 @@ class PortAllocator(object):
def __init__(self): def __init__(self):
self.socket_list = [] self.socket_list = []
# WKRD: this is a workaround for a weird bug allowing the same port to
# be bound more than once, causing later failure in tests, when
# different processes try to bind to the same port.
self.sock_port_set = set()
def allocate(self, address_type, local_ip): def allocate(self, address_type, local_ip):
s = socket.socket(address_type, socket.SOCK_STREAM) s = socket.socket(address_type, socket.SOCK_STREAM)
...@@ -76,17 +80,24 @@ class PortAllocator(object): ...@@ -76,17 +80,24 @@ class PortAllocator(object):
self.lock.acquire() self.lock.acquire()
self.allocator_set[self] = None self.allocator_set[self] = None
self.socket_list.append(s) self.socket_list.append(s)
sock_port_set = self.sock_port_set
while True: while True:
# Do not let the system choose the port to avoid conflicts # Do not let the system choose the port to avoid conflicts
# with other software. IOW, use a range different than: # with other software. IOW, use a range different than:
# - /proc/sys/net/ipv4/ip_local_port_range on Linux # - /proc/sys/net/ipv4/ip_local_port_range on Linux
# - what IANA recommends (49152 to 65535) # - what IANA recommends (49152 to 65535)
port = random.randint(16384, 32767)
try: try:
s.bind((local_ip, random.randint(16384, 32767))) s.bind((local_ip, port))
return s.getsockname()[1]
except socket.error, e: except socket.error, e:
if e.errno != errno.EADDRINUSE: if e.errno != errno.EADDRINUSE:
raise raise
else:
if port not in sock_port_set:
sock_port_set.add(port)
return port
neo.lib.logging.warning('Same port allocated twice: %s in %s',
port, sock_port_set)
def release(self): def release(self):
for s in self.socket_list: for s in self.socket_list:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment