• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2015 gRPC authors.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15from __future__ import print_function
16
17from . import jobset
18
19import six.moves.urllib.request as request
20import logging
21import os
22import socket
23import subprocess
24import sys
25import tempfile
26import time
27
28# must be synchronized with test/core/utils/port_server_client.h
29_PORT_SERVER_PORT = 32766
30
31
32def start_port_server():
33    # check if a compatible port server is running
34    # if incompatible (version mismatch) ==> start a new one
35    # if not running ==> start a new one
36    # otherwise, leave it up
37    try:
38        version = int(
39            request.urlopen('http://localhost:%d/version_number' %
40                            _PORT_SERVER_PORT).read())
41        logging.info('detected port server running version %d', version)
42        running = True
43    except Exception as e:
44        logging.exception('failed to detect port server')
45        running = False
46    if running:
47        current_version = int(
48            subprocess.check_output([
49                sys.executable,  # use the same python binary as this process
50                os.path.abspath('tools/run_tests/python_utils/port_server.py'),
51                'dump_version'
52            ]))
53        logging.info('my port server is version %d', current_version)
54        running = (version >= current_version)
55        if not running:
56            logging.info('port_server version mismatch: killing the old one')
57            request.urlopen('http://localhost:%d/quitquitquit' %
58                            _PORT_SERVER_PORT).read()
59            time.sleep(1)
60    if not running:
61        fd, logfile = tempfile.mkstemp()
62        os.close(fd)
63        logging.info('starting port_server, with log file %s', logfile)
64        args = [
65            sys.executable,
66            os.path.abspath('tools/run_tests/python_utils/port_server.py'),
67            '-p',
68            '%d' % _PORT_SERVER_PORT, '-l', logfile
69        ]
70        env = dict(os.environ)
71        env['BUILD_ID'] = 'pleaseDontKillMeJenkins'
72        if jobset.platform_string() == 'windows':
73            # Working directory of port server needs to be outside of Jenkins
74            # workspace to prevent file lock issues.
75            tempdir = tempfile.mkdtemp()
76            if sys.version_info.major == 2:
77                creationflags = 0x00000008  # detached process
78            else:
79                creationflags = 0  # DETACHED_PROCESS doesn't seem to work with python3
80            port_server = subprocess.Popen(args,
81                                           env=env,
82                                           cwd=tempdir,
83                                           creationflags=creationflags,
84                                           close_fds=True)
85        else:
86            port_server = subprocess.Popen(args,
87                                           env=env,
88                                           preexec_fn=os.setsid,
89                                           close_fds=True)
90        time.sleep(1)
91        # ensure port server is up
92        waits = 0
93        while True:
94            if waits > 10:
95                logging.warning(
96                    'killing port server due to excessive start up waits')
97                port_server.kill()
98            if port_server.poll() is not None:
99                logging.error('port_server failed to start')
100                # try one final time: maybe another build managed to start one
101                time.sleep(1)
102                try:
103                    request.urlopen('http://localhost:%d/get' %
104                                    _PORT_SERVER_PORT).read()
105                    logging.info(
106                        'last ditch attempt to contact port server succeeded')
107                    break
108                except:
109                    logging.exception(
110                        'final attempt to contact port server failed')
111                    port_log = open(logfile, 'r').read()
112                    print(port_log)
113                    sys.exit(1)
114            try:
115                port_server_url = 'http://localhost:%d/get' % _PORT_SERVER_PORT
116                request.urlopen(port_server_url).read()
117                logging.info('port server is up and ready')
118                break
119            except socket.timeout:
120                logging.exception('while waiting for port_server')
121                time.sleep(1)
122                waits += 1
123            except IOError:
124                logging.exception('while waiting for port_server')
125                time.sleep(1)
126                waits += 1
127            except:
128                logging.exception(
129                    'error while contacting port server at "%s".'
130                    'Will try killing it.', port_server_url)
131                port_server.kill()
132                raise
133