[FIX] core: ask OS to pick CDT port

When running multiple odoo on the same machine (in order to test
multiple things concurrently, etc...) it's easily enough to start them
on 8069, 8070, 8071, ... and that *seems* to work, but then they start
walking on one another and *losing* chromes entirely, so you end up
with hundreds of chrome processes: right now with 2 Odoo running tests
my machine is at 365 Chrome processes, 550 process and 3180 threads
total (should be ~160 and ~700 with 2 chrome processes at most).

Instead, ask the OS to ask for a devtools port, then close the socket
and pass that to the child process. There's a race of sort for the
instant between closing the socket and Chrome reopening it, but:

* the window is very short
* we got a random port from the ephemeral range, it's possible
  somebody else gets it inbetween but unlikely (the 50% on a birthday
  attack is 200 for Linux's ephemeral range, it's a somewhat lower 150
  for the IANA range used by BSDs and Windows)

Sadly chrome doesn't stop if it can't bind to the port it's given.

closes odoo/odoo#42102

X-original-commit: 897ded1cb8b675024d75c6975ca171dbefdfc333
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
This commit is contained in:
Xavier Morel
2019-12-18 06:56:24 +00:00
parent f26760e2f4
commit a3371a467b
+8 -1
View File
@@ -18,6 +18,7 @@ import re
import requests
import shutil
import signal
import socket
import subprocess
import sys
import tempfile
@@ -615,7 +616,7 @@ class ChromeBrowser():
if websocket is None:
self._logger.warning("websocket-client module is not installed")
raise unittest.SkipTest("websocket-client module is not installed")
self.devtools_port = PORT + 2
self.devtools_port = None
self.ws_url = '' # WebSocketUrl
self.ws = None # websocket
self.request_id = 0
@@ -697,6 +698,12 @@ class ChromeBrowser():
def _chrome_start(self):
if self.chrome_process is not None:
return
with socket.socket() as s:
s.bind(('localhost', 0))
if hasattr(socket, 'SO_REUSEADDR'):
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
_, self.devtools_port = s.getsockname()
switches = {
'--headless': '',
'--enable-logging': 'stderr',