_signal_client.py
Go to the documentation of this file.
1 # Copyright 2019 the gRPC authors.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 """Client for testing responsiveness to signals."""
15 
16 from __future__ import print_function
17 
18 import argparse
19 import functools
20 import logging
21 import signal
22 import sys
23 
24 import grpc
25 
26 SIGTERM_MESSAGE = "Handling sigterm!"
27 
28 UNARY_UNARY = "/test/Unary"
29 UNARY_STREAM = "/test/ServerStreaming"
30 
31 _MESSAGE = b'\x00\x00\x00'
32 
33 _ASSERTION_MESSAGE = "Control flow should never reach here."
34 
35 # NOTE(gnossen): We use a global variable here so that the signal handler can be
36 # installed before the RPC begins. If we do not do this, then we may receive the
37 # SIGINT before the signal handler is installed. I'm not happy with per-process
38 # global state, but the per-process global state that is signal handlers
39 # somewhat forces my hand.
40 per_process_rpc_future = None
41 
42 
43 def handle_sigint(unused_signum, unused_frame):
44  print(SIGTERM_MESSAGE)
45  if per_process_rpc_future is not None:
46  per_process_rpc_future.cancel()
47  sys.stderr.flush()
48  # This sys.exit(0) avoids an exception caused by the cancelled RPC.
49  sys.exit(0)
50 
51 
52 def main_unary(server_target):
53  """Initiate a unary RPC to be interrupted by a SIGINT."""
54  global per_process_rpc_future # pylint: disable=global-statement
55  with grpc.insecure_channel(server_target) as channel:
56  multicallable = channel.unary_unary(UNARY_UNARY)
57  signal.signal(signal.SIGINT, handle_sigint)
58  per_process_rpc_future = multicallable.future(_MESSAGE,
59  wait_for_ready=True)
60  result = per_process_rpc_future.result()
61  assert False, _ASSERTION_MESSAGE
62 
63 
64 def main_streaming(server_target):
65  """Initiate a streaming RPC to be interrupted by a SIGINT."""
66  global per_process_rpc_future # pylint: disable=global-statement
67  with grpc.insecure_channel(server_target) as channel:
68  signal.signal(signal.SIGINT, handle_sigint)
69  per_process_rpc_future = channel.unary_stream(UNARY_STREAM)(
70  _MESSAGE, wait_for_ready=True)
71  for result in per_process_rpc_future:
72  pass
73  assert False, _ASSERTION_MESSAGE
74 
75 
76 def main_unary_with_exception(server_target):
77  """Initiate a unary RPC with a signal handler that will raise."""
78  channel = grpc.insecure_channel(server_target)
79  try:
80  channel.unary_unary(UNARY_UNARY)(_MESSAGE, wait_for_ready=True)
81  except KeyboardInterrupt:
82  sys.stderr.write("Running signal handler.\n")
83  sys.stderr.flush()
84 
85  # This call should not freeze.
86  channel.close()
87 
88 
89 def main_streaming_with_exception(server_target):
90  """Initiate a streaming RPC with a signal handler that will raise."""
91  channel = grpc.insecure_channel(server_target)
92  try:
93  for _ in channel.unary_stream(UNARY_STREAM)(_MESSAGE,
94  wait_for_ready=True):
95  pass
96  except KeyboardInterrupt:
97  sys.stderr.write("Running signal handler.\n")
98  sys.stderr.flush()
99 
100  # This call should not freeze.
101  channel.close()
102 
103 
104 if __name__ == '__main__':
105  parser = argparse.ArgumentParser(description='Signal test client.')
106  parser.add_argument('server', help='Server target')
107  parser.add_argument('arity', help='Arity', choices=('unary', 'streaming'))
108  parser.add_argument('--exception',
109  help='Whether the signal throws an exception',
110  action='store_true')
111  parser.add_argument('--gevent',
112  help='Whether to run under gevent.',
113  action='store_true')
114  args = parser.parse_args()
115  if args.gevent:
116  from gevent import monkey
117  import gevent.util
118 
119  monkey.patch_all()
120 
123 
124  if args.arity == 'unary' and not args.exception:
125  main_unary(args.server)
126  elif args.arity == 'streaming' and not args.exception:
127  main_streaming(args.server)
128  elif args.arity == 'unary' and args.exception:
129  main_unary_with_exception(args.server)
130  else:
131  main_streaming_with_exception(args.server)
grpc.insecure_channel
def insecure_channel(target, options=None, compression=None)
Definition: src/python/grpcio/grpc/__init__.py:1962
grpc::experimental.gevent.init_gevent
def init_gevent()
Definition: gevent.py:19
tests.unit._signal_client.main_unary
def main_unary(server_target)
Definition: _signal_client.py:52
tests.unit._signal_client.main_unary_with_exception
def main_unary_with_exception(server_target)
Definition: _signal_client.py:76
tests.unit._signal_client.main_streaming_with_exception
def main_streaming_with_exception(server_target)
Definition: _signal_client.py:89
tests.unit._signal_client.main_streaming
def main_streaming(server_target)
Definition: _signal_client.py:64
tests.unit._signal_client.handle_sigint
def handle_sigint(unused_signum, unused_frame)
Definition: _signal_client.py:43
grpc::experimental.gevent
Definition: gevent.py:1


grpc
Author(s):
autogenerated on Thu Mar 13 2025 02:58:27