1 // 2 // 3 // Copyright 2017 gRPC authors. 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 // 17 // 18 19 #if defined(GRPC_PORT_ISOLATED_RUNTIME) 20 21 // When individual tests run in an isolated runtime environment (e.g. each test 22 // runs in a separate container) the framework takes a round-robin pick of a 23 // port within certain range. There is no need to recycle ports. 24 // 25 #include <stdlib.h> 26 27 #include <grpc/support/atm.h> 28 #include <grpc/support/log.h> 29 #include <grpc/support/time.h> 30 31 #include "src/core/lib/gprpp/crash.h" 32 #include "src/core/lib/iomgr/port.h" 33 #include "test/core/util/port.h" 34 #include "test/core/util/test_config.h" 35 36 #define MIN_PORT 1025 37 #define MAX_PORT 32766 38 get_random_port_offset()39static int get_random_port_offset() { 40 srand(gpr_now(GPR_CLOCK_REALTIME).tv_nsec); 41 double rnd = static_cast<double>(rand()) / 42 (static_cast<double>(RAND_MAX) + 1.0); // values from [0,1) 43 return static_cast<int>(rnd * (MAX_PORT - MIN_PORT + 1)); 44 } 45 46 static int s_initial_offset = get_random_port_offset(); 47 static gpr_atm s_pick_counter = 0; 48 grpc_pick_unused_port_or_die_impl(void)49static int grpc_pick_unused_port_or_die_impl(void) { 50 int orig_counter_val = 51 static_cast<int>(gpr_atm_full_fetch_add(&s_pick_counter, 1)); 52 GPR_ASSERT(orig_counter_val < (MAX_PORT - MIN_PORT + 1)); 53 return MIN_PORT + 54 (s_initial_offset + orig_counter_val) % (MAX_PORT - MIN_PORT + 1); 55 } 56 isolated_pick_unused_port_or_die(void)57static int isolated_pick_unused_port_or_die(void) { 58 while (true) { 59 int port = grpc_pick_unused_port_or_die_impl(); 60 // 5985 cannot be bound on Windows RBE and results in 61 // WSA_ERROR 10013: "An attempt was made to access a socket in a way 62 // forbidden by its access permissions." 63 if (port == 5985) { 64 continue; 65 } 66 return port; 67 } 68 } 69 isolated_recycle_unused_port(int port)70static void isolated_recycle_unused_port(int port) { (void)port; } 71 72 // We don't actually use prev_fns for anything, but need to save it in order to 73 // be able to call grpc_set_pick_port_functions() to override defaults for this 74 // environment. 75 static const auto prev_fns = 76 grpc_set_pick_port_functions(grpc_pick_port_functions{ 77 isolated_pick_unused_port_or_die, isolated_recycle_unused_port}); 78 79 #endif // GRPC_PORT_ISOLATED_RUNTIME 80