--- Begin Message ---
Package: grpc
Version: 1.51.1-4.1
Severity: normal
Tags: patch pending
X-Debbugs-CC: 1064...@bugs.debian.org, 1075...@bugs.debian.org
Dear maintainer,
I've prepared an NMU for grpc (versioned as 1.51.1-4.2) and
uploaded it to DELAYED/5. Please feel free to tell me if I
should delay it longer.
These are all versions of patches backported from the current grpc git,
so they're fairly well tested, and will be replaced when we can
transition to the new upstream release (#1064501)
Regards.
Stefano
diff -Nru grpc-1.51.1/debian/changelog grpc-1.51.1/debian/changelog
--- grpc-1.51.1/debian/changelog 2024-02-28 17:10:41.000000000 -0800
+++ grpc-1.51.1/debian/changelog 2024-11-07 20:22:58.000000000 -0800
@@ -1,3 +1,12 @@
+grpc (1.51.1-4.2) unstable; urgency=medium
+
+ * Non-maintainer upload.
+ * Patch: Cython 3 support.
+ * Patch: Python 3.13 support. (Closes: #1084603)
+ * Patch: GCC-14 support. (Closes: #1075045)
+
+ -- Stefano Rivera <stefa...@debian.org> Thu, 07 Nov 2024 20:22:58 -0800
+
grpc (1.51.1-4.1) unstable; urgency=medium
* Non-maintainer upload.
diff -Nru grpc-1.51.1/debian/control grpc-1.51.1/debian/control
--- grpc-1.51.1/debian/control 2024-02-28 17:10:41.000000000 -0800
+++ grpc-1.51.1/debian/control 2024-11-07 11:03:24.000000000 -0800
@@ -12,7 +12,7 @@
ruby-rspec, ruby-simplecov,
dh-python,
python3-all-dev,
- cython3-legacy,
+ cython3,
python3-six,
python3-setuptools,
python3-pkg-resources,
diff -Nru grpc-1.51.1/debian/patches/cython3-deadlocks.patch grpc-1.51.1/debian/patches/cython3-deadlocks.patch
--- grpc-1.51.1/debian/patches/cython3-deadlocks.patch 1969-12-31 16:00:00.000000000 -0800
+++ grpc-1.51.1/debian/patches/cython3-deadlocks.patch 2024-11-07 14:14:41.000000000 -0800
@@ -0,0 +1,250 @@
+From d6cdc919ba40eb650ed29f4ef3ed2813528db28e Mon Sep 17 00:00:00 2001
+From: Xuan Wang <xua...@google.com>
+Date: Mon, 14 Oct 2024 15:16:27 -0700
+Subject: [PATCH 1/3] [Cython AIO] Fix Aio tests time out issue (#37917)
+
+### What's happening
+Some of our asyncio tests began timing out following a Cython upgrade to 3.0. This issue occurs consistently across both our Bazel and setup.py test environments.
+
+### Why the time out
+After some investigation, we found that our code here:https://github.com/grpc/grpc/blob/4ffcdd4ab7976cac397fcff25b6f952d0b5c8168/src/python/grpcio/grpc/_cython/_cygrpc/aio/completion_queue.pyx.pxi#L115-L116
+
+Was translated to this in Cython 0.29:
+```
+__pyx_f_7_cython_6cygrpc__unified_socket_write(__pyx_v_self->_write_fd);
+```
+
+And it changed to this in Cython 3.0:
+```
+__pyx_f_7_cython_6cygrpc__unified_socket_write(__pyx_v_self->_write_fd); if (unlikely(__Pyx_ErrOccurredWithGIL())) __PYX_ERR(7, 136, __pyx_L1_error)
+```
+
+Which indicates that this `nogil` function `_unified_socket_write` now requires GIL.
+
+### What's new in Cython 3
+* Cython 3 `cdef` functions with `void` return type will default to use `except *` as exception specification.
+* If function have `void` return type and defined as `nogil`, Cython will always re-acquire the GIL after the function call to check if an exception has been raised.
+* In some cases, this will cause a deadlock, especially if the function was called inside another `nogil` function.
+
+### What's the fix
+* This PR changes those functions to use `noexcept` as exception specification since we don't expect them to throw any exception, and this is also the suggested workarounds in Cython documentation: https://cython.readthedocs.io/en/latest/src/userguide/language_basics.html#error-return-values
+
+### Test
+* Tested locally by running `bazel test`, time our rate decreased from 5% to 0.3% in 3000 runs and 10s test time out.
+<!--
+
+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 #37917
+
+COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/37917 from XuanWang-Amos:fix_cython_aio 063d27aee9192a26f36d16e6f056dcab1a48b9c9
+PiperOrigin-RevId: 685851320
+---
+ .../grpc/_cython/_cygrpc/aio/completion_queue.pxd.pxi | 4 ++--
+ .../grpc/_cython/_cygrpc/aio/completion_queue.pyx.pxi | 6 +++---
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+
+Origin: upstream, https://github.com/grpc/grpc/pull/38003
+--- a/src/python/grpcio/grpc/_cython/_cygrpc/aio/completion_queue.pxd.pxi
++++ b/src/python/grpcio/grpc/_cython/_cygrpc/aio/completion_queue.pxd.pxi
+@@ -23,7 +23,7 @@
+ int win_socket_send "send" (WIN_SOCKET s, const char *buf, int len, int flags)
+
+
+-cdef void _unified_socket_write(int fd) nogil
++cdef void _unified_socket_write(int fd) noexcept nogil
+
+
+ cdef class BaseCompletionQueue:
+--- a/src/python/grpcio/grpc/_cython/_cygrpc/aio/completion_queue.pyx.pxi
++++ b/src/python/grpcio/grpc/_cython/_cygrpc/aio/completion_queue.pyx.pxi
+@@ -22,12 +22,12 @@
+ cdef bint _has_fd_monitoring = True
+
+ IF UNAME_SYSNAME == "Windows":
+- cdef void _unified_socket_write(int fd) nogil:
++ cdef void _unified_socket_write(int fd) noexcept nogil:
+ win_socket_send(<WIN_SOCKET>fd, b"1", 1, 0)
+ ELSE:
+ from posix cimport unistd
+
+- cdef void _unified_socket_write(int fd) nogil:
++ cdef void _unified_socket_write(int fd) noexcept nogil:
+ unistd.write(fd, b"1", 1)
+
+
+--- a/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pxd.pxi
++++ b/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pxd.pxi
+@@ -26,9 +26,9 @@
+ grpc_credentials_plugin_metadata_cb cb, void *user_data,
+ grpc_metadata creds_md[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX],
+ size_t *num_creds_md, grpc_status_code *status,
+- const char **error_details) except * with gil
++ const char **error_details) except -1 with gil
+
+-cdef void _destroy(void *state) except * with gil
++cdef void _destroy(void *state) noexcept nogil
+
+
+ cdef class MetadataPluginCallCredentials(CallCredentials):
+--- a/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi
++++ b/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi
+@@ -12,6 +12,7 @@
+ # See the License for the specific language governing permissions and
+ # limitations under the License.
+
++import atexit
+
+ def _spawn_callback_in_thread(cb_func, args):
+ t = ForkManagedThread(target=cb_func, args=args)
+@@ -41,7 +42,7 @@
+ grpc_metadata creds_md[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX],
+ size_t *num_creds_md,
+ grpc_status_code *status,
+- const char **error_details) except * with gil:
++ const char **error_details) except -1 with gil:
+ cdef size_t metadata_count
+ cdef grpc_metadata *c_metadata
+ def callback(metadata, grpc_status_code status, bytes error_details):
+@@ -65,11 +66,59 @@
+ return 0 # Asynchronous return
+
+
+-cdef void _destroy(void *state) except * with gil:
+- cpython.Py_DECREF(<object>state)
++# Protects access to GIL from _destroy() and to g_shutting_down.
++# Do NOT hold this while holding GIL to prevent a deadlock.
++cdef mutex g_shutdown_mu
++# Number of C-core clean up calls in progress. Set to -1 when Python is shutting
++# down.
++cdef int g_shutting_down = 0
++
++# This is called by C-core when the plugin is destroyed, which may race between
++# GIL destruction during process shutdown. Since GIL destruction happens after
++# Python's exit handlers, we mark that Python is shutting down from an exit
++# handler and don't grab GIL in this function afterwards using a C mutex.
++cdef void _destroy(void *state) noexcept nogil:
++ global g_shutdown_mu
++ global g_shutting_down
++ g_shutdown_mu.lock()
++ if g_shutting_down > -1:
++ g_shutting_down += 1
++ g_shutdown_mu.unlock()
++ with gil:
++ cpython.Py_DECREF(<object>state)
++ g_shutdown_mu.lock()
++ g_shutting_down -= 1
++ g_shutdown_mu.unlock()
+ grpc_shutdown()
+
+
++g_shutdown_handler_registered = False
++
++def _maybe_register_shutdown_handler():
++ global g_shutdown_handler_registered
++ if g_shutdown_handler_registered:
++ return
++ g_shutdown_handler_registered = True
++ atexit.register(_on_shutdown)
++
++cdef void _on_shutdown() noexcept nogil:
++ global g_shutdown_mu
++ global g_shutting_down
++ # Wait for up to ~2s if C-core is still cleaning up.
++ cdef int wait_ms = 10
++ while wait_ms < 1500:
++ g_shutdown_mu.lock()
++ if g_shutting_down == 0:
++ g_shutting_down = -1
++ g_shutdown_mu.unlock()
++ return
++ g_shutdown_mu.unlock()
++ with gil:
++ time.sleep(wait_ms / 1000)
++ wait_ms = wait_ms * 2
++ with gil:
++ _LOGGER.error('Timed out waiting for C-core clean-up')
++
+ cdef class MetadataPluginCallCredentials(CallCredentials):
+
+ def __cinit__(self, metadata_plugin, name):
+@@ -83,6 +132,7 @@
+ c_metadata_plugin.state = <void *>self._metadata_plugin
+ c_metadata_plugin.type = self._name
+ cpython.Py_INCREF(self._metadata_plugin)
++ _maybe_register_shutdown_handler()
+ fork_handlers_and_grpc_init()
+ # TODO(yihuazhang): Expose min_security_level via the Python API so that
+ # applications can decide what minimum security level their plugins require.
+--- a/src/python/grpcio/grpc/_cython/_cygrpc/records.pxd.pxi
++++ b/src/python/grpcio/grpc/_cython/_cygrpc/records.pxd.pxi
+@@ -14,8 +14,8 @@
+
+
+ cdef bytes _slice_bytes(grpc_slice slice)
+-cdef grpc_slice _copy_slice(grpc_slice slice) nogil
+-cdef grpc_slice _slice_from_bytes(bytes value) nogil
++cdef grpc_slice _copy_slice(grpc_slice slice) noexcept nogil
++cdef grpc_slice _slice_from_bytes(bytes value) noexcept nogil
+
+
+ cdef class CallDetails:
+--- a/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi
++++ b/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi
+@@ -18,12 +18,12 @@
+ cdef size_t length = grpc_slice_length(slice)
+ return (<const char *>start)[:length]
+
+-cdef grpc_slice _copy_slice(grpc_slice slice) nogil:
++cdef grpc_slice _copy_slice(grpc_slice slice) noexcept nogil:
+ cdef void *start = grpc_slice_start_ptr(slice)
+ cdef size_t length = grpc_slice_length(slice)
+ return grpc_slice_from_copied_buffer(<const char *>start, length)
+
+-cdef grpc_slice _slice_from_bytes(bytes value) nogil:
++cdef grpc_slice _slice_from_bytes(bytes value) noexcept nogil:
+ cdef const char *value_ptr
+ cdef size_t length
+ with gil:
+--- a/src/python/grpcio/grpc/_cython/_cygrpc/security.pxd.pxi
++++ b/src/python/grpcio/grpc/_cython/_cygrpc/security.pxd.pxi
+@@ -14,4 +14,4 @@
+
+
+ cdef grpc_ssl_roots_override_result ssl_roots_override_callback(
+- char **pem_root_certs) nogil
++ char **pem_root_certs) noexcept nogil
+--- a/src/python/grpcio/grpc/_cython/_cygrpc/security.pyx.pxi
++++ b/src/python/grpcio/grpc/_cython/_cygrpc/security.pyx.pxi
+@@ -18,7 +18,7 @@
+
+
+ cdef grpc_ssl_roots_override_result ssl_roots_override_callback(
+- char **pem_root_certs) nogil:
++ char **pem_root_certs) noexcept nogil:
+ with gil:
+ pkg = __name__
+ if pkg.endswith('.cygrpc'):
+--- a/tools/distrib/python/grpcio_tools/grpc_tools/_protoc_compiler.pyx
++++ b/tools/distrib/python/grpcio_tools/grpc_tools/_protoc_compiler.pyx
+@@ -39,12 +39,12 @@
+ vector[string]* include_path,
+ vector[pair[string, string]]* files_out,
+ vector[cProtocError]* errors,
+- vector[cProtocWarning]* wrnings) nogil except +
++ vector[cProtocWarning]* wrnings) except + nogil
+ int protoc_get_services(char* protobuf_path,
+ vector[string]* include_path,
+ vector[pair[string, string]]* files_out,
+ vector[cProtocError]* errors,
+- vector[cProtocWarning]* wrnings) nogil except +
++ vector[cProtocWarning]* wrnings) except + nogil
+
+ def run_main(list args not None):
+ cdef char **argv = <char **>stdlib.malloc(len(args)*sizeof(char *))
diff -Nru grpc-1.51.1/debian/patches/cython3-noexcept.patch grpc-1.51.1/debian/patches/cython3-noexcept.patch
--- grpc-1.51.1/debian/patches/cython3-noexcept.patch 1969-12-31 16:00:00.000000000 -0800
+++ grpc-1.51.1/debian/patches/cython3-noexcept.patch 2024-11-07 14:12:12.000000000 -0800
@@ -0,0 +1,170 @@
+From 4bea12353c2f0f5a52746821f1e3f961592c7ca0 Mon Sep 17 00:00:00 2001
+From: Atri Bhattacharya <a.bhattacha...@uliege.be>
+Date: Tue, 2 Apr 2024 10:05:04 -0700
+Subject: [PATCH] [python] Cython 3 compatibility: declare functions noexcept.
+ (#35995)
+
+In Cython 3, cdef functions that really will not raise exceptions must be declared as `noexcept`. Fixed by this commit.
+
+Update requirements to `cython >= 3.0` in requirements*.txt and setup.py.
+
+Fixes issue #33918.
+
+<!--
+
+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 #35995
+
+COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/35995 from badshah400:master b3277bac1585ddee88a170b0a95c260d909cce9c
+PiperOrigin-RevId: 621214091
+---
+ requirements.bazel.txt | 2 +-
+ requirements.txt | 2 +-
+ setup.py | 2 +-
+ .../grpcio/grpc/_cython/_cygrpc/aio/callback_common.pxd.pxi | 2 +-
+ .../grpcio/grpc/_cython/_cygrpc/aio/callback_common.pyx.pxi | 2 +-
+ src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi | 2 +-
+ src/python/grpcio/grpc/_cython/_cygrpc/fork_posix.pxd.pxi | 6 +++---
+ src/python/grpcio/grpc/_cython/_cygrpc/fork_posix.pyx.pxi | 6 +++---
+ src/python/grpcio/grpc/_cython/_cygrpc/vtable.pyx.pxi | 6 +++---
+ 9 files changed, 15 insertions(+), 15 deletions(-)
+
+Origin: upstream, https://github.com/grpc/grpc/commit/4bea12353c2f0f5a52746821f1e3f961592c7ca0
+Bug-upstream: https://github.com/grpc/grpc/issues/33918
+--- a/requirements.bazel.txt
++++ b/requirements.bazel.txt
+@@ -1,6 +1,6 @@
+ # GRPC Python setup requirements
+ coverage==4.5.4
+-cython==0.29.21
++cython==3.0.0
+ protobuf>=3.5.0.post1, < 4.0dev
+ wheel==0.36.2
+ google-auth==1.24.0
+--- a/requirements.txt
++++ b/requirements.txt
+@@ -1,5 +1,5 @@
+ # GRPC Python setup requirements
+ coverage>=4.0
+-cython>=0.29.8
++cython>=3.0.0
+ protobuf>=4.21.3,<5.0dev
+ wheel>=0.29
+--- a/setup.py
++++ b/setup.py
+@@ -502,7 +502,7 @@
+ elif need_cython:
+ sys.stderr.write(
+ 'We could not find Cython. Setup may take 10-20 minutes.\n')
+- SETUP_REQUIRES += ('cython>=0.23',)
++ SETUP_REQUIRES += ('cython>=3.0.0',)
+
+ COMMAND_CLASS = {
+ 'doc': commands.SphinxDocumentation,
+--- a/src/python/grpcio/grpc/_cython/_cygrpc/aio/callback_common.pxd.pxi
++++ b/src/python/grpcio/grpc/_cython/_cygrpc/aio/callback_common.pxd.pxi
+@@ -48,7 +48,7 @@
+ @staticmethod
+ cdef void functor_run(
+ grpc_completion_queue_functor* functor,
+- int succeed)
++ int succeed) noexcept
+
+ cdef grpc_completion_queue_functor *c_functor(self)
+
+--- a/src/python/grpcio/grpc/_cython/_cygrpc/aio/callback_common.pyx.pxi
++++ b/src/python/grpcio/grpc/_cython/_cygrpc/aio/callback_common.pyx.pxi
+@@ -50,7 +50,7 @@
+ @staticmethod
+ cdef void functor_run(
+ grpc_completion_queue_functor* functor,
+- int success):
++ int success) noexcept:
+ cdef CallbackContext *context = <CallbackContext *>functor
+ cdef object waiter = <object>context.waiter
+ if not waiter.cancelled():
+--- a/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi
++++ b/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi
+@@ -314,7 +314,7 @@
+ return credentials
+
+ cdef grpc_ssl_certificate_config_reload_status _server_cert_config_fetcher_wrapper(
+- void* user_data, grpc_ssl_server_certificate_config **config) with gil:
++ void* user_data, grpc_ssl_server_certificate_config **config) noexcept with gil:
+ # This is a credentials.ServerCertificateConfig
+ cdef ServerCertificateConfig cert_config = None
+ if not user_data:
+--- a/src/python/grpcio/grpc/_cython/_cygrpc/fork_posix.pxd.pxi
++++ b/src/python/grpcio/grpc/_cython/_cygrpc/fork_posix.pxd.pxi
+@@ -20,10 +20,10 @@
+ void (*child)() nogil)
+
+
+-cdef void __prefork() nogil
++cdef void __prefork() noexcept nogil
+
+
+-cdef void __postfork_parent() nogil
++cdef void __postfork_parent() noexcept nogil
+
+
+-cdef void __postfork_child() nogil
+\ No newline at end of file
++cdef void __postfork_child() noexcept nogil
+--- a/src/python/grpcio/grpc/_cython/_cygrpc/fork_posix.pyx.pxi
++++ b/src/python/grpcio/grpc/_cython/_cygrpc/fork_posix.pyx.pxi
+@@ -34,7 +34,7 @@
+
+ _fork_handler_failed = False
+
+-cdef void __prefork() nogil:
++cdef void __prefork() noexcept nogil:
+ with gil:
+ global _fork_handler_failed
+ _fork_handler_failed = False
+@@ -48,14 +48,14 @@
+ _fork_handler_failed = True
+
+
+-cdef void __postfork_parent() nogil:
++cdef void __postfork_parent() noexcept nogil:
+ with gil:
+ with _fork_state.fork_in_progress_condition:
+ _fork_state.fork_in_progress = False
+ _fork_state.fork_in_progress_condition.notify_all()
+
+
+-cdef void __postfork_child() nogil:
++cdef void __postfork_child() noexcept nogil:
+ with gil:
+ try:
+ if _fork_handler_failed:
+--- a/src/python/grpcio/grpc/_cython/_cygrpc/vtable.pyx.pxi
++++ b/src/python/grpcio/grpc/_cython/_cygrpc/vtable.pyx.pxi
+@@ -13,16 +13,16 @@
+ # limitations under the License.
+
+ # TODO(https://github.com/grpc/grpc/issues/15662): Reform this.
+-cdef void* _copy_pointer(void* pointer):
++cdef void* _copy_pointer(void* pointer) noexcept:
+ return pointer
+
+
+ # TODO(https://github.com/grpc/grpc/issues/15662): Reform this.
+-cdef void _destroy_pointer(void* pointer):
++cdef void _destroy_pointer(void* pointer) noexcept:
+ pass
+
+
+-cdef int _compare_pointer(void* first_pointer, void* second_pointer):
++cdef int _compare_pointer(void* first_pointer, void* second_pointer) noexcept:
+ if first_pointer < second_pointer:
+ return -1
+ elif first_pointer > second_pointer:
diff -Nru grpc-1.51.1/debian/patches/gcc-14-2.patch grpc-1.51.1/debian/patches/gcc-14-2.patch
--- grpc-1.51.1/debian/patches/gcc-14-2.patch 1969-12-31 16:00:00.000000000 -0800
+++ grpc-1.51.1/debian/patches/gcc-14-2.patch 2024-11-07 16:38:02.000000000 -0800
@@ -0,0 +1,28 @@
+From f55bf225da0eafeeebffd507dcb57c625933d105 Mon Sep 17 00:00:00 2001
+From: alto-ruby <altoru...@gmail.com>
+Date: Tue, 17 Sep 2024 18:09:05 -0700
+Subject: [PATCH] [Ruby] fix incompatible pointer type of
+ grpc_compression_algorithm_name (#37741)
+
+fixes #37731
+
+Closes #37741
+
+COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/37741 from alto-ruby:fix-incompatible-pointer-type-in-grpc_compression_algorithm_name 18a89be44d54e8c8bd614f1cee626d1db598a45a
+PiperOrigin-RevId: 675779382
+---
+ src/ruby/ext/grpc/rb_compression_options.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+Origin: upstream, https://github.com/grpc/grpc/pull/37741
+--- a/src/ruby/ext/grpc/rb_compression_options.c
++++ b/src/ruby/ext/grpc/rb_compression_options.c
+@@ -297,7 +297,7 @@
+ * Fails if the enum value is invalid. */
+ VALUE grpc_rb_compression_options_algorithm_value_to_name_internal(
+ grpc_compression_algorithm internal_value) {
+- char* algorithm_name = NULL;
++ const char* algorithm_name = NULL;
+
+ if (!grpc_compression_algorithm_name(internal_value, &algorithm_name)) {
+ rb_raise(rb_eArgError, "Failed to convert algorithm value to name");
diff -Nru grpc-1.51.1/debian/patches/gcc-14.patch grpc-1.51.1/debian/patches/gcc-14.patch
--- grpc-1.51.1/debian/patches/gcc-14.patch 1969-12-31 16:00:00.000000000 -0800
+++ grpc-1.51.1/debian/patches/gcc-14.patch 2024-11-07 17:36:18.000000000 -0800
@@ -0,0 +1,119 @@
+From c637a9f82bc43f7380b04baa96df243f157939d4 Mon Sep 17 00:00:00 2001
+From: Stan Hu <sta...@gmail.com>
+Date: Mon, 22 Jan 2024 13:11:28 -0800
+Subject: [PATCH] [ruby] Fix compilation errors on clang 16 (#34481)
+
+As announced in https://discourse.llvm.org/t/clang-16-notice-of-potentially-breaking-changes/65562, clang 16 defaults `-Wincompatible-function-pointer-types` to be on. This causes a number of hard errors due to implicit conversions between `void *` and `void`, such as:
+
+```
+../../../../src/ruby/ext/grpc/rb_channel.c:770:47: error: incompatible function pointer types passing 'VALUE (VALUE)' (aka 'unsigned long (unsigned long)') to parameter of type 'VALUE (*)(void *)' (aka 'unsigned long (*)(void *)') [-Wincompatible-function-pointer-types]
+ g_channel_polling_thread = rb_thread_create(run_poll_channels_loop, NULL);
+ ^~~~~~~~~~~~~~~~~~~~~~
+/root/.rbenv/versions/3.1.4/include/ruby-3.1.0/ruby/internal/intern/thread.h:190:32: note: passing argument to parameter 'f' here
+VALUE rb_thread_create(VALUE (*f)(void *g), void *g);
+ ^
+../../../../src/ruby/ext/grpc/rb_channel.c:780:41: warning: a function declaration without a prototype is deprecated in all versions of C [-Wstrict-prototypes]
+void grpc_rb_channel_polling_thread_stop() {
+ ^
+ void
+../../../../src/ruby/ext/grpc/rb_channel.c:786:30: error: incompatible function pointer types passing 'void (void *)' to parameter of type 'void *(*)(void *)' [-Wincompatible-function-pointer-types]
+ rb_thread_call_without_gvl(run_poll_channels_loop_unblocking_func, NULL, NULL,
+```
+
+This commit fixes these pointer types using wrapper functions where necessary.
+
+This issue was also raised on the FreeBSD port of the grpc gem: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=271540
+
+<!--
+
+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 #34481
+
+COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/34481 from stanhu:sh-ruby-fix-clang-16 63c7424ad0c93f7a7aa1ce0e84ea7916c4cbdc5f
+PiperOrigin-RevId: 600548467
+---
+ src/ruby/ext/grpc/rb_channel.c | 16 +++++++++++-----
+ src/ruby/ext/grpc/rb_event_thread.c | 12 +++++++++---
+ 2 files changed, 20 insertions(+), 8 deletions(-)
+
+Bug-Upstream: https://github.com/grpc/grpc/pull/34481
+--- a/src/ruby/ext/grpc/rb_channel.c
++++ b/src/ruby/ext/grpc/rb_channel.c
+@@ -115,6 +115,7 @@
+ grpc_channel* channel);
+ static void bg_watched_channel_list_free_and_remove(bg_watched_channel* bg);
+ static void run_poll_channels_loop_unblocking_func(void* arg);
++static void* run_poll_channels_loop_unblocking_func_wrapper(void* arg);
+
+ // Needs to be called under global_connection_polling_mu
+ static void grpc_rb_channel_watch_connection_state_op_complete(
+@@ -659,8 +660,12 @@
+ return NULL;
+ }
+
+-// Notify the channel polling loop to cleanup and shutdown.
+ static void run_poll_channels_loop_unblocking_func(void* arg) {
++ run_poll_channels_loop_unblocking_func_wrapper(arg);
++}
++
++// Notify the channel polling loop to cleanup and shutdown.
++static void* run_poll_channels_loop_unblocking_func_wrapper(void* arg) {
+ bg_watched_channel* bg = NULL;
+ (void)arg;
+
+@@ -671,7 +676,7 @@
+ // early out after first time through
+ if (abort_channel_polling) {
+ gpr_mu_unlock(&global_connection_polling_mu);
+- return;
++ return NULL;
+ }
+ abort_channel_polling = 1;
+
+@@ -691,10 +696,11 @@
+ gpr_log(GPR_DEBUG,
+ "GRPC_RUBY: run_poll_channels_loop_unblocking_func - end aborting "
+ "connection polling");
++ return NULL;
+ }
+
+ // Poll channel connectivity states in background thread without the GIL.
+-static VALUE run_poll_channels_loop(VALUE arg) {
++static VALUE run_poll_channels_loop(void* arg) {
+ (void)arg;
+ gpr_log(
+ GPR_DEBUG,
+--- a/src/ruby/ext/grpc/rb_event_thread.c
++++ b/src/ruby/ext/grpc/rb_event_thread.c
+@@ -104,17 +104,22 @@
+ return NULL;
+ }
+
+-static void grpc_rb_event_unblocking_func(void* arg) {
++static void* grpc_rb_event_unblocking_func_wrapper(void* arg) {
+ (void)arg;
+ gpr_mu_lock(&event_queue.mu);
+ event_queue.abort = true;
+ gpr_cv_signal(&event_queue.cv);
+ gpr_mu_unlock(&event_queue.mu);
++ return NULL;
++}
++
++static void grpc_rb_event_unblocking_func(void* arg) {
++ grpc_rb_event_unblocking_func_wrapper(arg);
+ }
+
+ /* This is the implementation of the thread that handles auth metadata plugin
+ * events */
+-static VALUE grpc_rb_event_thread(VALUE arg) {
++static VALUE grpc_rb_event_thread(void* arg) {
+ grpc_rb_event* event;
+ (void)arg;
+ grpc_ruby_init();
diff -Nru grpc-1.51.1/debian/patches/python3.13-pipes.patch grpc-1.51.1/debian/patches/python3.13-pipes.patch
--- grpc-1.51.1/debian/patches/python3.13-pipes.patch 1969-12-31 16:00:00.000000000 -0800
+++ grpc-1.51.1/debian/patches/python3.13-pipes.patch 2024-11-07 14:19:07.000000000 -0800
@@ -0,0 +1,110 @@
+From dfa9d853fff02212ff232da5b39b76adf3ecce83 Mon Sep 17 00:00:00 2001
+From: Leonardo Pistone <lepist...@spotify.com>
+Date: Thu, 7 Dec 2023 12:59:29 -0800
+Subject: [PATCH] Fix Python DeprecationWarning: 'pipes' (#34941)
+
+Starting from Python 3.11, the pipes module produces this warning:
+
+DeprecationWarning: 'pipes' is deprecated and slated for removal in Python 3.13
+
+Turns out that in this repo the pipes module is only used for the
+"quote" function which is turn directly taken from the shlex module [1].
+
+The shlex module is not deprecated as of today and is already used in
+other places in this repo. The function shlex.quote has been around
+since the ancient Python 3.3.
+
+[1] https://github.com/python/cpython/blob/3.11/Lib/pipes.py#L64-L66
+
+<!--
+
+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 #34941
+
+COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/34941 from lepistone:deprecate-python-pipes 233c54c135542178703aa700a2dddadc895fedb0
+PiperOrigin-RevId: 588883480
+---
+ tools/run_tests/run_performance_tests.py | 10 +++++-----
+ tools/run_tests/run_tests.py | 4 ++--
+ 2 files changed, 7 insertions(+), 7 deletions(-)
+
+Origin: upstream, https://github.com/grpc/grpc/pull/34941
+Bug-Debian: https://bugs.debian.org/1084603
+--- a/tools/run_tests/run_performance_tests.py
++++ b/tools/run_tests/run_performance_tests.py
+@@ -22,8 +22,8 @@
+ import json
+ import multiprocessing
+ import os
+-import pipes
+ import re
++import shlex
+ import subprocess
+ import sys
+ import tempfile
+@@ -124,7 +124,7 @@
+ if bq_result_table:
+ cmd += 'BQ_RESULT_TABLE="%s" ' % bq_result_table
+ cmd += 'tools/run_tests/performance/run_qps_driver.sh '
+- cmd += '--scenarios_json=%s ' % pipes.quote(
++ cmd += '--scenarios_json=%s ' % shlex.quote(
+ json.dumps({'scenarios': [scenario_json]}))
+ cmd += '--scenario_result_file=scenario_result.json '
+ if server_cpu_load != 0:
+@@ -132,7 +132,7 @@
+ if remote_host:
+ user_at_host = '%s@%s' % (_REMOTE_HOST_USERNAME, remote_host)
+ cmd = 'ssh %s "cd ~/performance_workspace/grpc/ && "%s' % (
+- user_at_host, pipes.quote(cmd))
++ user_at_host, shlex.quote(cmd))
+
+ return jobset.JobSpec(cmdline=[cmd],
+ shortname='%s' % scenario_json['name'],
+@@ -149,7 +149,7 @@
+ if remote_host:
+ user_at_host = '%s@%s' % (_REMOTE_HOST_USERNAME, remote_host)
+ cmd = 'ssh %s "cd ~/performance_workspace/grpc/ && "%s' % (
+- user_at_host, pipes.quote(cmd))
++ user_at_host, shlex.quote(cmd))
+
+ return jobset.JobSpec(cmdline=[cmd],
+ shortname='shutdown_workers',
+@@ -180,7 +180,7 @@
+ if client_host:
+ user_at_host = '%s@%s' % (_REMOTE_HOST_USERNAME, client_host)
+ cmd = 'ssh %s "cd ~/performance_workspace/grpc/ && "%s' % (
+- user_at_host, pipes.quote(cmd))
++ user_at_host, shlex.quote(cmd))
+
+ return jobset.JobSpec(cmdline=[cmd],
+ shortname='netperf',
+--- a/tools/run_tests/run_tests.py
++++ b/tools/run_tests/run_tests.py
+@@ -26,10 +26,10 @@
+ import multiprocessing
+ import os
+ import os.path
+-import pipes
+ import platform
+ import random
+ import re
++import shlex
+ import socket
+ import subprocess
+ import sys
+@@ -415,7 +415,7 @@
+ cmdline = [binary] + target['args']
+ shortname = target.get(
+ 'shortname',
+- ' '.join(pipes.quote(arg) for arg in cmdline))
++ ' '.join(shlex.quote(arg) for arg in cmdline))
+ shortname += shortname_ext
+ out.append(
+ self.config.job_spec(
diff -Nru grpc-1.51.1/debian/patches/python3.13-pyeval-initthreads.patch grpc-1.51.1/debian/patches/python3.13-pyeval-initthreads.patch
--- grpc-1.51.1/debian/patches/python3.13-pyeval-initthreads.patch 1969-12-31 16:00:00.000000000 -0800
+++ grpc-1.51.1/debian/patches/python3.13-pyeval-initthreads.patch 2024-11-07 14:13:27.000000000 -0800
@@ -0,0 +1,39 @@
+From d583a79750a7f3cf2c955d880ebfbfd5b8aa1675 Mon Sep 17 00:00:00 2001
+From: "Benjamin A. Beasley" <c...@musicinmybrain.net>
+Date: Thu, 2 Nov 2023 07:00:37 -0400
+Subject: [PATCH] [Python] Do not call PyEval_InitThreads
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Since Python 3.7, it’s called by Py_Initialize and doesn’t need to be called manually, so this removal has no effect.
+
+Since Python 3.9, it does nothing, and in Python 3.13, it will be removed, which makes this change necessary.
+
+References:
+
+https://docs.python.org/3/c-api/init.html#c.PyEval_InitThreads
+
+https://github.com/python/cpython/issues/105182
+---
+ src/python/grpcio/grpc/_cython/cygrpc.pyx | 7 -------
+ 1 file changed, 7 deletions(-)
+
+Origin: upstream, https://github.com/grpc/grpc/pull/34857
+--- a/src/python/grpcio/grpc/_cython/cygrpc.pyx
++++ b/src/python/grpcio/grpc/_cython/cygrpc.pyx
+@@ -79,14 +79,7 @@
+ #
+ # initialize gRPC
+ #
+-cdef extern from "Python.h":
+-
+- int PyEval_InitThreads()
+-
+ cdef _initialize():
+- # We have Python callbacks called by c-core threads, this ensures the GIL
+- # is initialized.
+- PyEval_InitThreads()
+ grpc_set_ssl_roots_override_callback(
+ <grpc_ssl_roots_override_callback>ssl_roots_override_callback)
+
diff -Nru grpc-1.51.1/debian/patches/series grpc-1.51.1/debian/patches/series
--- grpc-1.51.1/debian/patches/series 2022-12-24 09:05:35.000000000 -0800
+++ grpc-1.51.1/debian/patches/series 2024-11-07 16:37:27.000000000 -0800
@@ -13,3 +13,9 @@
fix-protoc-path.patch
add_grpc_libdir.patch
link_python_all_absl.patch
+cython3-noexcept.patch
+python3.13-pyeval-initthreads.patch
+cython3-deadlocks.patch
+python3.13-pipes.patch
+gcc-14.patch
+gcc-14-2.patch
--- End Message ---