aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rwxr-xr-xexamples/ruby/route_guide/route_guide_client.rb4
-rw-r--r--include/grpc/support/tls_gcc.h46
-rw-r--r--src/csharp/README.md15
-rw-r--r--src/python/grpcio/tests/_runner.py91
-rw-r--r--test/core/surface/concurrent_connectivity_test.c34
5 files changed, 102 insertions, 88 deletions
diff --git a/examples/ruby/route_guide/route_guide_client.rb b/examples/ruby/route_guide/route_guide_client.rb
index 715a3c08c5..86dd1fe6ca 100755
--- a/examples/ruby/route_guide/route_guide_client.rb
+++ b/examples/ruby/route_guide/route_guide_client.rb
@@ -38,6 +38,7 @@ lib_dir = File.join(File.dirname(this_dir), 'lib')
$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
require 'grpc'
+require 'multi_json'
require 'route_guide_services'
include Routeguide
@@ -115,9 +116,8 @@ def run_record_route(stub, features)
p 'RecordRoute'
p '-----------'
points_on_route = 10 # arbitrary
- deadline = points_on_route # as delay b/w each is max 1 second
reqs = RandomRoute.new(features, points_on_route)
- resp = stub.record_route(reqs.each, deadline)
+ resp = stub.record_route(reqs.each)
p "summary: #{resp.inspect}"
end
diff --git a/include/grpc/support/tls_gcc.h b/include/grpc/support/tls_gcc.h
index a697ad05b0..5aebe6ded9 100644
--- a/include/grpc/support/tls_gcc.h
+++ b/include/grpc/support/tls_gcc.h
@@ -1,6 +1,6 @@
/*
*
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,9 +34,51 @@
#ifndef GRPC_SUPPORT_TLS_GCC_H
#define GRPC_SUPPORT_TLS_GCC_H
+#include <stdbool.h>
+
+#include <grpc/support/log.h>
+
/* Thread local storage based on gcc compiler primitives.
#include tls.h to use this - and see that file for documentation */
+#ifndef NDEBUG
+
+struct gpr_gcc_thread_local {
+ intptr_t value;
+ bool *inited;
+};
+
+#define GPR_TLS_DECL(name) \
+ static bool name##_inited = false; \
+ static __thread struct gpr_gcc_thread_local name = {0, &(name##_inited)}
+
+#define gpr_tls_init(tls) \
+ do { \
+ GPR_ASSERT(*((tls)->inited) == false); \
+ *((tls)->inited) = true; \
+ } while (0)
+
+/* It is allowed to call gpr_tls_init after gpr_tls_destroy is called. */
+#define gpr_tls_destroy(tls) \
+ do { \
+ GPR_ASSERT(*((tls)->inited)); \
+ *((tls)->inited) = false; \
+ } while (0)
+
+#define gpr_tls_set(tls, new_value) \
+ do { \
+ GPR_ASSERT(*((tls)->inited)); \
+ (tls)->value = (new_value); \
+ } while (0)
+
+#define gpr_tls_get(tls) \
+ ({ \
+ GPR_ASSERT(*((tls)->inited)); \
+ (tls)->value; \
+ })
+
+#else /* NDEBUG */
+
struct gpr_gcc_thread_local {
intptr_t value;
};
@@ -53,4 +95,6 @@ struct gpr_gcc_thread_local {
#define gpr_tls_set(tls, new_value) (((tls)->value) = (new_value))
#define gpr_tls_get(tls) ((tls)->value)
+#endif /* NDEBUG */
+
#endif
diff --git a/src/csharp/README.md b/src/csharp/README.md
index b4fa945ac9..201c5ab0b5 100644
--- a/src/csharp/README.md
+++ b/src/csharp/README.md
@@ -55,16 +55,11 @@ If you are a user of gRPC C#, go to Usage section above.
**Windows**
-- The grpc_csharp_ext native library needs to be built so you can build the gRPC C# solution. You can
- either build the native solution in `vsprojects/grpc_csharp_ext.sln` from Visual Studio manually, or you can use
- a convenience batch script that builds everything for you.
+- The grpc_csharp_ext native library needs to be built so you can build the gRPC C# solution. Open the
+ solution `vsprojects/grpc_csharp_ext.sln` in Visual Studio and build it.
- ```
- > REM From src/csharp directory
- > buildall.bat
- ```
-
-- Open Grpc.sln using Visual Studio.
+- Open `src\csharp\Grpc.sln` (path is relative to gRPC repository root)
+ using Visual Studio
**Linux**
@@ -79,7 +74,7 @@ If you are a user of gRPC C#, go to Usage section above.
**Mac OS X**
- The grpc_csharp_ext native library needs to be built so you can build the gRPC C# solution.
-
+
```sh
# from the gRPC repository root
$ tools/run_tests/run_tests.py -c dbg -l csharp --build_only
diff --git a/src/python/grpcio/tests/_runner.py b/src/python/grpcio/tests/_runner.py
index 32a31ce00e..3b5ca03dd9 100644
--- a/src/python/grpcio/tests/_runner.py
+++ b/src/python/grpcio/tests/_runner.py
@@ -35,6 +35,7 @@ import os
import select
import signal
import sys
+import tempfile
import threading
import time
import unittest
@@ -43,72 +44,47 @@ import uuid
from tests import _loader
from tests import _result
-# This number needs to be large enough to outpace output on stdout and stderr
-# from the gRPC core, otherwise we could end up in a potential deadlock. This
-# stems from the OS waiting on someone to clear a filled pipe buffer while the
-# GIL is held from a write to stderr from gRPC core, but said someone is in
-# Python code thus necessitating GIL acquisition.
-_READ_BYTES = 2**20
+class CaptureFile(object):
+ """A context-managed file to redirect output to a byte array.
-class CapturePipe(object):
- """A context-manager pipe to redirect output to a byte array.
+ Use by invoking `start` (`__enter__`) and at some point invoking `stop`
+ (`__exit__`). At any point after the initial call to `start` call `output` to
+ get the current redirected output. Note that we don't currently use file
+ locking, so calling `output` between calls to `start` and `stop` may muddle
+ the result (you should only be doing this during a Python-handled interrupt as
+ a last ditch effort to provide output to the user).
Attributes:
- _redirect_fd (int): File descriptor of file to redirect writes from.
+ _redirected_fd (int): File descriptor of file to redirect writes from.
_saved_fd (int): A copy of the original value of the redirected file
descriptor.
- _read_thread (threading.Thread or None): Thread upon which reads through the
- pipe are performed. Only non-None when self is started.
- _read_fd (int or None): File descriptor of the read end of the redirect
- pipe. Only non-None when self is started.
- _write_fd (int or None): File descriptor of the write end of the redirect
- pipe. Only non-None when self is started.
- output (bytearray or None): Redirected output from writes to the redirected
- file descriptor. Only valid during and after self has started.
+ _into_file (TemporaryFile or None): File to which writes are redirected.
+ Only non-None when self is started.
"""
def __init__(self, fd):
- self._redirect_fd = fd
- self._saved_fd = os.dup(self._redirect_fd)
- self._read_thread = None
- self._read_fd = None
- self._write_fd = None
- self.output = None
+ self._redirected_fd = fd
+ self._saved_fd = os.dup(self._redirected_fd)
+ self._into_file = None
+
+ def output(self):
+ """Get all output from the redirected-to file if it exists."""
+ if self._into_file:
+ self._into_file.seek(0)
+ return bytes(self._into_file.read())
+ else:
+ return bytes()
def start(self):
"""Start redirection of writes to the file descriptor."""
- self._read_fd, self._write_fd = os.pipe()
- os.dup2(self._write_fd, self._redirect_fd)
- flags = fcntl.fcntl(self._read_fd, fcntl.F_GETFL)
- fcntl.fcntl(self._read_fd, fcntl.F_SETFL, flags | os.O_NONBLOCK)
- self._read_thread = threading.Thread(target=self._read)
- # If the user wants to exit from the Python program and hits ctrl-C and the
- # read thread is somehow deadlocked with something else, the Python code may
- # refuse to exit. This prevents that by making the read thread second-class.
- self._read_thread.daemon = True
- self._read_thread.start()
+ self._into_file = tempfile.TemporaryFile()
+ os.dup2(self._into_file.fileno(), self._redirected_fd)
def stop(self):
"""Stop redirection of writes to the file descriptor."""
- os.close(self._write_fd)
- os.dup2(self._saved_fd, self._redirect_fd) # auto-close self._redirect_fd
- self._read_thread.join()
- self._read_thread = None
- # we waited for the read thread to finish, so _read_fd has been read and we
- # can close it.
- os.close(self._read_fd)
-
- def _read(self):
- """Read-thread target for self."""
- self.output = bytearray()
- while True:
- select.select([self._read_fd], [], [])
- read_bytes = os.read(self._read_fd, _READ_BYTES)
- if read_bytes:
- self.output.extend(read_bytes)
- else:
- break
+ # n.b. this dup2 call auto-closes self._redirected_fd
+ os.dup2(self._saved_fd, self._redirected_fd)
def write_bypass(self, value):
"""Bypass the redirection and write directly to the original file.
@@ -170,8 +146,8 @@ class Runner(object):
result_out = StringIO.StringIO()
result = _result.TerminalResult(
result_out, id_map=lambda case: case_id_by_case[case])
- stdout_pipe = CapturePipe(sys.stdout.fileno())
- stderr_pipe = CapturePipe(sys.stderr.fileno())
+ stdout_pipe = CaptureFile(sys.stdout.fileno())
+ stderr_pipe = CaptureFile(sys.stderr.fileno())
kill_flag = [False]
def sigint_handler(signal_number, frame):
@@ -182,7 +158,8 @@ class Runner(object):
def fault_handler(signal_number, frame):
stdout_pipe.write_bypass(
'Received fault signal {}\nstdout:\n{}\n\nstderr:{}\n'
- .format(signal_number, stdout_pipe.output, stderr_pipe.output))
+ .format(signal_number, stdout_pipe.output(),
+ stderr_pipe.output()))
os._exit(1)
def check_kill_self():
@@ -191,9 +168,9 @@ class Runner(object):
result.stopTestRun()
stdout_pipe.write_bypass(result_out.getvalue())
stdout_pipe.write_bypass(
- '\ninterrupted stdout:\n{}\n'.format(stdout_pipe.output))
+ '\ninterrupted stdout:\n{}\n'.format(stdout_pipe.output()))
stderr_pipe.write_bypass(
- '\ninterrupted stderr:\n{}\n'.format(stderr_pipe.output))
+ '\ninterrupted stderr:\n{}\n'.format(stderr_pipe.output()))
os._exit(1)
signal.signal(signal.SIGINT, sigint_handler)
signal.signal(signal.SIGSEGV, fault_handler)
@@ -223,7 +200,7 @@ class Runner(object):
# re-raise the exception after forcing the with-block to end
raise
result.set_output(
- augmented_case.case, stdout_pipe.output, stderr_pipe.output)
+ augmented_case.case, stdout_pipe.output(), stderr_pipe.output())
sys.stdout.write(result_out.getvalue())
sys.stdout.flush()
result_out.truncate(0)
diff --git a/test/core/surface/concurrent_connectivity_test.c b/test/core/surface/concurrent_connectivity_test.c
index 4d3b7bf22a..96761b0502 100644
--- a/test/core/surface/concurrent_connectivity_test.c
+++ b/test/core/surface/concurrent_connectivity_test.c
@@ -40,29 +40,27 @@
#include "test/core/util/test_config.h"
#define NUM_THREADS 100
-static grpc_channel* channels[NUM_THREADS];
-static grpc_completion_queue* queues[NUM_THREADS];
+#define NUM_OUTER_LOOPS 10
+#define NUM_INNER_LOOPS 10
+#define DELAY_MILLIS 10
+#define POLL_MILLIS 3000
-void create_loop_destroy(void* actually_an_int) {
- int thread_index = (int)(intptr_t)(actually_an_int);
- for (int i = 0; i < 10; ++i) {
+void create_loop_destroy(void* unused) {
+ for (int i = 0; i < NUM_OUTER_LOOPS; ++i) {
grpc_completion_queue* cq = grpc_completion_queue_create(NULL);
grpc_channel* chan = grpc_insecure_channel_create("localhost", NULL, NULL);
- channels[thread_index] = chan;
- queues[thread_index] = cq;
-
- for (int j = 0; j < 10; ++j) {
- gpr_timespec later_time = GRPC_TIMEOUT_MILLIS_TO_DEADLINE(10);
+ for (int j = 0; j < NUM_INNER_LOOPS; ++j) {
+ gpr_timespec later_time = GRPC_TIMEOUT_MILLIS_TO_DEADLINE(DELAY_MILLIS);
grpc_connectivity_state state =
grpc_channel_check_connectivity_state(chan, 1);
grpc_channel_watch_connectivity_state(chan, state, later_time, cq, NULL);
- GPR_ASSERT(grpc_completion_queue_next(cq,
- GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3),
- NULL).type == GRPC_OP_COMPLETE);
+ gpr_timespec poll_time = GRPC_TIMEOUT_MILLIS_TO_DEADLINE(POLL_MILLIS);
+ GPR_ASSERT(grpc_completion_queue_next(cq, poll_time, NULL).type ==
+ GRPC_OP_COMPLETE);
}
- grpc_channel_destroy(channels[thread_index]);
- grpc_completion_queue_destroy(queues[thread_index]);
+ grpc_channel_destroy(chan);
+ grpc_completion_queue_destroy(cq);
}
}
@@ -70,12 +68,12 @@ int main(int argc, char** argv) {
grpc_test_init(argc, argv);
grpc_init();
gpr_thd_id threads[NUM_THREADS];
- for (intptr_t i = 0; i < NUM_THREADS; ++i) {
+ for (size_t i = 0; i < NUM_THREADS; ++i) {
gpr_thd_options options = gpr_thd_options_default();
gpr_thd_options_set_joinable(&options);
- gpr_thd_new(&threads[i], create_loop_destroy, (void*)i, &options);
+ gpr_thd_new(&threads[i], create_loop_destroy, NULL, &options);
}
- for (int i = 0; i < NUM_THREADS; ++i) {
+ for (size_t i = 0; i < NUM_THREADS; ++i) {
gpr_thd_join(threads[i]);
}
grpc_shutdown();