Merge pull request #10748 from murgatroid99/upmerge_v1.3.x

Manually upmerge v1.3.x into master
pull/8471/merge
Michael Lumish 8 years ago committed by GitHub
commit 4c9114858c
  1. 4
      binding.gyp
  2. 1
      build.yaml
  3. 57
      config.m4
  4. 73
      package.xml
  5. 16
      src/node/performance/benchmark_client.js
  6. 10
      src/node/performance/benchmark_client_express.js
  7. 15
      src/node/performance/benchmark_server.js
  8. 8
      src/node/performance/benchmark_server_express.js
  9. 69
      src/ruby/end2end/forking_client_client.rb
  10. 69
      src/ruby/end2end/forking_client_driver.rb
  11. 77
      src/ruby/end2end/grpc_class_init_client.rb
  12. 67
      src/ruby/end2end/grpc_class_init_driver.rb
  13. 4
      src/ruby/ext/grpc/rb_call_credentials.c
  14. 75
      src/ruby/ext/grpc/rb_channel.c
  15. 2
      src/ruby/ext/grpc/rb_channel.h
  16. 3
      src/ruby/ext/grpc/rb_channel_credentials.c
  17. 7
      src/ruby/ext/grpc/rb_compression_options.c
  18. 21
      src/ruby/ext/grpc/rb_grpc.c
  19. 2
      src/ruby/ext/grpc/rb_grpc.h
  20. 6
      src/ruby/ext/grpc/rb_server.c
  21. 4
      templates/binding.gyp.template
  22. 7
      templates/config.m4.template
  23. 2
      tools/run_tests/artifacts/build_artifact_node.bat
  24. 2
      tools/run_tests/artifacts/build_artifact_node.sh
  25. 2
      tools/run_tests/helper_scripts/run_ruby_end2end_tests.sh
  26. 41
      tools/run_tests/performance/scenario_config.py
  27. 4
      tools/run_tests/run_tests.py
  28. 3
      tools/run_tests/run_tests_matrix.py

@ -507,7 +507,7 @@
},
]
}],
['OS == "win"', {
['OS == "win" and runtime!="electron"', {
'targets': [
{
# IMPORTANT WINDOWS BUILD INFORMATION
@ -518,6 +518,8 @@
# when including the Node headers. The remedy for this is to remove
# the OpenSSL headers, from the downloaded Node development package,
# which is typically located in `.node-gyp` in your home directory.
#
# This is not true of Electron, which does not have OpenSSL headers.
'target_name': 'WINDOWS_BUILD_WARNING',
'rules': [
{

@ -4518,6 +4518,7 @@ php_config_m4:
deps:
- grpc
- gpr
- ares
- boringssl
headers:
- src/php/ext/grpc/byte_buffer.h

@ -8,6 +8,8 @@ if test "$PHP_GRPC" != "no"; then
PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/include)
PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/src/php/ext/grpc)
PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/boringssl/include)
PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/cares)
PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/cares/cares)
LIBS="-lpthread $LIBS"
@ -18,8 +20,11 @@ if test "$PHP_GRPC" != "no"; then
PHP_ADD_LIBRARY(dl)
case $host in
*darwin*) ;;
*darwin*)
PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/cares/config_darwin)
;;
*)
PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/cares/config_linux)
PHP_ADD_LIBRARY(rt,,GRPC_SHARED_LIBADD)
PHP_ADD_LIBRARY(rt)
;;
@ -622,6 +627,55 @@ if test "$PHP_GRPC" != "no"; then
third_party/boringssl/ssl/tls13_server.c \
third_party/boringssl/ssl/tls_method.c \
third_party/boringssl/ssl/tls_record.c \
third_party/cares/cares/ares__close_sockets.c \
third_party/cares/cares/ares__get_hostent.c \
third_party/cares/cares/ares__read_line.c \
third_party/cares/cares/ares__timeval.c \
third_party/cares/cares/ares_cancel.c \
third_party/cares/cares/ares_create_query.c \
third_party/cares/cares/ares_data.c \
third_party/cares/cares/ares_destroy.c \
third_party/cares/cares/ares_expand_name.c \
third_party/cares/cares/ares_expand_string.c \
third_party/cares/cares/ares_fds.c \
third_party/cares/cares/ares_free_hostent.c \
third_party/cares/cares/ares_free_string.c \
third_party/cares/cares/ares_getenv.c \
third_party/cares/cares/ares_gethostbyaddr.c \
third_party/cares/cares/ares_gethostbyname.c \
third_party/cares/cares/ares_getnameinfo.c \
third_party/cares/cares/ares_getopt.c \
third_party/cares/cares/ares_getsock.c \
third_party/cares/cares/ares_init.c \
third_party/cares/cares/ares_library_init.c \
third_party/cares/cares/ares_llist.c \
third_party/cares/cares/ares_mkquery.c \
third_party/cares/cares/ares_nowarn.c \
third_party/cares/cares/ares_options.c \
third_party/cares/cares/ares_parse_a_reply.c \
third_party/cares/cares/ares_parse_aaaa_reply.c \
third_party/cares/cares/ares_parse_mx_reply.c \
third_party/cares/cares/ares_parse_naptr_reply.c \
third_party/cares/cares/ares_parse_ns_reply.c \
third_party/cares/cares/ares_parse_ptr_reply.c \
third_party/cares/cares/ares_parse_soa_reply.c \
third_party/cares/cares/ares_parse_srv_reply.c \
third_party/cares/cares/ares_parse_txt_reply.c \
third_party/cares/cares/ares_platform.c \
third_party/cares/cares/ares_process.c \
third_party/cares/cares/ares_query.c \
third_party/cares/cares/ares_search.c \
third_party/cares/cares/ares_send.c \
third_party/cares/cares/ares_strcasecmp.c \
third_party/cares/cares/ares_strdup.c \
third_party/cares/cares/ares_strerror.c \
third_party/cares/cares/ares_timeout.c \
third_party/cares/cares/ares_version.c \
third_party/cares/cares/ares_writev.c \
third_party/cares/cares/bitncmp.c \
third_party/cares/cares/inet_net_pton.c \
third_party/cares/cares/inet_ntop.c \
third_party/cares/cares/windows_port.c \
, $ext_shared, , -Wall -Werror \
-Wno-parentheses-equality -Wno-unused-value -std=c11 \
-fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN \
@ -724,5 +778,6 @@ if test "$PHP_GRPC" != "no"; then
PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/x509)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/x509v3)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/ssl)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/cares/cares)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/nanopb)
fi

