summaryrefslogtreecommitdiffstats
path: root/contrib/libs/grpc
diff options
context:
space:
mode:
authorthegeorg <[email protected]>2025-05-13 20:08:22 +0300
committerthegeorg <[email protected]>2025-05-13 20:25:27 +0300
commitf555b850f3b9d67929a251fe2a56cf901da621f9 (patch)
treefe5b00367272b59c3dbfe4943ce79ab057dfa215 /contrib/libs/grpc
parentfe3406147abc7bfd5a42610da6cc83f5a7774b0e (diff)
contrib/libs/grpc: Backport patch to fix race condition during openssl shutdown
Ensure OPENSSL global clean up happens after gRPC shutdown completes. OPENSSL registers an exit handler to clean up global objects, which may happen before gRPC removes all references to OPENSSL. commit_hash:7120e72fcbfbac3997483f3551f864ff9b8ec3a4
Diffstat (limited to 'contrib/libs/grpc')
-rw-r--r--contrib/libs/grpc/patches/pr37768-openssl-deinit.patch111
-rw-r--r--contrib/libs/grpc/src/core/lib/surface/init.cc15
-rw-r--r--contrib/libs/grpc/src/core/lib/surface/init.h5
-rw-r--r--contrib/libs/grpc/src/core/tsi/ssl_transport_security.cc8
4 files changed, 139 insertions, 0 deletions
diff --git a/contrib/libs/grpc/patches/pr37768-openssl-deinit.patch b/contrib/libs/grpc/patches/pr37768-openssl-deinit.patch
new file mode 100644
index 00000000000..d25735d163d
--- /dev/null
+++ b/contrib/libs/grpc/patches/pr37768-openssl-deinit.patch
@@ -0,0 +1,111 @@
+From cbccf975d07da4b6ddb716518de58917348c3e14 Mon Sep 17 00:00:00 2001
+From: Yousuk Seung <[email protected]>
+Date: Sat, 21 Sep 2024 15:22:10 -0700
+Subject: [PATCH] [ssl] Ensure OPENSSL global cleanup happens after gRPC
+ shutdowns (#37768)
+
+Ensure OPENSSL global clean up happens after gRPC shutdown completes. OPENSSL registers an exit handler to clean up global objects, which may happen before gRPC removes all references to OPENSSL.
+
+<!--
+
+If you know who should review your pull request, please assign it to that
+person, otherwise the pull request would get assigned randomly.
+
+If your pull request is for a specific language, please add the appropriate
+lang label.
+
+-->
+
+Closes #37768
+
+COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/37768 from yousukseung:openssl-atexit-wait d3d1c964a837179050acebd5e82b1d1e20338611
+PiperOrigin-RevId: 677284514
+---
+ BUILD | 2 ++
+ src/core/lib/surface/init.cc | 19 ++++++++++++++
+ src/core/lib/surface/init.h | 5 ++++
+ src/core/tsi/ssl_transport_security.cc | 8 ++++++
+ test/core/surface/init_test.cc | 35 ++++++++++++++++++++++++++
+ 5 files changed, 69 insertions(+)
+
+diff --git a/src/core/lib/surface/init.cc b/src/core/lib/surface/init.cc
+index 637941ccbd3d0..233f6f97d1677 100644
+--- a/src/core/lib/surface/init.cc
++++ b/src/core/lib/surface/init.cc
+@@ -20,6 +20,8 @@
+ #include <limits.h>
+
+ #include "y_absl/base/thread_annotations.h"
++#include "y_absl/time/clock.h"
++#include "y_absl/time/time.h"
+
+ #include <grpc/fork.h>
+ #include <grpc/grpc.h>
+@@ -216,3 +218,16 @@ void grpc_maybe_wait_for_async_shutdown(void) {
+ g_shutting_down_cv->Wait(g_init_mu);
+ }
+ }
++
++bool grpc_wait_for_shutdown_with_timeout(y_absl::Duration timeout) {
++ const auto started = y_absl::Now();
++ const auto deadline = started + timeout;
++ gpr_once_init(&g_basic_init, do_basic_init);
++ grpc_core::MutexLock lock(g_init_mu);
++ while (g_initializations != 0) {
++ if (g_shutting_down_cv->WaitWithDeadline(g_init_mu, deadline)) {
++ return false;
++ }
++ }
++ return true;
++}
+diff --git a/src/core/lib/surface/init.h b/src/core/lib/surface/init.h
+index 0d0035ae30474..804b79c5d5b31 100644
+--- a/src/core/lib/surface/init.h
++++ b/src/core/lib/surface/init.h
+@@ -18,8 +18,13 @@
+ #ifndef GRPC_SRC_CORE_LIB_SURFACE_INIT_H
+ #define GRPC_SRC_CORE_LIB_SURFACE_INIT_H
+
++#include "y_absl/time/time.h"
++
+ #include <grpc/support/port_platform.h>
+
+ void grpc_maybe_wait_for_async_shutdown(void);
+
++// Returns false if the timeout expired before fully shut down.
++bool grpc_wait_for_shutdown_with_timeout(y_absl::Duration timeout);
++
+ #endif // GRPC_SRC_CORE_LIB_SURFACE_INIT_H
+diff --git a/src/core/tsi/ssl_transport_security.cc b/src/core/tsi/ssl_transport_security.cc
+index 8012dc8459cac..4718417435154 100644
+--- a/src/core/tsi/ssl_transport_security.cc
++++ b/src/core/tsi/ssl_transport_security.cc
+@@ -23,6 +23,8 @@
+ #include <limits.h>
+ #include <string.h>
+
++# include <cstdlib>
++
+ // TODO(jboeuf): refactor inet_ntop into a portability header.
+ // Note: for whomever reads this and tries to refactor this, this
+ // can't be in grpc, it has to be in gpr.
+@@ -58,6 +60,7 @@
+
+ #include "src/core/lib/gpr/useful.h"
+ #include "src/core/lib/gprpp/crash.h"
++#include "src/core/lib/surface/init.h"
+ #include "src/core/tsi/ssl/key_logging/ssl_key_logging.h"
+ #include "src/core/tsi/ssl/session_cache/ssl_session_cache.h"
+ #include "src/core/tsi/ssl_transport_security_utils.h"
+@@ -189,6 +192,11 @@ static void verified_root_cert_free(void* /*parent*/, void* ptr,
+ static void init_openssl(void) {
+ #if OPENSSL_VERSION_NUMBER >= 0x10100000
+ OPENSSL_init_ssl(0, nullptr);
++ // Ensure OPENSSL global clean up happens after gRPC shutdown completes.
++ // OPENSSL registers an exit handler to clean up global objects, which
++ // otherwise may happen before gRPC removes all references to OPENSSL. Below
++ // exit handler is guaranteed to run after OPENSSL's.
++ std::atexit([]() { grpc_wait_for_shutdown_with_timeout(y_absl::Seconds(2)); });
+ #else
+ SSL_library_init();
+ SSL_load_error_strings();
diff --git a/contrib/libs/grpc/src/core/lib/surface/init.cc b/contrib/libs/grpc/src/core/lib/surface/init.cc
index 4527f273bf6..59521f8348e 100644
--- a/contrib/libs/grpc/src/core/lib/surface/init.cc
+++ b/contrib/libs/grpc/src/core/lib/surface/init.cc
@@ -23,6 +23,8 @@
#include <limits.h>
#include "y_absl/base/thread_annotations.h"
+#include "y_absl/time/clock.h"
+#include "y_absl/time/time.h"
#include <grpc/fork.h>
#include <grpc/grpc.h>
@@ -229,3 +231,16 @@ void grpc_maybe_wait_for_async_shutdown(void) {
g_shutting_down_cv->Wait(g_init_mu);
}
}
+
+bool grpc_wait_for_shutdown_with_timeout(y_absl::Duration timeout) {
+ const auto started = y_absl::Now();
+ const auto deadline = started + timeout;
+ gpr_once_init(&g_basic_init, do_basic_init);
+ grpc_core::MutexLock lock(g_init_mu);
+ while (g_initializations != 0) {
+ if (g_shutting_down_cv->WaitWithDeadline(g_init_mu, deadline)) {
+ return false;
+ }
+ }
+ return true;
+}
diff --git a/contrib/libs/grpc/src/core/lib/surface/init.h b/contrib/libs/grpc/src/core/lib/surface/init.h
index 0d0035ae304..20a2fdf3256 100644
--- a/contrib/libs/grpc/src/core/lib/surface/init.h
+++ b/contrib/libs/grpc/src/core/lib/surface/init.h
@@ -18,8 +18,13 @@
#ifndef GRPC_SRC_CORE_LIB_SURFACE_INIT_H
#define GRPC_SRC_CORE_LIB_SURFACE_INIT_H
+#include "y_absl/time/time.h"
+
#include <grpc/support/port_platform.h>
void grpc_maybe_wait_for_async_shutdown(void);
+// Returns false if the timeout expired before fully shut down.
+bool grpc_wait_for_shutdown_with_timeout(y_absl::Duration timeout);
+
#endif // GRPC_SRC_CORE_LIB_SURFACE_INIT_H
diff --git a/contrib/libs/grpc/src/core/tsi/ssl_transport_security.cc b/contrib/libs/grpc/src/core/tsi/ssl_transport_security.cc
index deb3b952d4b..fcccd0c5dd5 100644
--- a/contrib/libs/grpc/src/core/tsi/ssl_transport_security.cc
+++ b/contrib/libs/grpc/src/core/tsi/ssl_transport_security.cc
@@ -23,6 +23,8 @@
#include <limits.h>
#include <string.h>
+# include <cstdlib>
+
// TODO(jboeuf): refactor inet_ntop into a portability header.
// Note: for whomever reads this and tries to refactor this, this
// can't be in grpc, it has to be in gpr.
@@ -58,6 +60,7 @@
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/gprpp/crash.h"
+#include "src/core/lib/surface/init.h"
#include "src/core/tsi/ssl/key_logging/ssl_key_logging.h"
#include "src/core/tsi/ssl/session_cache/ssl_session_cache.h"
#include "src/core/tsi/ssl_transport_security_utils.h"
@@ -172,6 +175,11 @@ static unsigned long openssl_thread_id_cb(void) {
static void init_openssl(void) {
#if OPENSSL_VERSION_NUMBER >= 0x10100000
OPENSSL_init_ssl(0, nullptr);
+ // Ensure OPENSSL global clean up happens after gRPC shutdown completes.
+ // OPENSSL registers an exit handler to clean up global objects, which
+ // otherwise may happen before gRPC removes all references to OPENSSL. Below
+ // exit handler is guaranteed to run after OPENSSL's.
+ std::atexit([]() { grpc_wait_for_shutdown_with_timeout(y_absl::Seconds(2)); });
#else
SSL_library_init();
SSL_load_error_strings();