Adds a ready event to BackgroundConsumer to wait on start. (#7499)
* Adds a ready event to BackgroundConsumer to allow waiting for the background thread to start
diff --git a/google/api_core/bidi.py b/google/api_core/bidi.py
index 795a8d2..68d1300 100644
--- a/google/api_core/bidi.py
+++ b/google/api_core/bidi.py
@@ -505,8 +505,9 @@
# when the RPC has terminated.
self.resume()
- def _thread_main(self):
+ def _thread_main(self, ready):
try:
+ ready.set()
self._bidi_rpc.add_done_callback(self._on_call_done)
self._bidi_rpc.open()
@@ -555,11 +556,19 @@
def start(self):
"""Start the background thread and begin consuming the thread."""
with self._operational_lock:
+ ready = threading.Event()
thread = threading.Thread(
- name=_BIDIRECTIONAL_CONSUMER_NAME, target=self._thread_main
+ name=_BIDIRECTIONAL_CONSUMER_NAME,
+ target=self._thread_main,
+ args=(ready,)
)
thread.daemon = True
thread.start()
+ # Other parts of the code rely on `thread.is_alive` which
+ # isn't sufficient to know if a thread is active, just that it may
+ # soon be active. This can cause races. Further protect
+ # against races by using a ready event and wait on it to be set.
+ ready.wait()
self._thread = thread
_LOGGER.debug("Started helper thread %s", thread.name)