@ -1028,6 +1028,79 @@
<file baseinstalldir="/" name="third_party/boringssl/ssl/tls13_server.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/ssl/tls_method.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/ssl/tls_record.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares.h" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_data.h" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_dns.h" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_getenv.h" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_getopt.h" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_inet_net_pton.h" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_iphlpapi.h" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_ipv6.h" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_library_init.h" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_llist.h" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_nowarn.h" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_platform.h" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_private.h" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_rules.h" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_setup.h" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_strcasecmp.h" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_strdup.h" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_version.h" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/bitncmp.h" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/config-win32.h" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/setup_once.h" role="src" />
<file baseinstalldir="/" name="third_party/cares/ares_build.h" role="src" />
<file baseinstalldir="/" name="third_party/cares/config_linux/ares_config.h" role="src" />
<file baseinstalldir="/" name="third_party/cares/config_darwin/ares_config.h" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares__close_sockets.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares__get_hostent.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares__read_line.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares__timeval.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_cancel.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_create_query.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_data.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_destroy.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_expand_name.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_expand_string.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_fds.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_free_hostent.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_free_string.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_getenv.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_gethostbyaddr.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_gethostbyname.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_getnameinfo.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_getopt.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_getsock.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_init.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_library_init.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_llist.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_mkquery.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_nowarn.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_options.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_parse_a_reply.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_parse_aaaa_reply.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_parse_mx_reply.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_parse_naptr_reply.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_parse_ns_reply.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_parse_ptr_reply.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_parse_soa_reply.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_parse_srv_reply.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_parse_txt_reply.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_platform.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_process.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_query.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_search.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_send.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_strcasecmp.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_strdup.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_strerror.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_timeout.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_version.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/ares_writev.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/bitncmp.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/inet_net_pton.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/inet_ntop.c" role="src" />
<file baseinstalldir="/" name="third_party/cares/cares/windows_port.c" role="src" />
</dir>
</contents>
<dependencies>

