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