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 17import logging 18import os 19import socket 20import subprocess 21import sys 22import tempfile 23import time 24 25import six.moves.urllib.request as request 26 27sys.path.append(os.path.dirname(os.path.abspath(__file__))) 28import jobset 29 30# must be synchronized with test/core/test_util/port_server_client.h 31_PORT_SERVER_PORT = 32766 32 33 34def start_port_server(verbose=False): 35 # check if a compatible port server is running 36 # if incompatible (version mismatch) ==> start a new one 37 # if not running ==> start a new one 38 # otherwise, leave it up 39 try: 40 version = int( 41 request.urlopen( 42 "http://localhost:%d/version_number" % _PORT_SERVER_PORT 43 ).read() 44 ) 45 logging.info("detected port server running version %d", version) 46 running = True 47 except Exception as e: 48 if verbose: 49 logging.exception("failed to detect port server") 50 running = False 51 if running: 52 current_version = int( 53 subprocess.check_output( 54 [ 55 sys.executable, # use the same python binary as this process 56 os.path.abspath( 57 "tools/run_tests/python_utils/port_server.py" 58 ), 59 "dump_version", 60 ] 61 ).decode() 62 ) 63 logging.info("my port server is version %d", current_version) 64 running = version >= current_version 65 if not running: 66 logging.info("port_server version mismatch: killing the old one") 67 request.urlopen( 68 "http://localhost:%d/quitquitquit" % _PORT_SERVER_PORT 69 ).read() 70 time.sleep(1) 71 if not running: 72 fd, logfile = tempfile.mkstemp() 73 os.close(fd) 74 logging.info("starting port_server, with log file %s", logfile) 75 args = [ 76 sys.executable, 77 os.path.abspath("tools/run_tests/python_utils/port_server.py"), 78 "-p", 79 "%d" % _PORT_SERVER_PORT, 80 "-l", 81 logfile, 82 ] 83 env = dict(os.environ) 84 env["BUILD_ID"] = "pleaseDontKillMeJenkins" 85 if jobset.platform_string() == "windows": 86 # Working directory of port server needs to be outside of Jenkins 87 # workspace to prevent file lock issues. 88 tempdir = tempfile.mkdtemp() 89 if sys.version_info.major == 2: 90 creationflags = 0x00000008 # detached process 91 else: 92 creationflags = ( 93 0 # DETACHED_PROCESS doesn't seem to work with python3 94 ) 95 port_server = subprocess.Popen( 96 args, 97 env=env, 98 cwd=tempdir, 99 creationflags=creationflags, 100 close_fds=True, 101 ) 102 else: 103 port_server = subprocess.Popen( 104 args, env=env, preexec_fn=os.setsid, close_fds=True 105 ) 106 time.sleep(1) 107 # ensure port server is up 108 waits = 0 109 while True: 110 if waits > 10: 111 logging.warning( 112 "killing port server due to excessive start up waits" 113 ) 114 port_server.kill() 115 if port_server.poll() is not None: 116 logging.error("port_server failed to start") 117 # try one final time: maybe another build managed to start one 118 time.sleep(1) 119 try: 120 request.urlopen( 121 "http://localhost:%d/get" % _PORT_SERVER_PORT 122 ).read() 123 logging.info( 124 "last ditch attempt to contact port server succeeded" 125 ) 126 break 127 except: 128 logging.exception( 129 "final attempt to contact port server failed" 130 ) 131 port_log = open(logfile, "r").read() 132 print(port_log) 133 sys.exit(1) 134 try: 135 port_server_url = "http://localhost:%d/get" % _PORT_SERVER_PORT 136 request.urlopen(port_server_url).read() 137 logging.info("port server is up and ready") 138 break 139 except socket.timeout: 140 logging.exception("while waiting for port_server") 141 time.sleep(1) 142 waits += 1 143 except IOError: 144 logging.exception("while waiting for port_server") 145 time.sleep(1) 146 waits += 1 147 except: 148 logging.exception( 149 ( 150 'error while contacting port server at "%s".' 151 "Will try killing it." 152 ), 153 port_server_url, 154 ) 155 port_server.kill() 156 raise 157