Skip to content

Commit

Permalink
Use exact IPv4/IPv6 address in test_run:cmd()
Browse files Browse the repository at this point in the history
When test-run's inspector listens on a IPv4 port and some other process
listens on a IPv6 port of the same number, test_run:cmd() could connect
to this process rather then the inspector, because 'localhost' hostname
was used to connect.

Now test-run passes actual IP address of the inspector via an
environment variable and test_run:cmd() uses it to avoid the ambiguity
that is described above.

The problem was found during many parallel runs of app/socket.test.lua
test from tarantool, see case 4 in [1] (untitled, see right under case
3). This test starts many TCP servers and in rare cases a server port
may be the same as inspector's one.

There are two details that increase probability of the problem:

* It seems test-run's inspector always listens on IPv4 address, because
  it is configured with 'localhost' hostname and
  gevent.server.StreamServer implementation always chooses IPv4 for
  'localhost' (see [2], _parse_address() function).

* socket.tcp_connect() typically tries to connect to an IPv6 address
  first and only then to an IPv4 one, because getaddrinfo() returns
  addresses in this order according to RFC 3484 (see [3], section 2.1
  'Policy table'). This however can be configured in /etc/gai.conf.

[1]: https://lists.tarantool.org/pipermail/tarantool-patches/2019-December/013321.html
[2]: https://github.com/gevent/gevent/blob/ba3b15de7eb568fa09fdf1a9d28241288163ba67/src/gevent/baseserver.py#L406-L409
[3]: https://tools.ietf.org/rfc/rfc3484.txt
  • Loading branch information
Totktonada committed Dec 31, 2019
1 parent dc2cdb5 commit b23eeb7
Show file tree
Hide file tree
Showing 2 changed files with 6 additions and 4 deletions.
6 changes: 4 additions & 2 deletions lib/inspector.py
Expand Up @@ -55,10 +55,12 @@ def __init__(self, host, port):

def start(self):
super(TarantoolInspector, self).start()
os.environ['INSPECTOR'] = str(self.server_port)
os.environ['INSPECTOR_HOST'] = str(self.server_host)
os.environ['INSPECTOR_PORT'] = str(self.server_port)

def stop(self):
del os.environ['INSPECTOR']
del os.environ['INSPECTOR_HOST']
del os.environ['INSPECTOR_PORT']

def set_parser(self, parser):
self.parser = parser
Expand Down
4 changes: 2 additions & 2 deletions test_run.lua
Expand Up @@ -458,8 +458,8 @@ local inspector_methods = {
local function inspector_new(host, port)
local inspector = {}

inspector.host = host or 'localhost'
inspector.port = port or tonumber(os.getenv('INSPECTOR'))
inspector.host = host or os.getenv('INSPECTOR_HOST') or 'localhost'
inspector.port = port or tonumber(os.getenv('INSPECTOR_PORT'))
if inspector.port == nil then
error('Inspector not started')
end
Expand Down

0 comments on commit b23eeb7

Please sign in to comment.