def testJoinTimeoutSlowTarget(self): event = threading.Event() def target(): event.wait(_LONG_TIME) cleanup_thread = _common.CleanupThread(behavior=cleanup, target=target) cleanup_thread.start() start_time = time.time() cleanup_thread.join(_SHORT_TIME) end_time = time.time() self.assertAlmostEqual( _SHORT_TIME, end_time - start_time, delta=_EPSILON) event.set()
def _consume_request_iterator(request_iterator, state, call, request_serializer): event_handler = _event_handler(state, call, None) def consume_request_iterator(): for request in request_iterator: serialized_request = _common.serialize(request, request_serializer) with state.condition: if state.code is None and not state.cancelled: if serialized_request is None: call.cancel() details = 'Exception serializing request!' _abort(state, grpc.StatusCode.INTERNAL, details) return else: operations = (cygrpc.operation_send_message( serialized_request, _EMPTY_FLAGS), ) call.start_client_batch(cygrpc.Operations(operations), event_handler) state.due.add(cygrpc.OperationType.send_message) while True: state.condition.wait() if state.code is None: if cygrpc.OperationType.send_message not in state.due: break else: return else: return with state.condition: if state.code is None: operations = ( cygrpc.operation_send_close_from_client(_EMPTY_FLAGS), ) call.start_client_batch(cygrpc.Operations(operations), event_handler) state.due.add(cygrpc.OperationType.send_close_from_client) def stop_consumption_thread(timeout): with state.condition: if state.code is None: call.cancel() state.cancelled = True _abort(state, grpc.StatusCode.CANCELLED, 'Cancelled!') state.condition.notify_all() consumption_thread = _common.CleanupThread(stop_consumption_thread, target=consume_request_iterator) consumption_thread.start()
def _start(state): with state.lock: if state.stage is not _ServerStage.STOPPED: raise ValueError('Cannot start already-started server!') state.server.start() state.stage = _ServerStage.STARTED _request_call(state) def cleanup_server(timeout): if timeout is None: _stop(state, _UNEXPECTED_EXIT_SERVER_GRACE).wait() else: _stop(state, timeout).wait() thread = _common.CleanupThread( cleanup_server, target=_serve, args=(state,)) thread.start()
def testTargetInvocation(self): event = threading.Event() def target(arg1, arg2, arg3=None): self.assertEqual('arg1', arg1) self.assertEqual('arg2', arg2) self.assertEqual('arg3', arg3) event.set() cleanup_thread = _common.CleanupThread(behavior=lambda x: None, target=target, name='test-name', args=('arg1', 'arg2'), kwargs={'arg3': 'arg3'}) cleanup_thread.start() cleanup_thread.join() self.assertEqual(cleanup_thread.name, 'test-name') self.assertTrue(event.is_set())
def _subscribe(state, callback, try_to_connect): with state.lock: if not state.callbacks_and_connectivities and not state.polling: polling_thread = _common.CleanupThread( lambda timeout: _moot(state), target=_poll_connectivity, args=(state, state.channel, bool(try_to_connect))) polling_thread.start() state.polling = True state.callbacks_and_connectivities.append([callback, None]) elif not state.delivering and state.connectivity is not None: _spawn_delivery(state, (callback, )) state.try_to_connect |= bool(try_to_connect) state.callbacks_and_connectivities.append( [callback, state.connectivity]) else: state.try_to_connect |= bool(try_to_connect) state.callbacks_and_connectivities.append([callback, None])
def _run_request_pipe_thread(request_iterator, request_consumer, servicer_context): thread_joined = threading.Event() def pipe_requests(): for request in request_iterator: if not servicer_context.is_active() or thread_joined.is_set(): return request_consumer.consume(request) if not servicer_context.is_active() or thread_joined.is_set(): return request_consumer.terminate() def stop_request_pipe(timeout): thread_joined.set() request_pipe_thread = _common.CleanupThread( stop_request_pipe, target=pipe_requests) request_pipe_thread.start()
def _run_channel_spin_thread(state): def channel_spin(): while True: event = state.channel.next_call_event() call_completed = event.tag(event) if call_completed: with state.lock: state.managed_calls -= 1 if state.managed_calls == 0: return def stop_channel_spin(timeout): # pylint: disable=unused-argument with state.lock: state.channel.close(cygrpc.StatusCode.cancelled, 'Channel spin thread cleaned up!') channel_spin_thread = _common.CleanupThread(stop_channel_spin, target=channel_spin) channel_spin_thread.start()
def _start(state): with state.lock: if state.stage is not _ServerStage.STOPPED: raise ValueError('Cannot start already-started server!') state.server.start() state.stage = _ServerStage.STARTED _request_call(state) def cleanup_server(timeout): if timeout is None: _stop(state, state.exit_grace, state.exit_shutdown_handler_grace).wait() else: _stop(state, timeout, 0).wait() thread = _common.CleanupThread(cleanup_server, target=_serve, args=(state, )) thread.start()
def _run_channel_spin_thread(state): def channel_spin(): while True: event = state.completion_queue.poll() completed_call = event.tag(event) if completed_call is not None: with state.lock: state.managed_calls.remove(completed_call) if not state.managed_calls: state.managed_calls = None return def stop_channel_spin(timeout): with state.lock: if state.managed_calls is not None: for call in state.managed_calls: call.cancel() channel_spin_thread = _common.CleanupThread(stop_channel_spin, target=channel_spin) channel_spin_thread.start()
def _consume_request_iterator(request_iterator, state, call, request_serializer, event_handler): def consume_request_iterator(): # pylint: disable=too-many-branches while True: try: request = next(request_iterator) except StopIteration: break except Exception: # pylint: disable=broad-except code = grpc.StatusCode.UNKNOWN details = 'Exception iterating requests!' logging.exception(details) call.cancel(_common.STATUS_CODE_TO_CYGRPC_STATUS_CODE[code], details) _abort(state, code, details) return serialized_request = _common.serialize(request, request_serializer) with state.condition: if state.code is None and not state.cancelled: if serialized_request is None: code = grpc.StatusCode.INTERNAL # pylint: disable=redefined-variable-type details = 'Exception serializing request!' call.cancel( _common.STATUS_CODE_TO_CYGRPC_STATUS_CODE[code], details) _abort(state, code, details) return else: operations = (cygrpc.SendMessageOperation( serialized_request, _EMPTY_FLAGS), ) operating = call.operate(operations, event_handler) if operating: state.due.add(cygrpc.OperationType.send_message) else: return while True: state.condition.wait() if state.code is None: if cygrpc.OperationType.send_message not in state.due: break else: return else: return with state.condition: if state.code is None: operations = ( cygrpc.SendCloseFromClientOperation(_EMPTY_FLAGS), ) operating = call.operate(operations, event_handler) if operating: state.due.add(cygrpc.OperationType.send_close_from_client) def stop_consumption_thread(timeout): # pylint: disable=unused-argument with state.condition: if state.code is None: code = grpc.StatusCode.CANCELLED details = 'Consumption thread cleaned up!' call.cancel(_common.STATUS_CODE_TO_CYGRPC_STATUS_CODE[code], details) state.cancelled = True _abort(state, code, details) state.condition.notify_all() consumption_thread = _common.CleanupThread(stop_consumption_thread, target=consume_request_iterator) consumption_thread.start()