@@ -2856,6 +2856,38 @@ static PyObject *erlang_channel_is_closed_impl(PyObject *self, PyObject *args) {
28562856 }
28572857}
28582858
2859+ /**
2860+ * @brief Close a channel from Python
2861+ *
2862+ * Usage: erlang._channel_close(channel_ref)
2863+ * Returns: True on success
2864+ * Raises: TypeError if invalid reference
2865+ */
2866+ static PyObject * erlang_channel_close_impl (PyObject * self , PyObject * args ) {
2867+ (void )self ;
2868+ PyObject * capsule ;
2869+
2870+ if (!PyArg_ParseTuple (args , "O" , & capsule )) {
2871+ return NULL ;
2872+ }
2873+
2874+ if (!PyCapsule_CheckExact (capsule )) {
2875+ PyErr_SetString (PyExc_TypeError , "expected channel reference" );
2876+ return NULL ;
2877+ }
2878+
2879+ py_channel_t * channel = (py_channel_t * )PyCapsule_GetPointer (capsule , CHANNEL_CAPSULE_NAME );
2880+ if (channel == NULL ) {
2881+ PyErr_SetString (PyExc_ValueError , "invalid channel reference" );
2882+ return NULL ;
2883+ }
2884+
2885+ /* Close the channel - this wakes any waiting receivers */
2886+ channel_close (channel );
2887+
2888+ Py_RETURN_TRUE ;
2889+ }
2890+
28592891/* ============================================================================
28602892 * ByteChannel Methods (raw bytes, no term conversion)
28612893 * ============================================================================ */
@@ -3328,6 +3360,10 @@ static PyMethodDef ErlangModuleMethods[] = {
33283360 "Check if channel is closed.\n"
33293361 "Usage: erlang._channel_is_closed(channel_ref)\n"
33303362 "Returns: True if closed, False otherwise." },
3363+ {"_channel_close" , erlang_channel_close_impl , METH_VARARGS ,
3364+ "Close a channel.\n"
3365+ "Usage: erlang._channel_close(channel_ref)\n"
3366+ "Returns: True. Wakes any waiting receivers." },
33313367 /* ByteChannel methods (raw bytes, no term conversion) */
33323368 {"_byte_channel_try_receive_bytes" , erlang_byte_channel_try_receive_bytes_impl , METH_VARARGS ,
33333369 "ByteChannel receive (non-blocking, raw bytes).\n"
0 commit comments