Skip to content

Commit

Permalink
[Fix Python Deadlock] Guard grpc_google_default_credentials_create wi…
Browse files Browse the repository at this point in the history
…th nogil (grpc#36266)

This fix is similar to grpc#34712 but for `grpc_google_default_credentials_create` rather than `grpc_ssl_credentials_create`

Fixes grpc#36265
Fixes googleapis/python-bigtable#949

Closes grpc#36266

COPYBARA_INTEGRATE_REVIEW=grpc#36266 from parthea:repro-issue-34672 d736f6f
PiperOrigin-RevId: 623291826
  • Loading branch information
parthea authored and XuanWang-Amos committed Apr 16, 2024
1 parent a2ab898 commit b228ac6
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 8 deletions.
5 changes: 3 additions & 2 deletions src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -437,8 +437,9 @@ cdef class ComputeEngineChannelCredentials(ChannelCredentials):
raise ValueError("Call credentials may not be NULL.")

cdef grpc_channel_credentials *c(self) except *:
self._c_creds = grpc_google_default_credentials_create(self._call_creds)
return self._c_creds
with nogil:
self._c_creds = grpc_google_default_credentials_create(self._call_creds)
return self._c_creds


def channel_credentials_compute_engine(call_creds):
Expand Down
53 changes: 47 additions & 6 deletions src/python/grpcio_tests/tests/unit/_api_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,20 +112,61 @@ def testChannelConnectivity(self):


class ChannelTest(unittest.TestCase):
def test_secure_channel(self):
channel_credentials = grpc.ssl_channel_credentials()
channel = grpc.secure_channel("google.com:443", channel_credentials)
def compute_engine_channel_credentials(self):
class TestCallCredentials(grpc.AuthMetadataPlugin):
def __call__(self, context, callback):
callback((), None)

test_call_credentials = TestCallCredentials()
call_credentials = grpc.metadata_call_credentials(
test_call_credentials, "test call credentials"
)
return grpc.compute_engine_channel_credentials(call_credentials)

def test_ssl_secure_channel(self):
channel = grpc.secure_channel(
"google.com:443", grpc.ssl_channel_credentials()
)
channel.close()

def test_compute_engine_secure_channel(self):
channel = grpc.secure_channel(
"google.com:443", self.compute_engine_channel_credentials()
)
channel.close()

def test_multiple_secure_channel(self):
def test_multiple_ssl_secure_channel(self):
_THREAD_COUNT = 10
wait_group = test_common.WaitGroup(_THREAD_COUNT)

def create_secure_channel():
wait_group.done()
wait_group.wait()
channel = grpc.secure_channel(
"google.com:443", grpc.ssl_channel_credentials()
)
channel.close()

threads = []
for _ in range(_THREAD_COUNT):
thread = threading.Thread(target=create_secure_channel)
thread.setDaemon(True)
thread.start()
threads.append(thread)

for thread in threads:
thread.join()

def test_multiple_compute_engine_secure_channel(self):
_THREAD_COUNT = 10
wait_group = test_common.WaitGroup(_THREAD_COUNT)

def create_secure_channel():
channel_credentials = grpc.ssl_channel_credentials()
wait_group.done()
wait_group.wait()
channel = grpc.secure_channel("google.com:443", channel_credentials)
channel = grpc.secure_channel(
"google.com:443", self.compute_engine_channel_credentials()
)
channel.close()

threads = []
Expand Down

0 comments on commit b228ac6

Please sign in to comment.