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