diff --git a/Makefile b/Makefile index 278824a59aafcb4e0fe9299c8ef7c5ed9bf7a58a..f6821ec000640d1d3f720b1e0fbaf2f0b67a4f4c 100644 --- a/Makefile +++ b/Makefile @@ -257,7 +257,7 @@ HAS_SYSTEM_ZLIB = false HAS_SYSTEM_PROTOBUF = false endif -HAS_PROTOC = $(shell $(PROTOC_CMD) && echo true || echo false) +HAS_PROTOC = $(shell $(PROTOC_CMD) > /dev/null && echo true || echo false) ifeq ($(HAS_PROTOC),true) HAS_VALID_PROTOC = $(shell $(PROTOC_CHECK_CMD) 2> /dev/null && echo true || echo false) else @@ -2081,7 +2081,7 @@ install-certs: etc/roots.pem $(Q) $(INSTALL) etc/roots.pem $(prefix)/share/grpc/roots.pem verify-install: -ifeq ($(SYSTEM_OK),true) +ifeq ($(INSTALL_OK),true) @echo "Your system looks ready to go." @echo else diff --git a/include/grpc++/server.h b/include/grpc++/server.h index 26d18d1bbe4be0c49600d1268eeb2c2d323e6646..429c0ff3cf8579b9f70b3c48ca87f85838780761 100644 --- a/include/grpc++/server.h +++ b/include/grpc++/server.h @@ -69,6 +69,11 @@ class Server final : private CallHook, // Shutdown the server, block until all rpc processing finishes. void Shutdown(); + // Block waiting for all work to complete (the server must either + // be shutting down or some other thread must call Shutdown for this + // function to ever return) + void Wait(); + private: friend class ServerBuilder; diff --git a/include/grpc/support/alloc.h b/include/grpc/support/alloc.h index c7580655761e1a51e0788c52a68904735c68d565..09ea97565b22931a17d82462d7edebde363276eb 100644 --- a/include/grpc/support/alloc.h +++ b/include/grpc/support/alloc.h @@ -46,8 +46,8 @@ void *gpr_malloc(size_t size); void gpr_free(void *ptr); /* realloc, never returns NULL */ void *gpr_realloc(void *p, size_t size); -/* aligned malloc, never returns NULL, alignment must be power of 2 */ -void *gpr_malloc_aligned(size_t size, size_t alignment); +/* aligned malloc, never returns NULL, will align to 1 << alignment_log */ +void *gpr_malloc_aligned(size_t size, size_t alignment_log); /* free memory allocated by gpr_malloc_aligned */ void gpr_free_aligned(void *ptr); diff --git a/include/grpc/support/atm_win32.h b/include/grpc/support/atm_win32.h index acacf12013ce8af949df318463a944def1bdd8ec..9bb1cfec357c240a5ad0064f401c23f7ae080004 100644 --- a/include/grpc/support/atm_win32.h +++ b/include/grpc/support/atm_win32.h @@ -93,11 +93,13 @@ static __inline gpr_atm gpr_atm_no_barrier_fetch_add(gpr_atm *p, static __inline gpr_atm gpr_atm_full_fetch_add(gpr_atm *p, gpr_atm delta) { /* Use a CAS operation to get pointer-sized fetch and add */ gpr_atm old; +#ifdef GPR_ARCH_64 do { old = *p; -#ifdef GPR_ARCH_64 } while (old != (gpr_atm)InterlockedCompareExchange64(p, old + delta, old)); #else + do { + old = *p; } while (old != (gpr_atm)InterlockedCompareExchange(p, old + delta, old)); #endif return old; diff --git a/include/grpc/support/port_platform.h b/include/grpc/support/port_platform.h index 27efa2944855926728c9977d9e79e1a8584d5dea..0a651757bc0626b46401f543181abf68bb0a5879 100644 --- a/include/grpc/support/port_platform.h +++ b/include/grpc/support/port_platform.h @@ -147,16 +147,18 @@ #include <stdint.h> /* Cache line alignment */ -#ifndef GPR_CACHELINE_SIZE +#ifndef GPR_CACHELINE_SIZE_LOG #if defined(__i386__) || defined(__x86_64__) -#define GPR_CACHELINE_SIZE 64 +#define GPR_CACHELINE_SIZE_LOG 6 #endif -#ifndef GPR_CACHELINE_SIZE +#ifndef GPR_CACHELINE_SIZE_LOG /* A reasonable default guess. Note that overestimates tend to waste more space, while underestimates tend to waste more time. */ -#define GPR_CACHELINE_SIZE 64 -#endif /* GPR_CACHELINE_SIZE */ -#endif /* GPR_CACHELINE_SIZE */ +#define GPR_CACHELINE_SIZE_LOG 6 +#endif /* GPR_CACHELINE_SIZE_LOG */ +#endif /* GPR_CACHELINE_SIZE_LOG */ + +#define GPR_CACHELINE_SIZE (1 << GPR_CACHELINE_SIZE_LOG) /* scrub GCC_ATOMIC if it's not available on this compiler */ #if defined(GPR_GCC_ATOMIC) && !defined(__ATOMIC_RELAXED) diff --git a/include/grpc/support/slice.h b/include/grpc/support/slice.h index 261e3baabee0bd1b26d1b98ba9201cccc1c8f24c..8a2129028fdd39a605c37bd8895d43de60d436f4 100644 --- a/include/grpc/support/slice.h +++ b/include/grpc/support/slice.h @@ -165,7 +165,9 @@ gpr_slice gpr_slice_split_head(gpr_slice *s, size_t split); gpr_slice gpr_empty_slice(void); -/* Returns <0 if a < b, ==0 if a == b, >0 if a > b */ +/* Returns <0 if a < b, ==0 if a == b, >0 if a > b + The order is arbitrary, and is not guaranteed to be stable across different + versions of the API. */ int gpr_slice_cmp(gpr_slice a, gpr_slice b); int gpr_slice_str_cmp(gpr_slice a, const char *b); diff --git a/src/core/compression/message_compress.c b/src/core/compression/message_compress.c index 9b8100a3d6c2ae66e2297025296b9fc8fa598e3b..7856f40dd18c22d679318256d5f6ee7350e095b7 100644 --- a/src/core/compression/message_compress.c +++ b/src/core/compression/message_compress.c @@ -48,7 +48,6 @@ static int zlib_body(z_stream *zs, gpr_slice_buffer *input, int r; int flush; size_t i; - size_t output_bytes = 0; gpr_slice outbuf = gpr_slice_malloc(OUTPUT_BLOCK_SIZE); zs->avail_out = GPR_SLICE_LENGTH(outbuf); @@ -60,7 +59,6 @@ static int zlib_body(z_stream *zs, gpr_slice_buffer *input, zs->next_in = GPR_SLICE_START_PTR(input->slices[i]); do { if (zs->avail_out == 0) { - output_bytes += GPR_SLICE_LENGTH(outbuf); gpr_slice_buffer_add_indexed(output, outbuf); outbuf = gpr_slice_malloc(OUTPUT_BLOCK_SIZE); zs->avail_out = GPR_SLICE_LENGTH(outbuf); @@ -80,7 +78,6 @@ static int zlib_body(z_stream *zs, gpr_slice_buffer *input, GPR_ASSERT(outbuf.refcount); outbuf.data.refcounted.length -= zs->avail_out; - output_bytes += GPR_SLICE_LENGTH(outbuf); gpr_slice_buffer_add_indexed(output, outbuf); return 1; diff --git a/src/core/statistics/census_log.c b/src/core/statistics/census_log.c index 24e46876d25a0613a9bb18862d1dcbdc321567c6..ec56ce38df7a6af9a90fce5c3f0804d2c96ad863 100644 --- a/src/core/statistics/census_log.c +++ b/src/core/statistics/census_log.c @@ -475,11 +475,11 @@ void census_log_initialize(size_t size_in_mb, int discard_old_records) { g_log.block_being_read = NULL; gpr_atm_rel_store(&g_log.is_full, 0); g_log.core_local_blocks = (cl_core_local_block*)gpr_malloc_aligned( - g_log.num_cores * sizeof(cl_core_local_block), GPR_CACHELINE_SIZE); + g_log.num_cores * sizeof(cl_core_local_block), GPR_CACHELINE_SIZE_LOG); memset(g_log.core_local_blocks, 0, g_log.num_cores * sizeof(cl_core_local_block)); g_log.blocks = (cl_block*)gpr_malloc_aligned( - g_log.num_blocks * sizeof(cl_block), GPR_CACHELINE_SIZE); + g_log.num_blocks * sizeof(cl_block), GPR_CACHELINE_SIZE_LOG); memset(g_log.blocks, 0, g_log.num_blocks * sizeof(cl_block)); g_log.buffer = gpr_malloc(g_log.num_blocks * CENSUS_LOG_MAX_RECORD_SIZE); memset(g_log.buffer, 0, g_log.num_blocks * CENSUS_LOG_MAX_RECORD_SIZE); diff --git a/src/core/support/alloc.c b/src/core/support/alloc.c index 44f343b4f400445d1f39dd203069dd18b04c4043..a19a0141d45fe8ffa959b2aa60257ecd87a0463f 100644 --- a/src/core/support/alloc.c +++ b/src/core/support/alloc.c @@ -54,7 +54,8 @@ void *gpr_realloc(void *p, size_t size) { return p; } -void *gpr_malloc_aligned(size_t size, size_t alignment) { +void *gpr_malloc_aligned(size_t size, size_t alignment_log) { + size_t alignment = 1 << alignment_log; size_t extra = alignment - 1 + sizeof(void *); void *p = gpr_malloc(size + extra); void **ret = (void **)(((gpr_uintptr)p + extra) & ~(alignment - 1)); diff --git a/src/core/support/cpu_linux.c b/src/core/support/cpu_linux.c index ef6bf9ca09641146485c9144ff6293aedbda7767..37e840d4cf9ff0b572367d674804ae77c8b39ff2 100644 --- a/src/core/support/cpu_linux.c +++ b/src/core/support/cpu_linux.c @@ -39,25 +39,28 @@ #ifdef GPR_CPU_LINUX -#include <grpc/support/cpu.h> - #include <sched.h> #include <errno.h> #include <unistd.h> #include <string.h> +#include <grpc/support/cpu.h> #include <grpc/support/log.h> +#include <grpc/support/sync.h> -unsigned gpr_cpu_num_cores(void) { - static int ncpus = 0; - /* FIXME: !threadsafe */ - if (ncpus == 0) { - ncpus = sysconf(_SC_NPROCESSORS_ONLN); - if (ncpus < 1) { - gpr_log(GPR_ERROR, "Cannot determine number of CPUs: assuming 1"); - ncpus = 1; - } +static int ncpus = 0; + +static void init_num_cpus() { + ncpus = sysconf(_SC_NPROCESSORS_ONLN); + if (ncpus < 1) { + gpr_log(GPR_ERROR, "Cannot determine number of CPUs: assuming 1"); + ncpus = 1; } +} + +unsigned gpr_cpu_num_cores(void) { + static gpr_once once = GPR_ONCE_INIT; + gpr_once_init(&once, init_num_cpus); return ncpus; } diff --git a/src/core/support/cpu_posix.c b/src/core/support/cpu_posix.c index 91ce80c364e788f9d1658be8eda037971aac43a0..33c7b90b0b2fe7c1b8c7dd385719302ac755e123 100644 --- a/src/core/support/cpu_posix.c +++ b/src/core/support/cpu_posix.c @@ -43,15 +43,19 @@ static __thread char magic_thread_local; -unsigned gpr_cpu_num_cores(void) { - static int ncpus = 0; - if (ncpus == 0) { - ncpus = sysconf(_SC_NPROCESSORS_ONLN); - if (ncpus < 1) { - gpr_log(GPR_ERROR, "Cannot determine number of CPUs: assuming 1"); - ncpus = 1; - } +static int ncpus = 0; + +static void init_ncpus() { + ncpus = sysconf(_SC_NPROCESSORS_ONLN); + if (ncpus < 1) { + gpr_log(GPR_ERROR, "Cannot determine number of CPUs: assuming 1"); + ncpus = 1; } +} + +unsigned gpr_cpu_num_cores(void) { + static gpr_once once = GPR_ONCE_INIT; + gpr_once_init(&once, init_num_cpus); return ncpus; } diff --git a/src/core/support/string.c b/src/core/support/string.c index f3d26b45acf8edc2d1cb0fb819485ad2db814a29..bfd7ce1590d021cd47a55427c48e77324fa3fac7 100644 --- a/src/core/support/string.c +++ b/src/core/support/string.c @@ -91,7 +91,6 @@ char *gpr_hexdump(const char *buf, size_t len, gpr_uint32 flags) { } if (flags & GPR_HEXDUMP_PLAINTEXT) { - cur = beg; if (len) hexout_append(&out, ' '); hexout_append(&out, '\''); for (cur = beg; cur != end; ++cur) { diff --git a/src/core/tsi/ssl_transport_security.c b/src/core/tsi/ssl_transport_security.c index 92fcb96dd23cbfc4e957502e93e5bbb6c5789e0f..85b0922a439a2ecb9d3f55c1607064afddcaada3 100644 --- a/src/core/tsi/ssl_transport_security.c +++ b/src/core/tsi/ssl_transport_security.c @@ -1150,6 +1150,7 @@ tsi_result tsi_create_ssl_client_handshaker_factory( if (result != TSI_OK) { gpr_log(GPR_ERROR, "Building alpn list failed with error %s.", tsi_result_to_string(result)); + free(alpn_protocol_list); break; } ssl_failed = SSL_CTX_set_alpn_protos(ssl_context, alpn_protocol_list, diff --git a/src/cpp/server/server.cc b/src/cpp/server/server.cc index f565d3aa5d5ec16b1e936318585d4d8e842adf1c..178fa1a71679586c1a6ebefc435406179433a5a8 100644 --- a/src/cpp/server/server.cc +++ b/src/cpp/server/server.cc @@ -265,21 +265,26 @@ bool Server::Start() { } void Server::Shutdown() { - { - std::unique_lock<std::mutex> lock(mu_); - if (started_ && !shutdown_) { - shutdown_ = true; - grpc_server_shutdown(server_); - cq_.Shutdown(); + std::unique_lock<std::mutex> lock(mu_); + if (started_ && !shutdown_) { + shutdown_ = true; + grpc_server_shutdown(server_); + cq_.Shutdown(); - // Wait for running callbacks to finish. - while (num_running_cb_ != 0) { - callback_cv_.wait(lock); - } + // Wait for running callbacks to finish. + while (num_running_cb_ != 0) { + callback_cv_.wait(lock); } } } +void Server::Wait() { + std::unique_lock<std::mutex> lock(mu_); + while (num_running_cb_ != 0) { + callback_cv_.wait(lock); + } +} + void Server::PerformOpsOnCall(CallOpBuffer* buf, Call* call) { static const size_t MAX_OPS = 8; size_t nops = MAX_OPS; diff --git a/src/node/ext/credentials.cc b/src/node/ext/credentials.cc index 4b95c72bf73a23770f8d702c29d3bfe21a03c50e..3f65d59c766be9641fefb804b4e1f26baf2fccd0 100644 --- a/src/node/ext/credentials.cc +++ b/src/node/ext/credentials.cc @@ -130,7 +130,7 @@ NAN_METHOD(Credentials::New) { NAN_METHOD(Credentials::CreateDefault) { NanScope(); - NanReturnValue(WrapStruct(grpc_default_credentials_create())); + NanReturnValue(WrapStruct(grpc_google_default_credentials_create())); } NAN_METHOD(Credentials::CreateSsl) { diff --git a/src/node/interop/messages.proto b/src/node/interop/messages.proto index 65a81404652520a211940cd4af81968620ea8dc2..de0b1a232051052e2117f3718f21f040df06150c 100644 --- a/src/node/interop/messages.proto +++ b/src/node/interop/messages.proto @@ -49,7 +49,7 @@ enum PayloadType { // A block of data, to simply increase gRPC message size. message Payload { // The type of data in body. - optional PayloadType type = 1; + optional PayloadType type = 1 [default = COMPRESSABLE]; // Primary contents of payload. optional bytes body = 2; } @@ -58,7 +58,7 @@ message Payload { message SimpleRequest { // Desired payload type in the response from the server. // If response_type is RANDOM, server randomly chooses one from other formats. - optional PayloadType response_type = 1; + optional PayloadType response_type = 1 [default = COMPRESSABLE]; // Desired payload size in the response from the server. // If response_type is COMPRESSABLE, this denotes the size before compression. @@ -116,7 +116,7 @@ message StreamingOutputCallRequest { // If response_type is RANDOM, the payload from each response in the stream // might be of different types. This is to simulate a mixed type of payload // stream. - optional PayloadType response_type = 1; + optional PayloadType response_type = 1 [default = COMPRESSABLE]; // Configuration for each expected response message. repeated ResponseParameters response_parameters = 2; diff --git a/src/node/src/client.js b/src/node/src/client.js index aaa7be79c9d4898adba04d1f131afa04b7bd7eaa..54b8dbdc9c617258efcb220b8754e4e9c9d4cd77 100644 --- a/src/node/src/client.js +++ b/src/node/src/client.js @@ -245,7 +245,9 @@ function makeUnaryRequestFunction(method, serialize, deserialize) { return; } if (response.status.code !== grpc.status.OK) { - callback(response.status); + var error = new Error(response.status.details); + error.code = response.status.code; + callback(error); return; } emitter.emit('status', response.status); @@ -314,7 +316,9 @@ function makeClientStreamRequestFunction(method, serialize, deserialize) { return; } if (response.status.code !== grpc.status.OK) { - callback(response.status); + var error = new Error(response.status.details); + error.code = response.status.code; + callback(error); return; } stream.emit('status', response.status); diff --git a/src/python/src/grpc/_adapter/rear.py b/src/python/src/grpc/_adapter/rear.py index d16fbeecf7bc6c6b7d917f9c450cd1482a8c5601..94ff66ffdada0ef97db8116f73a962f5efaf25f3 100644 --- a/src/python/src/grpc/_adapter/rear.py +++ b/src/python/src/grpc/_adapter/rear.py @@ -170,7 +170,8 @@ class RearLink(ticket_interfaces.RearLink, activated.Activated): if event.status.code is _low.Code.OK: category = tickets.Kind.COMPLETION elif event.status.code is _low.Code.CANCELLED: - category = tickets.Kind.CANCELLATION + # TODO(issue 752): Use a CANCELLATION ticket kind here. + category = tickets.Kind.SERVICER_FAILURE elif event.status.code is _low.Code.EXPIRED: category = tickets.Kind.EXPIRATION else: diff --git a/src/ruby/ext/grpc/rb_credentials.c b/src/ruby/ext/grpc/rb_credentials.c index 778270735bcda7f48dc489794b1075a97916f8d6..4ee5d6b51c863de454a7ce2f78ff2108fed5e51c 100644 --- a/src/ruby/ext/grpc/rb_credentials.c +++ b/src/ruby/ext/grpc/rb_credentials.c @@ -125,7 +125,7 @@ static VALUE grpc_rb_credentials_init_copy(VALUE copy, VALUE orig) { Creates the default credential instances. */ static VALUE grpc_rb_default_credentials_create(VALUE cls) { grpc_rb_credentials *wrapper = ALLOC(grpc_rb_credentials); - wrapper->wrapped = grpc_default_credentials_create(); + wrapper->wrapped = grpc_google_default_credentials_create(); if (wrapper->wrapped == NULL) { rb_raise(rb_eRuntimeError, "could not create default credentials, not sure why"); diff --git a/src/ruby/spec/generic/active_call_spec.rb b/src/ruby/spec/generic/active_call_spec.rb index 84bb7b4f9bd9353e7e32fe429cfb63c22ca29698..12cb5c15580ab775ade7580895a56b93aa955012 100644 --- a/src/ruby/spec/generic/active_call_spec.rb +++ b/src/ruby/spec/generic/active_call_spec.rb @@ -67,7 +67,7 @@ describe GRPC::ActiveCall do end describe '#multi_req_view' do - it 'exposes a fixed subset of the ActiveCall methods' do + xit 'exposes a fixed subset of the ActiveCall methods' do want = %w(cancelled, deadline, each_remote_read, shutdown) v = @client_call.multi_req_view want.each do |w| @@ -77,7 +77,7 @@ describe GRPC::ActiveCall do end describe '#single_req_view' do - it 'exposes a fixed subset of the ActiveCall methods' do + xit 'exposes a fixed subset of the ActiveCall methods' do want = %w(cancelled, deadline, shutdown) v = @client_call.single_req_view want.each do |w| diff --git a/templates/Makefile.template b/templates/Makefile.template index cd7eb238454d140642fd65b12e9a5d44fe535505..8240996cfc68391168d6f6ca83cfbb53a64708d5 100644 --- a/templates/Makefile.template +++ b/templates/Makefile.template @@ -274,7 +274,7 @@ HAS_SYSTEM_ZLIB = false HAS_SYSTEM_PROTOBUF = false endif -HAS_PROTOC = $(shell $(PROTOC_CMD) && echo true || echo false) +HAS_PROTOC = $(shell $(PROTOC_CMD) > /dev/null && echo true || echo false) ifeq ($(HAS_PROTOC),true) HAS_VALID_PROTOC = $(shell $(PROTOC_CHECK_CMD) 2> /dev/null && echo true || echo false) else @@ -830,7 +830,7 @@ install-certs: etc/roots.pem $(Q) $(INSTALL) etc/roots.pem $(prefix)/share/grpc/roots.pem verify-install: -ifeq ($(SYSTEM_OK),true) +ifeq ($(INSTALL_OK),true) @echo "Your system looks ready to go." @echo else diff --git a/tools/dockerfile/grpc_build_deb/Dockerfile b/tools/dockerfile/grpc_build_deb/Dockerfile index ad26fb35d016ac923d9d501e87ee17511683ff80..6cba74e4c63eb2e4277beb1c4527f80d25c029f5 100644 --- a/tools/dockerfile/grpc_build_deb/Dockerfile +++ b/tools/dockerfile/grpc_build_deb/Dockerfile @@ -1,3 +1,32 @@ +# Copyright 2015, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + # Dockerfile to build Debian packages for gRPC C core. FROM grpc/base diff --git a/tools/dockerfile/grpc_ruby_deb/Dockerfile b/tools/dockerfile/grpc_ruby_deb/Dockerfile index 25ea2c54bd868ce236c14e6352fbd11e3f1763be..679fa51f5d592350d7efb83f4ab5f1f94bcc20d0 100644 --- a/tools/dockerfile/grpc_ruby_deb/Dockerfile +++ b/tools/dockerfile/grpc_ruby_deb/Dockerfile @@ -1,3 +1,32 @@ +# Copyright 2015, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + # Dockerfile for gRPC Ruby, but using Debian packages for gRPC C core. FROM grpc/ruby_base diff --git a/tools/run_tests/jobset.py b/tools/run_tests/jobset.py index df83b30516bce44c8dcea425c64232bec9ff2136..569cb5bac2090719d6e0cff3d0b57d0fe935ed48 100755 --- a/tools/run_tests/jobset.py +++ b/tools/run_tests/jobset.py @@ -33,6 +33,7 @@ import hashlib import multiprocessing import os import random +import signal import subprocess import sys import tempfile @@ -42,6 +43,12 @@ import time _DEFAULT_MAX_JOBS = 16 * multiprocessing.cpu_count() +# setup a signal handler so that signal.pause registers 'something' +# when a child finishes +# not using futures and threading to avoid a dependency on subprocess32 +signal.signal(signal.SIGCHLD, lambda unused_signum, unused_frame: None) + + def shuffle_iteratable(it): """Return an iterable that randomly walks it""" # take a random sampling from the passed in iterable @@ -94,16 +101,19 @@ _TAG_COLOR = { def message(tag, message, explanatory_text=None, do_newline=False): - sys.stdout.write('%s%s%s\x1b[%d;%dm%s\x1b[0m: %s%s' % ( - _BEGINNING_OF_LINE, - _CLEAR_LINE, - '\n%s' % explanatory_text if explanatory_text is not None else '', - _COLORS[_TAG_COLOR[tag]][1], - _COLORS[_TAG_COLOR[tag]][0], - tag, - message, - '\n' if do_newline or explanatory_text is not None else '')) - sys.stdout.flush() + try: + sys.stdout.write('%s%s%s\x1b[%d;%dm%s\x1b[0m: %s%s' % ( + _BEGINNING_OF_LINE, + _CLEAR_LINE, + '\n%s' % explanatory_text if explanatory_text is not None else '', + _COLORS[_TAG_COLOR[tag]][1], + _COLORS[_TAG_COLOR[tag]][0], + tag, + message, + '\n' if do_newline or explanatory_text is not None else '')) + sys.stdout.flush() + except: + pass def which(filename): @@ -232,7 +242,7 @@ class Jobset(object): if dead: return message('WAITING', '%d jobs running, %d complete, %d failed' % ( len(self._running), self._completed, self._failures)) - time.sleep(0.1) + signal.pause() def cancelled(self): """Poll for cancellation.""" diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py index 64478b37532775a19a2fc5a1b1d8eba37fa94467..7732466d6ea220d287014784b4275b7ebe9868f0 100755 --- a/tools/run_tests/run_tests.py +++ b/tools/run_tests/run_tests.py @@ -36,6 +36,7 @@ import itertools import json import multiprocessing import os +import re import sys import time @@ -168,6 +169,7 @@ argp.add_argument('-c', '--config', nargs='+', default=_DEFAULT) argp.add_argument('-n', '--runs_per_test', default=1, type=int) +argp.add_argument('-r', '--regex', default='.*', type=str) argp.add_argument('-j', '--jobs', default=1000, type=int) argp.add_argument('-f', '--forever', default=False, @@ -205,7 +207,8 @@ one_run = set( spec for config in run_configs for language in args.language - for spec in _LANGUAGES[language].test_specs(config)) + for spec in _LANGUAGES[language].test_specs(config) + if re.search(args.regex, spec.shortname)) runs_per_test = args.runs_per_test forever = args.forever