@ -88,7 +88,10 @@ function timeDiffToNanos(time_diff) {
*/
function BenchmarkClient(server_targets, channels, histogram_params,
security_params) {
var options = {};
var options = {
"grpc.max_receive_message_length": -1,
"grpc.max_send_message_length": -1
};
var creds;
if (security_params) {
var ca_path;
@ -180,6 +183,8 @@ BenchmarkClient.prototype.startClosedLoop = function(
self.last_wall_time = process.hrtime();
self.last_usage = process.cpuUsage();
var makeCall;
var argument;
@ -270,6 +275,8 @@ BenchmarkClient.prototype.startPoisson = function(
self.last_wall_time = process.hrtime();
self.last_usage = process.cpuUsage();
var makeCall;
var argument;
@ -354,9 +361,11 @@ BenchmarkClient.prototype.startPoisson = function(
*/
BenchmarkClient.prototype.mark = function(reset) {
var wall_time_diff = process.hrtime(this.last_wall_time);
var usage_diff = process.cpuUsage(this.last_usage);
var histogram = this.histogram;
if (reset) {
this.last_wall_time = process.hrtime();
this.last_usage = process.cpuUsage();
this.histogram = new Histogram(histogram.resolution,
histogram.max_possible);
}
@ -371,9 +380,8 @@ BenchmarkClient.prototype.mark = function(reset) {
count: histogram.getCount()
},
time_elapsed: wall_time_diff[0] + wall_time_diff[1] / 1e9,
// Not sure how to measure these values
time_user: 0,
time_system: 0
time_user: usage_diff.user / 1000000,
time_system: usage_diff.system / 1000000
};
};

@ -95,7 +95,6 @@ function BenchmarkClient(server_targets, channels, histogram_params,
var host_port;
host_port = server_targets[i % server_targets.length].split(':');
var new_options = _.assign({hostname: host_port[0], port: +host_port[1]}, options);
new_options.agent = new protocol.Agent(new_options);
this.client_options[i] = new_options;
}
@ -137,6 +136,7 @@ BenchmarkClient.prototype.startClosedLoop = function(
}
self.last_wall_time = process.hrtime();
self.last_usage = process.cpuUsage();
var argument = {
response_size: resp_size,
@ -207,6 +207,7 @@ BenchmarkClient.prototype.startPoisson = function(
}
self.last_wall_time = process.hrtime();
self.last_usage = process.cpuUsage();
var argument = {
response_size: resp_size,
@ -264,9 +265,11 @@ BenchmarkClient.prototype.startPoisson = function(
*/
BenchmarkClient.prototype.mark = function(reset) {
var wall_time_diff = process.hrtime(this.last_wall_time);
var usage_diff = process.cpuUsage(this.last_usage);
var histogram = this.histogram;
if (reset) {
this.last_wall_time = process.hrtime();
this.last_usage = process.cpuUsage();
this.histogram = new Histogram(histogram.resolution,
histogram.max_possible);
}
@ -281,9 +284,8 @@ BenchmarkClient.prototype.mark = function(reset) {
count: histogram.getCount()
},
time_elapsed: wall_time_diff[0] + wall_time_diff[1] / 1e9,
// Not sure how to measure these values
time_user: 0,
time_system: 0
time_user: usage_diff.user / 1000000,
time_system: usage_diff.system / 1000000
};
};

@ -132,7 +132,12 @@ function BenchmarkServer(host, port, tls, generic, response_size) {
server_creds = grpc.ServerCredentials.createInsecure();
}
var server = new grpc.Server();
var options = {
"grpc.max_receive_message_length": -1,
"grpc.max_send_message_length": -1
};
var server = new grpc.Server(options);
this.port = server.bind(host + ':' + port, server_creds);
if (generic) {
server.addService(genericService, {
@ -156,6 +161,7 @@ util.inherits(BenchmarkServer, EventEmitter);
BenchmarkServer.prototype.start = function() {
this.server.start();
this.last_wall_time = process.hrtime();
this.last_usage = process.cpuUsage();
this.emit('started');
};
@ -175,14 +181,15 @@ BenchmarkServer.prototype.getPort = function() {
*/
BenchmarkServer.prototype.mark = function(reset) {
var wall_time_diff = process.hrtime(this.last_wall_time);
var usage_diff = process.cpuUsage(this.last_usage);
if (reset) {
this.last_wall_time = process.hrtime();
this.last_usage = process.cpuUsage();
}
return {
time_elapsed: wall_time_diff[0] + wall_time_diff[1] / 1e9,
// Not sure how to measure these values
time_user: 0,
time_system: 0
time_user: usage_diff.user / 1000000,
time_system: usage_diff.system / 1000000
};
};

@ -81,6 +81,7 @@ BenchmarkServer.prototype.start = function() {
var self = this;
this.server.listen(this.input_port, this.input_hostname, function() {
self.last_wall_time = process.hrtime();
self.last_usage = process.cpuUsage();
self.emit('started');
});
};
@ -91,14 +92,15 @@ BenchmarkServer.prototype.getPort = function() {
BenchmarkServer.prototype.mark = function(reset) {
var wall_time_diff = process.hrtime(this.last_wall_time);
var usage_diff = process.cpuUsage(this.last_usage);
if (reset) {
this.last_wall_time = process.hrtime();
this.last_usage = process.cpuUsage();
}
return {
time_elapsed: wall_time_diff[0] + wall_time_diff[1] / 1e9,
// Not sure how to measure these values
time_user: 0,
time_system: 0
time_user: usage_diff.user / 1000000,
time_system: usage_diff.system / 1000000
};
};

@ -0,0 +1,69 @@
#!/usr/bin/env ruby
# 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.
# Prompted by and minimal repro of https://github.com/grpc/grpc/issues/10658
require_relative './end2end_common'
def main
server_port = ''
OptionParser.new do |opts|
opts.on('--client_control_port=P', String) do
STDERR.puts 'client control port not used'
end
opts.on('--server_port=P', String) do |p|
server_port = p
end
end.parse!
p = fork do
stub = Echo::EchoServer::Stub.new("localhost:#{server_port}",
:this_channel_is_insecure)
stub.echo(Echo::EchoRequest.new(request: 'hello'))
end
begin
Timeout.timeout(10) do
Process.wait(p)
end
rescue Timeout::Error
STDERR.puts "timeout waiting for forked process #{p}"
Process.kill('SIGKILL', p)
Process.wait(p)
raise 'Timed out waiting for client process. ' \
'It likely hangs when using gRPC after loading it and then forking'
end
client_exit_code = $CHILD_STATUS
fail "forked process failed #{client_exit_code}" if client_exit_code != 0
end
main

@ -0,0 +1,69 @@
#!/usr/bin/env ruby
# Copyright 2016, 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.
require_relative './end2end_common'
def main
STDERR.puts 'start server'
server_runner = ServerRunner.new(EchoServerImpl)
server_port = server_runner.run
# TODO(apolcyn) Can we get rid of this sleep?
# Without it, an immediate call to the just started EchoServer
# fails with UNAVAILABLE
sleep 1
STDERR.puts 'start client'
_, client_pid = start_client('forking_client_client.rb',
server_port)
begin
Timeout.timeout(10) do
Process.wait(client_pid)
end
rescue Timeout::Error
STDERR.puts "timeout wait for client pid #{client_pid}"
Process.kill('SIGKILL', client_pid)
Process.wait(client_pid)
STDERR.puts 'killed client child'
raise 'Timed out waiting for client process. ' \
'It likely hangs when requiring grpc, then forking, then using grpc '
end
client_exit_code = $CHILD_STATUS
if client_exit_code != 0
fail "forking client client failed, exit code #{client_exit_code}"
end
server_runner.stop
end
main

@ -0,0 +1,77 @@
#!/usr/bin/env ruby
# 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.
# For GRPC::Core classes, which use the grpc c-core, object init
# is interesting because it's related to overall library init.
require_relative './end2end_common'
def main
grpc_class = ''
OptionParser.new do |opts|
opts.on('--grpc_class=P', String) do |p|
grpc_class = p
end
end.parse!
test_proc = nil
case grpc_class
when 'channel'
test_proc = proc do
GRPC::Core::Channel.new('dummy_host', nil, :this_channel_is_insecure)
end
when 'server'
test_proc = proc do
GRPC::Core::Server.new({})
end
when 'channel_credentials'
test_proc = proc do
GRPC::Core::ChannelCredentials.new
end
when 'call_credentials'
test_proc = proc do
GRPC::Core::CallCredentials.new(proc { |noop| noop })
end
when 'compression_options'
test_proc = proc do
GRPC::Core::CompressionOptions.new
end
else
fail "bad --grpc_class=#{grpc_class} param"
end
th = Thread.new { test_proc.call }
test_proc.call
th.join
end
main

@ -0,0 +1,67 @@
#!/usr/bin/env ruby
# Copyright 2016, 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.
require_relative './end2end_common'
def main
native_grpc_classes = %w( channel
server
channel_credentials
call_credentials
compression_options )
native_grpc_classes.each do |grpc_class|
STDERR.puts 'start client'
this_dir = File.expand_path(File.dirname(__FILE__))
client_path = File.join(this_dir, 'grpc_class_init_client.rb')
client_pid = Process.spawn(RbConfig.ruby,
client_path,
"--grpc_class=#{grpc_class}")
begin
Timeout.timeout(10) do
Process.wait(client_pid)
end
rescue Timeout::Error
STDERR.puts "timeout waiting for client pid #{client_pid}"
Process.kill('SIGKILL', client_pid)
Process.wait(client_pid)
STDERR.puts 'killed client child'
raise 'Timed out waiting for client process. ' \
'It likely hangs when the first constructed gRPC object has ' \
"type: #{grpc_class}"
end
client_exit_code = $CHILD_STATUS
fail "client failed, exit code #{client_exit_code}" if client_exit_code != 0
end
end
main

@ -223,6 +223,8 @@ static VALUE grpc_rb_call_credentials_init(VALUE self, VALUE proc) {
grpc_call_credentials *creds = NULL;
grpc_metadata_credentials_plugin plugin;
grpc_ruby_once_init();
TypedData_Get_Struct(self, grpc_rb_call_credentials,
&grpc_rb_call_credentials_data_type, wrapper);
@ -283,8 +285,6 @@ void Init_grpc_call_credentials() {
grpc_rb_call_credentials_compose, -1);
id_callback = rb_intern("__callback");
grpc_rb_event_queue_thread_start();
}
/* Gets the wrapped grpc_call_credentials from the ruby wrapper */

@ -89,10 +89,14 @@ typedef struct grpc_rb_channel {
static void grpc_rb_channel_try_register_connection_polling(
grpc_rb_channel *wrapper);
static void grpc_rb_channel_safe_destroy(grpc_rb_channel *wrapper);
static void *wait_until_channel_polling_thread_started_no_gil(void *);
static void wait_until_channel_polling_thread_started_unblocking_func(void *);
static grpc_completion_queue *channel_polling_cq;
static gpr_mu global_connection_polling_mu;
static gpr_cv global_connection_polling_cv;
static int abort_channel_polling = 0;
static int channel_polling_thread_started = 0;
/* Destroys Channel instances. */
static void grpc_rb_channel_free(void *p) {
@ -166,6 +170,11 @@ static VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) {
grpc_channel_args args;
MEMZERO(&args, grpc_channel_args, 1);
grpc_ruby_once_init();
rb_thread_call_without_gvl(
wait_until_channel_polling_thread_started_no_gil, NULL,
wait_until_channel_polling_thread_started_unblocking_func, NULL);
/* "3" == 3 mandatory args */
rb_scan_args(argc, argv, "3", &target, &channel_args, &credentials);
@ -440,6 +449,7 @@ static void grpc_rb_channel_try_register_connection_polling(
}
gpr_mu_lock(&global_connection_polling_mu);
GPR_ASSERT(channel_polling_thread_started || abort_channel_polling);
conn_state = grpc_channel_check_connectivity_state(wrapper->wrapped, 0);
if (conn_state != wrapper->current_connectivity_state) {
wrapper->current_connectivity_state = conn_state;
@ -473,7 +483,7 @@ static void grpc_rb_channel_safe_destroy(grpc_rb_channel *wrapper) {
}
// Note this loop breaks out with a single call of
// "grpc_rb_event_unblocking_func".
// "run_poll_channels_loop_no_gil".
// This assumes that a ruby call the unblocking func
// indicates process shutdown.
// In the worst case, this stops polling channel connectivity
@ -481,6 +491,14 @@ static void grpc_rb_channel_safe_destroy(grpc_rb_channel *wrapper) {
static void *run_poll_channels_loop_no_gil(void *arg) {
grpc_event event;
(void)arg;
gpr_log(GPR_DEBUG, "GRPC_RUBY: run_poll_channels_loop_no_gil - begin");
gpr_mu_lock(&global_connection_polling_mu);
GPR_ASSERT(!channel_polling_thread_started);
channel_polling_thread_started = 1;
gpr_cv_broadcast(&global_connection_polling_cv);
gpr_mu_unlock(&global_connection_polling_mu);
for (;;) {
event = grpc_completion_queue_next(
channel_polling_cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
@ -500,7 +518,7 @@ static void *run_poll_channels_loop_no_gil(void *arg) {
}
// Notify the channel polling loop to cleanup and shutdown.
static void grpc_rb_event_unblocking_func(void *arg) {
static void run_poll_channels_loop_unblocking_func(void *arg) {
(void)arg;
gpr_mu_lock(&global_connection_polling_mu);
gpr_log(GPR_DEBUG,
@ -518,10 +536,37 @@ static VALUE run_poll_channels_loop(VALUE arg) {
GPR_DEBUG,
"GRPC_RUBY: run_poll_channels_loop - create connection polling thread");
rb_thread_call_without_gvl(run_poll_channels_loop_no_gil, NULL,
grpc_rb_event_unblocking_func, NULL);
run_poll_channels_loop_unblocking_func, NULL);
return Qnil;
}
static void *wait_until_channel_polling_thread_started_no_gil(void *arg) {
(void)arg;
gpr_log(GPR_DEBUG, "GRPC_RUBY: wait for channel polling thread to start");
gpr_mu_lock(&global_connection_polling_mu);
while (!channel_polling_thread_started && !abort_channel_polling) {
gpr_cv_wait(&global_connection_polling_cv, &global_connection_polling_mu,
gpr_inf_future(GPR_CLOCK_REALTIME));
}
gpr_mu_unlock(&global_connection_polling_mu);
return NULL;
}
static void wait_until_channel_polling_thread_started_unblocking_func(
void *arg) {
(void)arg;
gpr_mu_lock(&global_connection_polling_mu);
gpr_log(GPR_DEBUG,
"GRPC_RUBY: "
"wait_until_channel_polling_thread_started_unblocking_func - begin "
"aborting connection polling");
abort_channel_polling = 1;
gpr_cv_broadcast(&global_connection_polling_cv);
gpr_mu_unlock(&global_connection_polling_mu);
}
/* Temporary fix for
* https://github.com/GoogleCloudPlatform/google-cloud-ruby/issues/899.
* Transports in idle channels can get destroyed. Normally c-core re-connects,
@ -532,11 +577,26 @@ static VALUE run_poll_channels_loop(VALUE arg) {
* calls - so that c-core can reconnect if needed, when there aren't any RPC's.
* TODO(apolcyn) remove this when core handles new RPCs on dead connections.
*/
static void start_poll_channels_loop() {
channel_polling_cq = grpc_completion_queue_create_for_next(NULL);
void grpc_rb_channel_polling_thread_start() {
VALUE background_thread = Qnil;
GPR_ASSERT(!abort_channel_polling);
GPR_ASSERT(!channel_polling_thread_started);
GPR_ASSERT(channel_polling_cq == NULL);
gpr_mu_init(&global_connection_polling_mu);
abort_channel_polling = 0;
rb_thread_create(run_poll_channels_loop, NULL);
gpr_cv_init(&global_connection_polling_cv);
channel_polling_cq = grpc_completion_queue_create_for_next(NULL);
background_thread = rb_thread_create(run_poll_channels_loop, NULL);
if (!RTEST(background_thread)) {
gpr_log(GPR_DEBUG, "GRPC_RUBY: failed to spawn channel polling thread");
gpr_mu_lock(&global_connection_polling_mu);
abort_channel_polling = 1;
gpr_cv_broadcast(&global_connection_polling_cv);
gpr_mu_unlock(&global_connection_polling_mu);
}
}
static void Init_grpc_propagate_masks() {
@ -608,7 +668,6 @@ void Init_grpc_channel() {
id_insecure_channel = rb_intern("this_channel_is_insecure");
Init_grpc_propagate_masks();
Init_grpc_connectivity_states();
start_poll_channels_loop();
}
/* Gets the wrapped channel from the ruby wrapper */

@ -41,6 +41,8 @@
/* Initializes the Channel class. */
void Init_grpc_channel();
void grpc_rb_channel_polling_thread_start();
/* Gets the wrapped channel from the ruby wrapper */
grpc_channel* grpc_rb_get_wrapped_channel(VALUE v);

@ -161,6 +161,9 @@ static VALUE grpc_rb_channel_credentials_init(int argc, VALUE *argv,
grpc_ssl_pem_key_cert_pair key_cert_pair;
const char *pem_root_certs_cstr = NULL;
MEMZERO(&key_cert_pair, grpc_ssl_pem_key_cert_pair, 1);
grpc_ruby_once_init();
/* "03" == no mandatory arg, 3 optional */
rb_scan_args(argc, argv, "03", &pem_root_certs, &pem_private_key,
&pem_cert_chain);

@ -100,8 +100,11 @@ static rb_data_type_t grpc_rb_compression_options_data_type = {
Allocate the wrapped grpc compression options and
initialize it here too. */
static VALUE grpc_rb_compression_options_alloc(VALUE cls) {
grpc_rb_compression_options *wrapper =
gpr_malloc(sizeof(grpc_rb_compression_options));
grpc_rb_compression_options *wrapper = NULL;
grpc_ruby_once_init();
wrapper = gpr_malloc(sizeof(grpc_rb_compression_options));
wrapper->wrapped = NULL;
wrapper->wrapped = gpr_malloc(sizeof(grpc_compression_options));
grpc_compression_options_init(wrapper->wrapped);

@ -47,6 +47,7 @@
#include "rb_channel.h"
#include "rb_channel_credentials.h"
#include "rb_compression_options.h"
#include "rb_event_thread.h"
#include "rb_loader.h"
#include "rb_server.h"
#include "rb_server_credentials.h"
@ -289,17 +290,14 @@ VALUE sym_metadata = Qundef;
static gpr_once g_once_init = GPR_ONCE_INIT;
static void grpc_ruby_once_init() {
static void grpc_ruby_once_init_internal() {
grpc_init();
grpc_rb_event_queue_thread_start();
grpc_rb_channel_polling_thread_start();
atexit(grpc_rb_shutdown);
}
void Init_grpc_c() {
if (!grpc_rb_load_core()) {
rb_raise(rb_eLoadError, "Couldn't find or load gRPC's dynamic C core");
return;
}
void grpc_ruby_once_init() {
/* ruby_vm_at_exit doesn't seem to be working. It would crash once every
* blue moon, and some users are getting it repeatedly. See the discussions
* - https://github.com/grpc/grpc/pull/5337
@ -310,7 +308,14 @@ void Init_grpc_c() {
* then loaded again by another VM within the same process, we need to
* schedule our initialization and destruction only once.
*/
gpr_once_init(&g_once_init, grpc_ruby_once_init);
gpr_once_init(&g_once_init, grpc_ruby_once_init_internal);
}
void Init_grpc_c() {
if (!grpc_rb_load_core()) {
rb_raise(rb_eLoadError, "Couldn't find or load gRPC's dynamic C core");
return;
}
grpc_rb_mGRPC = rb_define_module("GRPC");
grpc_rb_mGrpcCore = rb_define_module_under(grpc_rb_mGRPC, "Core");

@ -82,4 +82,6 @@ VALUE grpc_rb_cannot_init_copy(VALUE copy, VALUE self);
/* grpc_rb_time_timeval creates a gpr_timespec from a ruby time object. */
gpr_timespec grpc_rb_time_timeval(VALUE time, int interval);
void grpc_ruby_once_init();
#endif /* GRPC_RB_H_ */

@ -132,11 +132,15 @@ static VALUE grpc_rb_server_alloc(VALUE cls) {
Initializes server instances. */
static VALUE grpc_rb_server_init(VALUE self, VALUE channel_args) {
grpc_completion_queue *cq = grpc_completion_queue_create_for_pluck(NULL);
grpc_completion_queue *cq = NULL;
grpc_rb_server *wrapper = NULL;
grpc_server *srv = NULL;
grpc_channel_args args;
MEMZERO(&args, grpc_channel_args, 1);
grpc_ruby_once_init();
cq = grpc_completion_queue_create_for_pluck(NULL);
TypedData_Get_Struct(self, grpc_rb_server, &grpc_rb_server_data_type,
wrapper);
grpc_rb_hash_convert_to_channel_args(channel_args, &args);

@ -205,7 +205,7 @@
% endfor
]
}],
['OS == "win"', {
['OS == "win" and runtime!="electron"', {
'targets': [
{
# IMPORTANT WINDOWS BUILD INFORMATION
@ -216,6 +216,8 @@
# when including the Node headers. The remedy for this is to remove
# the OpenSSL headers, from the downloaded Node development package,
# which is typically located in `.node-gyp` in your home directory.
#
# This is not true of Electron, which does not have OpenSSL headers.
'target_name': 'WINDOWS_BUILD_WARNING',
'rules': [
{

@ -10,6 +10,8 @@
PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/include)
PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/src/php/ext/grpc)
PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/boringssl/include)
PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/cares)
PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/cares/cares)
LIBS="-lpthread $LIBS"
@ -20,8 +22,11 @@
PHP_ADD_LIBRARY(dl)
case $host in
*darwin*) ;;
*darwin*)
PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/cares/config_darwin)
;;
*)
PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/cares/config_linux)
PHP_ADD_LIBRARY(rt,,GRPC_SHARED_LIBADD)
PHP_ADD_LIBRARY(rt)
;;

@ -29,7 +29,7 @@
set node_versions=4.0.0 5.0.0 6.0.0 7.0.0
set electron_versions=1.0.0 1.1.0 1.2.0 1.3.0 1.4.0
set electron_versions=1.0.0 1.1.0 1.2.0 1.3.0 1.4.0 1.5.0 1.6.0
set PATH=%PATH%;C:\Program Files\nodejs\;%APPDATA%\npm

@ -44,7 +44,7 @@ npm update
node_versions=( 4.0.0 5.0.0 6.0.0 7.0.0 )
electron_versions=( 1.0.0 1.1.0 1.2.0 1.3.0 1.4.0 )
electron_versions=( 1.0.0 1.1.0 1.2.0 1.3.0 1.4.0 1.5.0 1.6.0 )
for version in ${node_versions[@]}
do

@ -39,4 +39,6 @@ ruby src/ruby/end2end/channel_state_driver.rb || EXIT_CODE=1
ruby src/ruby/end2end/channel_closing_driver.rb || EXIT_CODE=1
ruby src/ruby/end2end/sig_int_during_channel_watch_driver.rb || EXIT_CODE=1
ruby src/ruby/end2end/killed_client_thread_driver.rb || EXIT_CODE=1
ruby src/ruby/end2end/forking_client_driver.rb || EXIT_CODE=1
ruby src/ruby/end2end/grpc_class_init_driver.rb || EXIT_CODE=1
exit $EXIT_CODE

@ -513,7 +513,22 @@ class NodeLanguage:
'node_protobuf_unary_ping_pong_1MB', rpc_type='UNARY',
client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
req_size=1024*1024, resp_size=1024*1024,
categories=[SCALABLE, SMOKETEST])
categories=[SCALABLE])
sizes = [('1B', 1), ('1KB', 1024), ('10KB', 10 * 1024),
('1MB', 1024 * 1024), ('10MB', 10 * 1024 * 1024),
('100MB', 100 * 1024 * 1024)]
for size_name, size in sizes:
for secure in (True, False):
yield _ping_pong_scenario(
'node_protobuf_unary_ping_pong_%s_resp_%s' %
(size_name, 'secure' if secure else 'insecure'),
rpc_type='UNARY',
client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
req_size=0, resp_size=size,
secure=secure,
categories=[SCALABLE])
# TODO(murgatroid99): fix bugs with this scenario and re-enable it
# yield _ping_pong_scenario(
@ -528,11 +543,10 @@ class NodeLanguage:
# client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
# unconstrained_client='async')
# TODO(jtattermusch): make this scenario work
#yield _ping_pong_scenario(
# 'node_to_cpp_protobuf_async_unary_ping_pong', rpc_type='UNARY',
# client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
# server_language='c++', async_server_threads=1)
yield _ping_pong_scenario(
'node_to_cpp_protobuf_async_unary_ping_pong', rpc_type='UNARY',
client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
server_language='c++', async_server_threads=1)
# TODO(jtattermusch): make this scenario work
#yield _ping_pong_scenario(
@ -829,6 +843,21 @@ class NodeExpressLanguage:
unconstrained_client='async',
categories=[SCALABLE, SMOKETEST])
sizes = [('1B', 1), ('1KB', 1024), ('10KB', 10 * 1024),
('1MB', 1024 * 1024), ('10MB', 10 * 1024 * 1024),
('100MB', 100 * 1024 * 1024)]
for size_name, size in sizes:
for secure in (True, False):
yield _ping_pong_scenario(
'node_express_json_unary_ping_pong_%s_resp_%s' %
(size_name, 'secure' if secure else 'insecure'),
rpc_type='UNARY',
client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
req_size=0, resp_size=size,
secure=secure,
categories=[SCALABLE])
def __str__(self):
return 'node_express'

@ -429,7 +429,7 @@ class NodeLanguage(object):
# we should specify in the compiler argument
_check_compiler(self.args.compiler, ['default', 'node0.12',
'node4', 'node5', 'node6',
'node7', 'electron1.3'])
'node7', 'electron1.3', 'electron1.6'])
if args.iomgr_platform == "uv":
self.use_uv = True
else:
@ -1178,7 +1178,7 @@ argp.add_argument('--compiler',
'vs2013', 'vs2015',
'python2.7', 'python3.4', 'python3.5', 'python3.6', 'pypy', 'pypy3', 'python_alpine',
'node0.12', 'node4', 'node5', 'node6', 'node7',
'electron1.3',
'electron1.3', 'electron1.6',
'coreclr',
'cmake'],
default='default',

@ -278,7 +278,8 @@ def _create_portability_test_jobs(extra_args=[], inner_jobs=_DEFAULT_INNER_JOBS)
configs=['dbg'],
platforms=['linux'],
arch='default',
compiler='electron1.3',
compiler='electron1.6',
iomgr_platform='uv',
labels=['portability'],
extra_args=extra_args,
inner_jobs=inner_jobs)

Loading…
Cancel
Save