aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Masood Malekghassemi <atash@google.com>2017-01-12 17:16:48 -0800
committerGravatar Masood Malekghassemi <atash@google.com>2017-01-13 17:40:30 -0800
commit62d895bc77ec9a06659ad66bddc7930eb3ce24fe (patch)
treebbdc2a54d355279413961ac8fc81a6060a0d0e8b
parent38842566f72ca51762df4dac4677bfdbd15d16d7 (diff)
Paper-over Python errors
This reads directly off of the slices rather than ref'ing and unref'ing them. There's likely some silliness w.r.t. interned slices and references to them outliving their associated call objects, but we are just ignoring that for now.
-rw-r--r--.gitignore5
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi6
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/records.pxd.pxi5
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi57
-rw-r--r--src/python/grpcio/grpc/_server.py2
5 files changed, 56 insertions, 19 deletions
diff --git a/.gitignore b/.gitignore
index 3112445176..06a3d25c3d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,7 +31,7 @@ coverage
# python compiled objects
*.pyc
-#eclipse project files
+# eclipse project files
.cproject
.project
.settings
@@ -110,3 +110,6 @@ bazel-genfiles
bazel-grpc
bazel-out
bazel-testlogs
+
+# Debug output
+gdb.txt
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi
index a258ba4063..2b5cce88a4 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi
@@ -70,6 +70,8 @@ cdef class CompletionQueue:
operation_call = tag.operation_call
request_call_details = tag.request_call_details
request_metadata = tag.request_metadata
+ if request_metadata is not None:
+ request_metadata._claim_slice_ownership()
batch_operations = tag.batch_operations
if tag.is_new_request:
# Stuff in the tag not explicitly handled by us needs to live through
@@ -91,7 +93,7 @@ cdef class CompletionQueue:
c_deadline = gpr_inf_future(GPR_CLOCK_REALTIME)
if deadline is not None:
c_deadline = deadline.c_time
-
+
while True:
c_timeout = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), c_increment)
if gpr_time_cmp(c_timeout, c_deadline) > 0:
@@ -100,7 +102,7 @@ cdef class CompletionQueue:
self.c_completion_queue, c_timeout, NULL)
if event.type != GRPC_QUEUE_TIMEOUT or gpr_time_cmp(c_timeout, c_deadline) == 0:
break;
-
+
# Handle any signals
with gil:
cpython.PyErr_CheckSignals()
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/records.pxd.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/records.pxd.pxi
index 870da51fa8..3644b7cdae 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/records.pxd.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/records.pxd.pxi
@@ -77,6 +77,8 @@ cdef class Slice:
cdef void _assign_slice(self, grpc_slice new_slice) nogil
@staticmethod
cdef Slice from_slice(grpc_slice slice)
+ @staticmethod
+ cdef bytes bytes_from_slice(grpc_slice slice)
cdef class ByteBuffer:
@@ -113,7 +115,10 @@ cdef class Metadatum:
cdef class Metadata:
cdef grpc_metadata_array c_metadata_array
+ cdef bint owns_metadata_slices
cdef object metadata
+ cdef void _claim_slice_ownership(self) nogil
+ cdef void _drop_slice_ownership(self) nogil
cdef class Operation:
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi
index b7a75cd97a..30e7b9657a 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi
@@ -189,11 +189,11 @@ cdef class CallDetails:
@property
def method(self):
- return Slice.from_slice(self.c_details.method).bytes()
+ return Slice.bytes_from_slice(self.c_details.method)
@property
def host(self):
- return Slice.from_slice(self.c_details.host).bytes()
+ return Slice.bytes_from_slice(self.c_details.host)
@property
def deadline(self):
@@ -251,12 +251,16 @@ cdef class Slice:
self._assign_slice(slice)
return self
- def bytes(self):
+ @staticmethod
+ cdef bytes bytes_from_slice(grpc_slice slice):
with nogil:
- pointer = grpc_slice_start_ptr(self.c_slice)
- length = grpc_slice_length(self.c_slice)
+ pointer = grpc_slice_start_ptr(slice)
+ length = grpc_slice_length(slice)
return (<char *>pointer)[:length]
+ def bytes(self):
+ return Slice.bytes_from_slice(self.c_slice)
+
def __dealloc__(self):
with nogil:
grpc_slice_unref(self.c_slice)
@@ -466,13 +470,14 @@ cdef class _MetadataIterator:
cdef class Metadata:
def __cinit__(self, metadata):
- grpc_init()
+ with nogil:
+ grpc_init()
+ grpc_metadata_array_init(&self.c_metadata_array)
+ self.owns_metadata_slices = False
self.metadata = list(metadata)
- for metadatum in metadata:
+ for metadatum in self.metadata:
if not isinstance(metadatum, Metadatum):
raise TypeError("expected list of Metadatum")
- with nogil:
- grpc_metadata_array_init(&self.c_metadata_array)
self.c_metadata_array.count = len(self.metadata)
self.c_metadata_array.capacity = len(self.metadata)
with nogil:
@@ -484,23 +489,43 @@ cdef class Metadata:
(<Metadatum>self.metadata[i]).c_metadata)
def __dealloc__(self):
- # this frees the allocated memory for the grpc_metadata_array (although
- # it'd be nice if that were documented somewhere...)
- # TODO(atash): document this in the C core
- grpc_metadata_array_destroy(&self.c_metadata_array)
- grpc_shutdown()
+ with nogil:
+ self._drop_slice_ownership()
+ # this frees the allocated memory for the grpc_metadata_array (although
+ # it'd be nice if that were documented somewhere...)
+ # TODO(atash): document this in the C core
+ grpc_metadata_array_destroy(&self.c_metadata_array)
+ grpc_shutdown()
def __len__(self):
return self.c_metadata_array.count
def __getitem__(self, size_t i):
+ if i >= self.c_metadata_array.count:
+ raise IndexError
return Metadatum(
- key=Slice.from_slice(self.c_metadata_array.metadata[i].key).bytes(),
- value=Slice.from_slice(self.c_metadata_array.metadata[i].value).bytes())
+ key=Slice.bytes_from_slice(self.c_metadata_array.metadata[i].key),
+ value=Slice.bytes_from_slice(self.c_metadata_array.metadata[i].value))
def __iter__(self):
return _MetadataIterator(self)
+ cdef void _claim_slice_ownership(self) nogil:
+ if self.owns_metadata_slices:
+ return
+ for i in range(self.c_metadata_array.count):
+ grpc_slice_ref(self.c_metadata_array.metadata[i].key)
+ grpc_slice_ref(self.c_metadata_array.metadata[i].value)
+ self.owns_metadata_slices = True
+
+ cdef void _drop_slice_ownership(self) nogil:
+ if not self.owns_metadata_slices:
+ return
+ for i in range(self.c_metadata_array.count):
+ grpc_slice_unref(self.c_metadata_array.metadata[i].key)
+ grpc_slice_unref(self.c_metadata_array.metadata[i].value)
+ self.owns_metadata_slices = False
+
cdef class Operation:
diff --git a/src/python/grpcio/grpc/_server.py b/src/python/grpcio/grpc/_server.py
index 5223712dfa..75f661340c 100644
--- a/src/python/grpcio/grpc/_server.py
+++ b/src/python/grpcio/grpc/_server.py
@@ -576,6 +576,8 @@ def _handle_with_method_handler(rpc_event, method_handler, thread_pool):
def _handle_call(rpc_event, generic_handlers, thread_pool):
+ if not rpc_event.success:
+ return None
if rpc_event.request_call_details.method is not None:
method_handler = _find_method_handler(rpc_event, generic_handlers)
if method_handler is None: