From f4544591740406d1fe9999a59acb52f02f4682cf Mon Sep 17 00:00:00 2001 From: Hu Yueh-Wei Date: Mon, 13 Jan 2025 21:58:02 +0800 Subject: [PATCH 01/11] fix: on_xxx timing checkings --- core/include_internal/ten_runtime/extension/extension.h | 9 +++++++++ core/src/ten_runtime/extension/extension.c | 6 ++++++ core/src/ten_runtime/extension/ten_env/on_xxx.c | 6 +++--- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/core/include_internal/ten_runtime/extension/extension.h b/core/include_internal/ten_runtime/extension/extension.h index c2408ae5bd..c3bc20f214 100644 --- a/core/include_internal/ten_runtime/extension/extension.h +++ b/core/include_internal/ten_runtime/extension/extension.h @@ -65,9 +65,15 @@ typedef struct ten_timer_t ten_timer_t; typedef enum TEN_EXTENSION_STATE { TEN_EXTENSION_STATE_INIT, + // on_configure() is called. + TEN_EXTENSION_STATE_ON_CONFIGURE, + // on_configure_done() is completed. TEN_EXTENSION_STATE_ON_CONFIGURE_DONE, + // on_init() is called. + TEN_EXTENSION_STATE_ON_INIT, + // on_init_done() is completed. TEN_EXTENSION_STATE_ON_INIT_DONE, @@ -77,6 +83,9 @@ typedef enum TEN_EXTENSION_STATE { // on_start_done() is completed. TEN_EXTENSION_STATE_ON_START_DONE, + // on_stop() is called. + TEN_EXTENSION_STATE_ON_STOP, + // on_stop_done() is completed. TEN_EXTENSION_STATE_ON_STOP_DONE, diff --git a/core/src/ten_runtime/extension/extension.c b/core/src/ten_runtime/extension/extension.c index d33b60cff2..9cb9af6c08 100644 --- a/core/src/ten_runtime/extension/extension.c +++ b/core/src/ten_runtime/extension/extension.c @@ -767,6 +767,8 @@ static void ten_extension_on_configure(ten_env_t *ten_env) { self->property_info = ten_metadata_info_create(TEN_METADATA_ATTACH_TO_PROPERTY, self->ten_env); + self->state = TEN_EXTENSION_STATE_ON_CONFIGURE; + if (self->on_configure) { self->on_configure(self, self->ten_env); } else { @@ -787,6 +789,8 @@ void ten_extension_on_init(ten_env_t *ten_env) { TEN_LOGD("[%s] on_init().", ten_extension_get_name(self, true)); + self->state = TEN_EXTENSION_STATE_ON_INIT; + if (self->on_init) { self->on_init(self, self->ten_env); } else { @@ -817,6 +821,8 @@ void ten_extension_on_stop(ten_extension_t *self) { TEN_LOGI("[%s] on_stop().", ten_extension_get_name(self, true)); + self->state = TEN_EXTENSION_STATE_ON_STOP; + if (self->on_stop) { self->on_stop(self, self->ten_env); } else { diff --git a/core/src/ten_runtime/extension/ten_env/on_xxx.c b/core/src/ten_runtime/extension/ten_env/on_xxx.c index 6d3f3a6cc8..e4487f1c17 100644 --- a/core/src/ten_runtime/extension/ten_env/on_xxx.c +++ b/core/src/ten_runtime/extension/ten_env/on_xxx.c @@ -87,7 +87,7 @@ bool ten_extension_on_configure_done(ten_env_t *self) { TEN_LOGD("[%s] on_configure() done.", ten_extension_get_name(extension, true)); - if (extension->state != TEN_EXTENSION_STATE_INIT) { + if (extension->state != TEN_EXTENSION_STATE_ON_CONFIGURE) { TEN_LOGI("[%s] Failed to on_configure_done() because of incorrect timing.", ten_extension_get_name(extension, true)); return false; @@ -185,7 +185,7 @@ bool ten_extension_on_init_done(ten_env_t *self) { TEN_LOGD("[%s] on_init() done.", ten_extension_get_name(extension, true)); - if (extension->state != TEN_EXTENSION_STATE_ON_CONFIGURE_DONE) { + if (extension->state != TEN_EXTENSION_STATE_ON_INIT) { // `on_init_done` can only be called at specific times. TEN_LOGI("[%s] Failed to on_init_done() because of incorrect timing.", ten_extension_get_name(extension, true)); @@ -278,7 +278,7 @@ bool ten_extension_on_stop_done(ten_env_t *self) { TEN_LOGI("[%s] on_stop() done.", ten_extension_get_name(extension, true)); - if (extension->state != TEN_EXTENSION_STATE_ON_START_DONE) { + if (extension->state != TEN_EXTENSION_STATE_ON_STOP) { TEN_LOGI("[%s] Failed to on_stop_done() because of incorrect timing.", ten_extension_get_name(extension, true)); return false; From 974c0af7cb6892cdae685ce8b2a190f45d3de764 Mon Sep 17 00:00:00 2001 From: Hu Yueh-Wei Date: Tue, 14 Jan 2025 00:14:40 +0800 Subject: [PATCH 02/11] fix: on_xxx timing checkings --- .../binding/go/ten_env/ten_env_internal.h | 1 - .../ten_runtime/test/env_tester.h | 3 +- .../binding/go/native/test/extension_tester.c | 25 +++++---- .../python/interface/ten/async_test.py | 14 ++++- .../native/ten_env/ten_env_get_property.c | 24 +++++++++ .../ten_env/ten_env_get_property_async.c | 4 ++ .../native/ten_env/ten_env_init_property.c | 9 ++++ .../python/native/ten_env/ten_env_log.c | 4 ++ .../ten_env/ten_env_on_configure_done.c | 4 ++ .../native/ten_env/ten_env_on_deinit_done.c | 8 +++ .../native/ten_env/ten_env_on_init_done.c | 4 ++ .../native/ten_env/ten_env_on_start_done.c | 4 ++ .../native/ten_env/ten_env_on_stop_done.c | 4 ++ .../native/ten_env/ten_env_return_result.c | 8 +++ .../native/ten_env/ten_env_send_audio_frame.c | 4 ++ .../python/native/ten_env/ten_env_send_cmd.c | 4 ++ .../python/native/ten_env/ten_env_send_data.c | 4 ++ .../native/ten_env/ten_env_send_video_frame.c | 4 ++ .../native/ten_env/ten_env_set_property.c | 20 +++++++ .../ten_env/ten_env_set_property_async.c | 20 +++++++ .../native/test/env_tester/env_tester.c | 4 ++ .../native/test/env_tester/env_tester_log.c | 4 ++ .../env_tester/env_tester_on_start_done.c | 5 ++ .../test/env_tester/env_tester_stop_test.c | 4 ++ .../test/env_tester/ten_env_return_result.c | 6 ++- .../env_tester/ten_env_send_audio_frame.c | 6 ++- .../native/test/env_tester/ten_env_send_cmd.c | 9 +++- .../test/env_tester/ten_env_send_data.c | 6 ++- .../env_tester/ten_env_send_video_frame.c | 6 ++- .../python/native/test/extension_tester.c | 30 ++++++----- core/src/ten_runtime/test/env_tester.c | 43 ++++++++++----- core/src/ten_runtime/test/env_tester_proxy.c | 5 +- core/src/ten_runtime/test/extension_tester.c | 12 ++++- ...t_async_basic.py => test_async_basic_1.py} | 0 .../tests/test_async_basic_2.py | 54 +++++++++++++++++++ 35 files changed, 317 insertions(+), 49 deletions(-) rename tests/ten_runtime/integration/python/standalone_test_python/default_extension_python/tests/{test_async_basic.py => test_async_basic_1.py} (100%) create mode 100644 tests/ten_runtime/integration/python/standalone_test_python/default_extension_python/tests/test_async_basic_2.py diff --git a/core/include_internal/ten_runtime/binding/go/ten_env/ten_env_internal.h b/core/include_internal/ten_runtime/binding/go/ten_env/ten_env_internal.h index 642e816c15..c242e20e74 100644 --- a/core/include_internal/ten_runtime/binding/go/ten_env/ten_env_internal.h +++ b/core/include_internal/ten_runtime/binding/go/ten_env/ten_env_internal.h @@ -12,7 +12,6 @@ #include "include_internal/ten_runtime/extension_group/extension_group.h" #include "include_internal/ten_runtime/ten_env/ten_env.h" #include "include_internal/ten_runtime/ten_env_proxy/ten_env_proxy.h" -#include "ten_runtime/addon/extension/extension.h" #include "ten_runtime/binding/go/interface/ten/common.h" #include "ten_runtime/binding/go/interface/ten/ten_env.h" #include "ten_runtime/ten.h" diff --git a/core/include_internal/ten_runtime/test/env_tester.h b/core/include_internal/ten_runtime/test/env_tester.h index ca845c7c53..027caaac0e 100644 --- a/core/include_internal/ten_runtime/test/env_tester.h +++ b/core/include_internal/ten_runtime/test/env_tester.h @@ -35,7 +35,8 @@ typedef struct ten_env_tester_t { ten_env_tester_destroy_handler_in_target_lang_func_t destroy_handler; } ten_env_tester_t; -TEN_RUNTIME_API bool ten_env_tester_check_integrity(ten_env_tester_t *self); +TEN_RUNTIME_API bool ten_env_tester_check_integrity(ten_env_tester_t *self, + bool check_thread); TEN_RUNTIME_PRIVATE_API ten_env_tester_t *ten_env_tester_create( ten_extension_tester_t *tester); diff --git a/core/src/ten_runtime/binding/go/native/test/extension_tester.c b/core/src/ten_runtime/binding/go/native/test/extension_tester.c index 1cb65e6c9a..87ca9da89f 100644 --- a/core/src/ten_runtime/binding/go/native/test/extension_tester.c +++ b/core/src/ten_runtime/binding/go/native/test/extension_tester.c @@ -91,8 +91,9 @@ static void proxy_on_start(ten_extension_tester_t *self, ten_env_tester_t *ten_env_tester) { TEN_ASSERT(self && ten_extension_tester_check_integrity(self, true), "Should not happen."); - TEN_ASSERT(ten_env_tester && ten_env_tester_check_integrity(ten_env_tester), - "Should not happen."); + TEN_ASSERT( + ten_env_tester && ten_env_tester_check_integrity(ten_env_tester, true), + "Should not happen."); TEN_ASSERT(ten_extension_tester_get_ten_env_tester(self) == ten_env_tester, "Should not happen."); @@ -114,8 +115,9 @@ static void proxy_on_cmd(ten_extension_tester_t *self, ten_shared_ptr_t *cmd) { TEN_ASSERT(self && ten_extension_tester_check_integrity(self, true), "Should not happen."); - TEN_ASSERT(ten_env_tester && ten_env_tester_check_integrity(ten_env_tester), - "Should not happen."); + TEN_ASSERT( + ten_env_tester && ten_env_tester_check_integrity(ten_env_tester, true), + "Should not happen."); TEN_ASSERT(ten_extension_tester_get_ten_env_tester(self) == ten_env_tester, "Should not happen."); TEN_ASSERT(cmd && ten_cmd_check_integrity(cmd), "Should not happen."); @@ -141,8 +143,9 @@ static void proxy_on_data(ten_extension_tester_t *self, ten_shared_ptr_t *data) { TEN_ASSERT(self && ten_extension_tester_check_integrity(self, true), "Should not happen."); - TEN_ASSERT(ten_env_tester && ten_env_tester_check_integrity(ten_env_tester), - "Should not happen."); + TEN_ASSERT( + ten_env_tester && ten_env_tester_check_integrity(ten_env_tester, true), + "Should not happen."); TEN_ASSERT(ten_extension_tester_get_ten_env_tester(self) == ten_env_tester, "Should not happen."); TEN_ASSERT(data && ten_msg_check_integrity(data), "Should not happen."); @@ -168,8 +171,9 @@ static void proxy_on_audio_frame(ten_extension_tester_t *self, ten_shared_ptr_t *audio_frame) { TEN_ASSERT(self && ten_extension_tester_check_integrity(self, true), "Should not happen."); - TEN_ASSERT(ten_env_tester && ten_env_tester_check_integrity(ten_env_tester), - "Should not happen."); + TEN_ASSERT( + ten_env_tester && ten_env_tester_check_integrity(ten_env_tester, true), + "Should not happen."); TEN_ASSERT(ten_extension_tester_get_ten_env_tester(self) == ten_env_tester, "Should not happen."); TEN_ASSERT(audio_frame && ten_msg_check_integrity(audio_frame), @@ -196,8 +200,9 @@ static void proxy_on_video_frame(ten_extension_tester_t *self, ten_shared_ptr_t *video_frame) { TEN_ASSERT(self && ten_extension_tester_check_integrity(self, true), "Should not happen."); - TEN_ASSERT(ten_env_tester && ten_env_tester_check_integrity(ten_env_tester), - "Should not happen."); + TEN_ASSERT( + ten_env_tester && ten_env_tester_check_integrity(ten_env_tester, true), + "Should not happen."); TEN_ASSERT(ten_extension_tester_get_ten_env_tester(self) == ten_env_tester, "Should not happen."); TEN_ASSERT(video_frame && ten_msg_check_integrity(video_frame), diff --git a/core/src/ten_runtime/binding/python/interface/ten/async_test.py b/core/src/ten_runtime/binding/python/interface/ten/async_test.py index 0dcb6a9ad4..9ba36182c8 100644 --- a/core/src/ten_runtime/binding/python/interface/ten/async_test.py +++ b/core/src/ten_runtime/binding/python/interface/ten/async_test.py @@ -122,8 +122,20 @@ def __init__(self) -> None: def __del__(self) -> None: self._ten_stop_event.set() + + # TODO(Wei): The `__del__` method of `AsyncExtensionTester` might be + # called in the `self._ten_thread`, making it potentially unsuitable for + # invoking `self._ten_thread.join()`. Therefore, an explicit mechanism + # to trigger the termination of `AsyncExtensionTester` may be needed, + # where `self._ten_thread.join()` can be called instead. if hasattr(self, "_ten_thread"): - self._ten_thread.join() + current_thread = threading.current_thread() + if current_thread != self._ten_thread: + self._ten_thread.join() + else: + # If `__del__` is called in `self._ten_thread`, do not execute + # `join`. + pass def _exit_on_exception( self, async_ten_env_tester: AsyncTenEnvTester, e: Exception diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_get_property.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_get_property.c index 08e0d08fb9..5ce81b7591 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_get_property.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_get_property.c @@ -118,6 +118,10 @@ PyObject *ten_py_ten_env_get_property_to_json(PyObject *self, PyObject *args) { "Failed to parse argument when ten_env.get_property_to_json."); } + if (!py_ten_env->c_ten_env_proxy) { + Py_RETURN_NONE; + } + ten_value_t *value = ten_py_ten_property_get_and_check_if_exists(py_ten_env, path); if (!value) { @@ -163,6 +167,10 @@ PyObject *ten_py_ten_env_get_property_int(PyObject *self, PyObject *args) { "Failed to parse argument when ten_env.get_property_int."); } + if (!py_ten_env->c_ten_env_proxy) { + Py_RETURN_NONE; + } + ten_value_t *value = ten_py_ten_property_get_and_check_if_exists(py_ten_env, path); if (!value) { @@ -202,6 +210,10 @@ PyObject *ten_py_ten_env_get_property_string(PyObject *self, PyObject *args) { "Failed to parse argument when ten_env.get_property_string."); } + if (!py_ten_env->c_ten_env_proxy) { + Py_RETURN_NONE; + } + ten_value_t *value = ten_py_ten_property_get_and_check_if_exists(py_ten_env, path); if (!value) { @@ -240,6 +252,10 @@ PyObject *ten_py_ten_env_get_property_bool(PyObject *self, PyObject *args) { "Failed to parse argument when ten_env.get_property_bool."); } + if (!py_ten_env->c_ten_env_proxy) { + Py_RETURN_NONE; + } + ten_value_t *value = ten_py_ten_property_get_and_check_if_exists(py_ten_env, path); if (!value) { @@ -279,6 +295,10 @@ PyObject *ten_py_ten_env_get_property_float(PyObject *self, PyObject *args) { "Failed to parse argument when ten_env.get_property_float."); } + if (!py_ten_env->c_ten_env_proxy) { + Py_RETURN_NONE; + } + ten_value_t *value = ten_py_ten_property_get_and_check_if_exists(py_ten_env, path); if (!value) { @@ -318,6 +338,10 @@ PyObject *ten_py_ten_env_is_property_exist(PyObject *self, PyObject *args) { "Failed to parse argument when ten_env.is_property_exist."); } + if (!py_ten_env->c_ten_env_proxy) { + Py_RETURN_NONE; + } + ten_value_t *value = ten_py_ten_property_get_and_check_if_exists(py_ten_env, path); if (!value) { diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_get_property_async.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_get_property_async.c index e8d1b0be80..2f66a600be 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_get_property_async.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_get_property_async.c @@ -426,6 +426,10 @@ static PyObject *ten_py_ten_env_get_property_async(PyObject *self, "Invalid callback function when ten_env.get_property_to_json_async."); } + if (!py_ten_env->c_ten_env_proxy) { + Py_RETURN_NONE; + } + ten_error_t err; ten_error_init(&err); diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_init_property.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_init_property.c index d2b11afbeb..92f54ef001 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_init_property.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_init_property.c @@ -9,6 +9,7 @@ #include "include_internal/ten_runtime/binding/python/common/common.h" #include "include_internal/ten_runtime/binding/python/common/error.h" #include "include_internal/ten_runtime/binding/python/ten_env/ten_env.h" +#include "object.h" #include "ten_runtime/ten_env/internal/metadata.h" #include "ten_runtime/ten_env_proxy/ten_env_proxy.h" #include "ten_utils/macro/memory.h" @@ -163,6 +164,10 @@ PyObject *ten_py_ten_env_init_property_from_json(PyObject *self, "ten_env.init_property_from_json."); } + if (!py_ten_env->c_ten_env_proxy) { + Py_RETURN_NONE; + } + ten_error_t err; ten_error_init(&err); @@ -213,6 +218,10 @@ PyObject *ten_py_ten_env_init_property_from_json_async(PyObject *self, "ten_env.init_property_from_json_async."); } + if (!py_ten_env->c_ten_env_proxy) { + Py_RETURN_NONE; + } + ten_error_t err; ten_error_init(&err); diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_log.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_log.c index afad357bcc..48a4933740 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_log.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_log.c @@ -81,6 +81,10 @@ PyObject *ten_py_ten_env_log(PyObject *self, PyObject *args) { "Failed to parse argument when ten_env.log."); } + if (!py_ten_env->c_ten_env_proxy) { + Py_RETURN_NONE; + } + ten_error_t err; ten_error_init(&err); diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_configure_done.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_configure_done.c index 133a0360e6..81dba3441b 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_configure_done.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_configure_done.c @@ -38,6 +38,10 @@ PyObject *ten_py_ten_env_on_configure_done(PyObject *self, PyObject *args) { TEN_ASSERT(py_ten_env && ten_py_ten_env_check_integrity(py_ten_env), "Invalid argument."); + if (!py_ten_env->c_ten_env_proxy) { + Py_RETURN_NONE; + } + ten_error_t err; ten_error_init(&err); diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_deinit_done.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_deinit_done.c index 8b38ce6911..a62d70caa3 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_deinit_done.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_deinit_done.c @@ -47,6 +47,10 @@ static void ten_env_proxy_notify_on_deinit_done(ten_env_t *ten_env, ten_py_gil_state_release_internal(prev_state); + // TODO(Wei): Access to `c_ten_env_proxy` may result in threading issues. + // There is a possibility that it could be used simultaneously in a Python + // thread and released in a C pthread. A mechanism is needed to resolve this + // issue. if (py_ten_env->c_ten_env_proxy) { TEN_ASSERT( ten_env_proxy_get_thread_cnt(py_ten_env->c_ten_env_proxy, NULL) == 1, @@ -88,6 +92,10 @@ PyObject *ten_py_ten_env_on_deinit_done(PyObject *self, TEN_ASSERT(py_ten_env && ten_py_ten_env_check_integrity(py_ten_env), "Invalid argument."); + if (!py_ten_env->c_ten_env_proxy) { + Py_RETURN_NONE; + } + ten_error_t err; ten_error_init(&err); diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_init_done.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_init_done.c index f38ad97685..2e5ce871ba 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_init_done.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_init_done.c @@ -38,6 +38,10 @@ PyObject *ten_py_ten_env_on_init_done(PyObject *self, PyObject *args) { TEN_ASSERT(py_ten_env && ten_py_ten_env_check_integrity(py_ten_env), "Invalid argument."); + if (!py_ten_env->c_ten_env_proxy) { + Py_RETURN_NONE; + } + ten_error_t err; ten_error_init(&err); diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_start_done.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_start_done.c index db115c9161..8d403c4cd2 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_start_done.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_start_done.c @@ -36,6 +36,10 @@ PyObject *ten_py_ten_env_on_start_done(PyObject *self, TEN_ASSERT(py_ten_env && ten_py_ten_env_check_integrity(py_ten_env), "Invalid argument."); + if (!py_ten_env->c_ten_env_proxy) { + Py_RETURN_NONE; + } + ten_error_t err; ten_error_init(&err); diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_stop_done.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_stop_done.c index 2ae513920e..f718e573ec 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_stop_done.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_stop_done.c @@ -36,6 +36,10 @@ PyObject *ten_py_ten_env_on_stop_done(PyObject *self, TEN_ASSERT(py_ten_env && ten_py_ten_env_check_integrity(py_ten_env), "Invalid argument."); + if (!py_ten_env->c_ten_env_proxy) { + Py_RETURN_NONE; + } + ten_error_t err; ten_error_init(&err); diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_return_result.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_return_result.c index e5021016b0..0ba7d11a7c 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_return_result.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_return_result.c @@ -174,6 +174,10 @@ PyObject *ten_py_ten_env_return_result(PyObject *self, PyObject *args) { TEN_ASSERT(py_ten_env && ten_py_ten_env_check_integrity(py_ten_env), "Invalid argument."); + if (!py_ten_env->c_ten_env_proxy) { + Py_RETURN_NONE; + } + bool success = true; ten_error_t err; @@ -242,6 +246,10 @@ PyObject *ten_py_ten_env_return_result_directly(PyObject *self, TEN_ASSERT(py_ten_env && ten_py_ten_env_check_integrity(py_ten_env), "Invalid argument."); + if (!py_ten_env->c_ten_env_proxy) { + Py_RETURN_NONE; + } + bool success = true; ten_error_t err; diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_audio_frame.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_audio_frame.c index 7e399605eb..acab850474 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_audio_frame.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_audio_frame.c @@ -151,6 +151,10 @@ PyObject *ten_py_ten_env_send_audio_frame(PyObject *self, PyObject *args) { TEN_ASSERT(py_ten_env && ten_py_ten_env_check_integrity(py_ten_env), "Invalid argument."); + if (!py_ten_env->c_ten_env_proxy) { + Py_RETURN_NONE; + } + bool success = true; ten_error_t err; diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_cmd.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_cmd.c index fa3a19a94a..03fb2071cf 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_cmd.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_cmd.c @@ -181,6 +181,10 @@ PyObject *ten_py_ten_env_send_cmd(PyObject *self, PyObject *args) { "Invalid argument count when ten_env.send_cmd."); } + if (!py_ten_env->c_ten_env_proxy) { + Py_RETURN_NONE; + } + bool success = true; ten_error_t err; diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_data.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_data.c index f5c00d0c05..d4c80a9d8e 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_data.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_data.c @@ -150,6 +150,10 @@ PyObject *ten_py_ten_env_send_data(PyObject *self, PyObject *args) { TEN_ASSERT(py_ten_env && ten_py_ten_env_check_integrity(py_ten_env), "Invalid argument."); + if (!py_ten_env->c_ten_env_proxy) { + Py_RETURN_NONE; + } + bool success = true; ten_error_t err; diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_video_frame.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_video_frame.c index 3774abb309..cd087461bd 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_video_frame.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_video_frame.c @@ -151,6 +151,10 @@ PyObject *ten_py_ten_env_send_video_frame(PyObject *self, PyObject *args) { TEN_ASSERT(py_ten_env && ten_py_ten_env_check_integrity(py_ten_env), "Invalid argument."); + if (!py_ten_env->c_ten_env_proxy) { + Py_RETURN_NONE; + } + bool success = true; ten_error_t err; diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_set_property.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_set_property.c index 5a99c0c1a0..915bf5d30c 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_set_property.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_set_property.c @@ -112,6 +112,10 @@ PyObject *ten_py_ten_env_set_property_from_json(PyObject *self, "Failed to parse arguments when ten_env.set_property_from_json."); } + if (!py_ten_env->c_ten_env_proxy) { + Py_RETURN_NONE; + } + ten_json_t *json = ten_json_from_string(json_str, NULL); if (!json) { return ten_py_raise_py_value_error_exception( @@ -148,6 +152,10 @@ PyObject *ten_py_ten_env_set_property_int(PyObject *self, PyObject *args) { "Failed to parse arguments when ten_env.set_property_int."); } + if (!py_ten_env->c_ten_env_proxy) { + Py_RETURN_NONE; + } + ten_value_t *c_value = ten_value_create_int64(value); if (!c_value) { return ten_py_raise_py_value_error_exception( @@ -176,6 +184,10 @@ PyObject *ten_py_ten_env_set_property_string(PyObject *self, PyObject *args) { "Failed to parse arguments when ten_env.set_property_string."); } + if (!py_ten_env->c_ten_env_proxy) { + Py_RETURN_NONE; + } + ten_value_t *c_value = ten_value_create_string(value); if (!c_value) { return ten_py_raise_py_value_error_exception( @@ -204,6 +216,10 @@ PyObject *ten_py_ten_env_set_property_bool(PyObject *self, PyObject *args) { "Failed to parse arguments when ten_env.set_property_bool."); } + if (!py_ten_env->c_ten_env_proxy) { + Py_RETURN_NONE; + } + ten_value_t *c_value = ten_value_create_bool(value > 0); if (!c_value) { return ten_py_raise_py_value_error_exception( @@ -232,6 +248,10 @@ PyObject *ten_py_ten_env_set_property_float(PyObject *self, PyObject *args) { "Failed to parse arguments when ten_env.set_property_float."); } + if (!py_ten_env->c_ten_env_proxy) { + Py_RETURN_NONE; + } + ten_value_t *c_value = ten_value_create_float64(value); if (!c_value) { return ten_py_raise_py_value_error_exception( diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_set_property_async.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_set_property_async.c index 5115307c90..90833b223d 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_set_property_async.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_set_property_async.c @@ -151,6 +151,10 @@ PyObject *ten_py_ten_env_set_property_from_json_async(PyObject *self, "Failed to parse argument when ten_env.set_property_from_json_async."); } + if (!py_ten_env->c_ten_env_proxy) { + Py_RETURN_NONE; + } + ten_json_t *json = ten_json_from_string(json_str, NULL); if (!json) { return ten_py_raise_py_value_error_exception( @@ -204,6 +208,10 @@ PyObject *ten_py_ten_env_set_property_string_async(PyObject *self, "Failed to parse argument when ten_env.set_property_string_async."); } + if (!py_ten_env->c_ten_env_proxy) { + Py_RETURN_NONE; + } + ten_value_t *c_value = ten_value_create_string(value); if (!c_value) { return ten_py_raise_py_value_error_exception( @@ -248,6 +256,10 @@ PyObject *ten_py_ten_env_set_property_int_async(PyObject *self, "Failed to parse argument when ten_env.set_property_int_async."); } + if (!py_ten_env->c_ten_env_proxy) { + Py_RETURN_NONE; + } + ten_value_t *c_value = ten_value_create_int64(value); if (!c_value) { return ten_py_raise_py_value_error_exception( @@ -292,6 +304,10 @@ PyObject *ten_py_ten_env_set_property_bool_async(PyObject *self, "Failed to parse argument when ten_env.set_property_bool_async."); } + if (!py_ten_env->c_ten_env_proxy) { + Py_RETURN_NONE; + } + ten_value_t *c_value = ten_value_create_bool(value); if (!c_value) { return ten_py_raise_py_value_error_exception( @@ -336,6 +352,10 @@ PyObject *ten_py_ten_env_set_property_float_async(PyObject *self, "Failed to parse argument when ten_env.set_property_float_async."); } + if (!py_ten_env->c_ten_env_proxy) { + Py_RETURN_NONE; + } + ten_value_t *c_value = ten_value_create_float64(value); if (!c_value) { return ten_py_raise_py_value_error_exception( diff --git a/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester.c b/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester.c index 8898d7b03a..acee6f95f6 100644 --- a/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester.c +++ b/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester.c @@ -33,6 +33,10 @@ static void ten_py_ten_env_tester_c_part_destroyed( ten_py_ten_env_tester_check_integrity(ten_env_tester_bridge_), "Should not happen."); + // TODO(Wei): Access to `c_ten_env_tester_proxy` may result in threading + // issues. There is a possibility that it could be used simultaneously in a + // Python thread and released in a C pthread. A mechanism is needed to resolve + // this issue. ten_env_tester_bridge->c_ten_env_tester = NULL; if (ten_env_tester_bridge->c_ten_env_tester_proxy) { ten_env_tester_proxy_release(ten_env_tester_bridge->c_ten_env_tester_proxy, diff --git a/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_log.c b/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_log.c index 5ed0ac576c..9aa0ad89c9 100644 --- a/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_log.c +++ b/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_log.c @@ -81,6 +81,10 @@ PyObject *ten_py_ten_env_tester_log(PyObject *self, TEN_UNUSED PyObject *args) { "Failed to parse argument when ten_env.log."); } + if (!py_ten_env_tester->c_ten_env_tester_proxy) { + Py_RETURN_NONE; + } + ten_error_t err; ten_error_init(&err); diff --git a/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_on_start_done.c b/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_on_start_done.c index 5fec698ddd..993b3b0a3c 100644 --- a/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_on_start_done.c +++ b/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_on_start_done.c @@ -5,6 +5,7 @@ // Refer to the "LICENSE" file in the root directory for more information. // #include "include_internal/ten_runtime/binding/python/test/env_tester.h" +#include "object.h" #include "ten_runtime/test/env_tester.h" #include "ten_runtime/test/env_tester_proxy.h" #include "ten_utils/lib/error.h" @@ -23,6 +24,10 @@ PyObject *ten_py_ten_env_tester_on_start_done(PyObject *self, ten_py_ten_env_tester_check_integrity(py_ten_env_tester), "Invalid argument."); + if (!py_ten_env_tester->c_ten_env_tester_proxy) { + Py_RETURN_NONE; + } + ten_error_t err; ten_error_init(&err); diff --git a/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_stop_test.c b/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_stop_test.c index abe45c7b0f..f500b85a6d 100644 --- a/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_stop_test.c +++ b/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_stop_test.c @@ -22,6 +22,10 @@ PyObject *ten_py_ten_env_tester_stop_test(PyObject *self, ten_py_ten_env_tester_check_integrity(py_ten_env_tester), "Invalid argument."); + if (!py_ten_env_tester->c_ten_env_tester_proxy) { + Py_RETURN_NONE; + } + ten_error_t err; ten_error_init(&err); diff --git a/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_return_result.c b/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_return_result.c index bacb648ab4..0ded349668 100644 --- a/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_return_result.c +++ b/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_return_result.c @@ -55,7 +55,7 @@ static void ten_py_ten_env_tester_notify_return_result_ctx_destroy( static void proxy_return_result_callback(ten_env_tester_t *self, void *user_data, ten_error_t *error) { - TEN_ASSERT(self && ten_env_tester_check_integrity(self), + TEN_ASSERT(self && ten_env_tester_check_integrity(self, true), "Should not happen."); TEN_ASSERT(user_data, "Should not happen."); @@ -125,6 +125,10 @@ PyObject *ten_py_ten_env_tester_return_result(PyObject *self, PyObject *args) { "Invalid argument count when ten_env_tester.return_result."); } + if (!py_ten_env_tester->c_ten_env_tester_proxy) { + Py_RETURN_NONE; + } + bool success = true; ten_error_t err; diff --git a/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_audio_frame.c b/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_audio_frame.c index 9d44640188..917400e59b 100644 --- a/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_audio_frame.c +++ b/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_audio_frame.c @@ -48,7 +48,7 @@ static void ten_py_ten_env_tester_send_audio_frame_ctx_destroy( static void proxy_send_xxx_callback(ten_env_tester_t *self, void *user_audio_frame, ten_error_t *error) { - TEN_ASSERT(self && ten_env_tester_check_integrity(self), + TEN_ASSERT(self && ten_env_tester_check_integrity(self, true), "Should not happen."); TEN_ASSERT(user_audio_frame, "Should not happen."); @@ -119,6 +119,10 @@ PyObject *ten_py_ten_env_tester_send_audio_frame(PyObject *self, "Invalid argument count when ten_env_tester.send_audio_frame."); } + if (!py_ten_env_tester->c_ten_env_tester_proxy) { + Py_RETURN_NONE; + } + bool success = true; ten_error_t err; diff --git a/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_cmd.c b/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_cmd.c index d1eb3c578a..8501a1c898 100644 --- a/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_cmd.c +++ b/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_cmd.c @@ -51,8 +51,9 @@ static void ten_py_ten_env_tester_send_cmd_ctx_destroy( static void proxy_send_xxx_callback(ten_env_tester_t *ten_env_tester, ten_shared_ptr_t *cmd_result, void *callback_info, ten_error_t *error) { - TEN_ASSERT(ten_env_tester && ten_env_tester_check_integrity(ten_env_tester), - "Should not happen."); + TEN_ASSERT( + ten_env_tester && ten_env_tester_check_integrity(ten_env_tester, true), + "Should not happen."); TEN_ASSERT(callback_info, "Should not happen."); // About to call the Python function, so it's necessary to ensure that the GIL @@ -135,6 +136,10 @@ PyObject *ten_py_ten_env_tester_send_cmd(PyObject *self, PyObject *args) { "Invalid argument count when ten_env_tester.send_cmd."); } + if (!py_ten_env_tester->c_ten_env_tester_proxy) { + Py_RETURN_NONE; + } + bool success = true; ten_error_t err; diff --git a/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_data.c b/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_data.c index 29c89d65dc..2bdcd99aaf 100644 --- a/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_data.c +++ b/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_data.c @@ -47,7 +47,7 @@ static void ten_py_ten_env_tester_send_data_ctx_destroy( static void proxy_send_xxx_callback(ten_env_tester_t *self, void *user_data, ten_error_t *error) { - TEN_ASSERT(self && ten_env_tester_check_integrity(self), + TEN_ASSERT(self && ten_env_tester_check_integrity(self, true), "Should not happen."); TEN_ASSERT(user_data, "Should not happen."); @@ -115,6 +115,10 @@ PyObject *ten_py_ten_env_tester_send_data(PyObject *self, PyObject *args) { "Invalid argument count when ten_env_tester.send_data."); } + if (!py_ten_env_tester->c_ten_env_tester_proxy) { + Py_RETURN_NONE; + } + bool success = true; ten_error_t err; diff --git a/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_video_frame.c b/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_video_frame.c index f789eab5c9..3f7f1ec95a 100644 --- a/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_video_frame.c +++ b/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_video_frame.c @@ -48,7 +48,7 @@ static void ten_py_ten_env_tester_send_video_frame_ctx_destroy( static void proxy_send_xxx_callback(ten_env_tester_t *self, void *user_video_frame, ten_error_t *error) { - TEN_ASSERT(self && ten_env_tester_check_integrity(self), + TEN_ASSERT(self && ten_env_tester_check_integrity(self, true), "Should not happen."); TEN_ASSERT(user_video_frame, "Should not happen."); @@ -119,6 +119,10 @@ PyObject *ten_py_ten_env_tester_send_video_frame(PyObject *self, "Invalid argument count when ten_env_tester.send_video_frame."); } + if (!py_ten_env_tester->c_ten_env_tester_proxy) { + Py_RETURN_NONE; + } + bool success = true; ten_error_t err; diff --git a/core/src/ten_runtime/binding/python/native/test/extension_tester.c b/core/src/ten_runtime/binding/python/native/test/extension_tester.c index 55d60b6d4f..5f78601fd3 100644 --- a/core/src/ten_runtime/binding/python/native/test/extension_tester.c +++ b/core/src/ten_runtime/binding/python/native/test/extension_tester.c @@ -56,8 +56,9 @@ static void proxy_on_start(ten_extension_tester_t *extension_tester, TEN_ASSERT(extension_tester && ten_extension_tester_check_integrity(extension_tester, true), "Invalid argument."); - TEN_ASSERT(ten_env_tester && ten_env_tester_check_integrity(ten_env_tester), - "Invalid argument."); + TEN_ASSERT( + ten_env_tester && ten_env_tester_check_integrity(ten_env_tester, true), + "Invalid argument."); // About to call the Python function, so it's necessary to ensure that the GIL // has been acquired. @@ -95,8 +96,9 @@ static void proxy_on_stop(ten_extension_tester_t *extension_tester, TEN_ASSERT(extension_tester && ten_extension_tester_check_integrity(extension_tester, true), "Invalid argument."); - TEN_ASSERT(ten_env_tester && ten_env_tester_check_integrity(ten_env_tester), - "Invalid argument."); + TEN_ASSERT( + ten_env_tester && ten_env_tester_check_integrity(ten_env_tester, true), + "Invalid argument."); ten_py_extension_tester_t *py_extension_tester = (ten_py_extension_tester_t *)ten_binding_handle_get_me_in_target_lang( @@ -137,8 +139,9 @@ static void proxy_on_cmd(ten_extension_tester_t *extension_tester, TEN_ASSERT(extension_tester && ten_extension_tester_check_integrity(extension_tester, true), "Invalid argument."); - TEN_ASSERT(ten_env_tester && ten_env_tester_check_integrity(ten_env_tester), - "Invalid argument."); + TEN_ASSERT( + ten_env_tester && ten_env_tester_check_integrity(ten_env_tester, true), + "Invalid argument."); TEN_ASSERT(cmd && ten_msg_check_integrity(cmd), "Invalid argument."); // About to call the Python function, so it's necessary to ensure that the GIL @@ -180,8 +183,9 @@ static void proxy_on_data(ten_extension_tester_t *extension_tester, TEN_ASSERT(extension_tester && ten_extension_tester_check_integrity(extension_tester, true), "Invalid argument."); - TEN_ASSERT(ten_env_tester && ten_env_tester_check_integrity(ten_env_tester), - "Invalid argument."); + TEN_ASSERT( + ten_env_tester && ten_env_tester_check_integrity(ten_env_tester, true), + "Invalid argument."); TEN_ASSERT(data && ten_msg_check_integrity(data), "Invalid argument."); // About to call the Python function, so it's necessary to ensure that the GIL @@ -223,8 +227,9 @@ static void proxy_on_audio_frame(ten_extension_tester_t *extension_tester, TEN_ASSERT(extension_tester && ten_extension_tester_check_integrity(extension_tester, true), "Invalid argument."); - TEN_ASSERT(ten_env_tester && ten_env_tester_check_integrity(ten_env_tester), - "Invalid argument."); + TEN_ASSERT( + ten_env_tester && ten_env_tester_check_integrity(ten_env_tester, true), + "Invalid argument."); TEN_ASSERT(audio_frame && ten_msg_check_integrity(audio_frame), "Invalid argument."); @@ -267,8 +272,9 @@ static void proxy_on_video_frame(ten_extension_tester_t *extension_tester, TEN_ASSERT(extension_tester && ten_extension_tester_check_integrity(extension_tester, true), "Invalid argument."); - TEN_ASSERT(ten_env_tester && ten_env_tester_check_integrity(ten_env_tester), - "Invalid argument."); + TEN_ASSERT( + ten_env_tester && ten_env_tester_check_integrity(ten_env_tester, true), + "Invalid argument."); TEN_ASSERT(video_frame && ten_msg_check_integrity(video_frame), "Invalid argument."); diff --git a/core/src/ten_runtime/test/env_tester.c b/core/src/ten_runtime/test/env_tester.c index e79434ab27..e6d273beb2 100644 --- a/core/src/ten_runtime/test/env_tester.c +++ b/core/src/ten_runtime/test/env_tester.c @@ -26,7 +26,7 @@ #include "ten_utils/macro/mark.h" #include "ten_utils/macro/memory.h" -bool ten_env_tester_check_integrity(ten_env_tester_t *self) { +bool ten_env_tester_check_integrity(ten_env_tester_t *self, bool check_thread) { TEN_ASSERT(self, "Should not happen."); if (ten_signature_get(&self->signature) != @@ -36,7 +36,8 @@ bool ten_env_tester_check_integrity(ten_env_tester_t *self) { return false; } - if (!ten_sanitizer_thread_check_do_check(&self->tester->thread_check)) { + if (check_thread && + !ten_sanitizer_thread_check_do_check(&self->tester->thread_check)) { return false; } @@ -63,7 +64,12 @@ ten_env_tester_t *ten_env_tester_create(ten_extension_tester_t *tester) { } void ten_env_tester_destroy(ten_env_tester_t *self) { - TEN_ASSERT(self && ten_env_tester_check_integrity(self), "Invalid argument."); + TEN_ASSERT(self && + // TEN_NOLINTNEXTLINE(thread-check) + // thread-check: In TEN world, the destroy operations need to + // be performed in any threads. + ten_env_tester_check_integrity(self, false), + "Invalid argument."); if (self->destroy_handler && self->binding_handle.me_in_target_lang) { self->destroy_handler(self->binding_handle.me_in_target_lang); @@ -609,7 +615,8 @@ static void test_extension_ten_env_send_video_frame(ten_env_t *ten_env, bool ten_env_tester_send_cmd(ten_env_tester_t *self, ten_shared_ptr_t *cmd, ten_env_tester_cmd_result_handler_func_t handler, void *user_data, ten_error_t *err) { - TEN_ASSERT(self && ten_env_tester_check_integrity(self), "Invalid argument."); + TEN_ASSERT(self && ten_env_tester_check_integrity(self, true), + "Invalid argument."); ten_env_tester_send_cmd_ctx_t *send_cmd_info = ten_extension_tester_send_cmd_ctx_create( self->tester, ten_shared_ptr_clone(cmd), handler, user_data); @@ -630,7 +637,8 @@ bool ten_env_tester_return_result( ten_shared_ptr_t *target_cmd, ten_env_tester_error_handler_func_t error_handler, void *user_data, ten_error_t *error) { - TEN_ASSERT(self && ten_env_tester_check_integrity(self), "Invalid argument."); + TEN_ASSERT(self && ten_env_tester_check_integrity(self, true), + "Invalid argument."); ten_env_tester_return_result_ctx_t *return_result_info = ten_extension_tester_return_result_ctx_create( @@ -652,7 +660,8 @@ bool ten_env_tester_return_result( bool ten_env_tester_send_data(ten_env_tester_t *self, ten_shared_ptr_t *data, ten_env_tester_error_handler_func_t handler, void *user_data, ten_error_t *err) { - TEN_ASSERT(self && ten_env_tester_check_integrity(self), "Invalid argument."); + TEN_ASSERT(self && ten_env_tester_check_integrity(self, true), + "Invalid argument."); ten_env_tester_send_msg_ctx_t *send_msg_info = ten_extension_tester_send_msg_ctx_create( @@ -673,7 +682,8 @@ bool ten_env_tester_send_audio_frame( ten_env_tester_t *self, ten_shared_ptr_t *audio_frame, ten_env_tester_error_handler_func_t handler, void *user_data, ten_error_t *err) { - TEN_ASSERT(self && ten_env_tester_check_integrity(self), "Invalid argument."); + TEN_ASSERT(self && ten_env_tester_check_integrity(self, true), + "Invalid argument."); ten_env_tester_send_msg_ctx_t *send_msg_info = ten_extension_tester_send_msg_ctx_create( @@ -694,7 +704,8 @@ bool ten_env_tester_send_video_frame( ten_env_tester_t *self, ten_shared_ptr_t *video_frame, ten_env_tester_error_handler_func_t handler, void *user_data, ten_error_t *err) { - TEN_ASSERT(self && ten_env_tester_check_integrity(self), "Invalid argument."); + TEN_ASSERT(self && ten_env_tester_check_integrity(self, true), + "Invalid argument."); ten_env_tester_send_msg_ctx_t *send_msg_info = ten_extension_tester_send_msg_ctx_create( @@ -731,7 +742,8 @@ static void test_app_ten_env_send_close_app_cmd(ten_env_t *ten_env, } bool ten_env_tester_stop_test(ten_env_tester_t *self, ten_error_t *err) { - TEN_ASSERT(self && ten_env_tester_check_integrity(self), "Invalid argument."); + TEN_ASSERT(self && ten_env_tester_check_integrity(self, true), + "Invalid argument."); return ten_env_proxy_notify(self->tester->test_app_ten_env_proxy, test_app_ten_env_send_close_app_cmd, NULL, false, err); @@ -751,7 +763,8 @@ static void test_extension_ten_env_log(ten_env_t *self, void *user_data) { bool ten_env_tester_log(ten_env_tester_t *self, TEN_LOG_LEVEL level, const char *func_name, const char *file_name, size_t line_no, const char *msg, ten_error_t *error) { - TEN_ASSERT(self && ten_env_tester_check_integrity(self), "Invalid argument."); + TEN_ASSERT(self && ten_env_tester_check_integrity(self, true), + "Invalid argument."); ten_env_tester_notify_log_ctx_t *ctx = ten_env_tester_notify_log_ctx_create( self, level, func_name, file_name, line_no, msg); @@ -767,7 +780,8 @@ bool ten_env_tester_log(ten_env_tester_t *self, TEN_LOG_LEVEL level, } bool ten_env_tester_on_start_done(ten_env_tester_t *self, ten_error_t *err) { - TEN_ASSERT(self && ten_env_tester_check_integrity(self), "Invalid argument."); + TEN_ASSERT(self && ten_env_tester_check_integrity(self, true), + "Invalid argument."); ten_extension_tester_on_start_done(self->tester); @@ -775,7 +789,8 @@ bool ten_env_tester_on_start_done(ten_env_tester_t *self, ten_error_t *err) { } bool ten_env_tester_on_stop_done(ten_env_tester_t *self, ten_error_t *err) { - TEN_ASSERT(self && ten_env_tester_check_integrity(self), "Invalid argument."); + TEN_ASSERT(self && ten_env_tester_check_integrity(self, true), + "Invalid argument."); ten_extension_tester_on_stop_done(self->tester); @@ -786,7 +801,7 @@ void ten_env_tester_set_close_handler_in_target_lang( ten_env_tester_t *self, ten_env_tester_close_handler_in_target_lang_func_t close_handler) { TEN_ASSERT(self, "Invalid argument."); - TEN_ASSERT(ten_env_tester_check_integrity(self), + TEN_ASSERT(ten_env_tester_check_integrity(self, true), "Invalid use of ten_env_tester %p.", self); self->close_handler = close_handler; @@ -796,7 +811,7 @@ void ten_env_tester_set_destroy_handler_in_target_lang( ten_env_tester_t *self, ten_env_tester_destroy_handler_in_target_lang_func_t destroy_handler) { TEN_ASSERT(self, "Invalid argument."); - TEN_ASSERT(ten_env_tester_check_integrity(self), + TEN_ASSERT(ten_env_tester_check_integrity(self, true), "Invalid use of ten_env_tester %p.", self); self->destroy_handler = destroy_handler; diff --git a/core/src/ten_runtime/test/env_tester_proxy.c b/core/src/ten_runtime/test/env_tester_proxy.c index e71fb29fe1..738d15e4d7 100644 --- a/core/src/ten_runtime/test/env_tester_proxy.c +++ b/core/src/ten_runtime/test/env_tester_proxy.c @@ -58,8 +58,9 @@ ten_env_tester_proxy_t *ten_env_tester_proxy_create( static void ten_env_tester_on_proxy_deleted(void *self_, void *arg) { ten_env_tester_t *ten_env_tester = self_; ten_env_tester_proxy_t *self = arg; - TEN_ASSERT(ten_env_tester && ten_env_tester_check_integrity(ten_env_tester), - "Should not happen."); + TEN_ASSERT( + ten_env_tester && ten_env_tester_check_integrity(ten_env_tester, true), + "Should not happen."); TEN_ASSERT(self && ten_env_tester_proxy_check_integrity(self), "Should not happen."); diff --git a/core/src/ten_runtime/test/extension_tester.c b/core/src/ten_runtime/test/extension_tester.c index a945fcb01a..618618f484 100644 --- a/core/src/ten_runtime/test/extension_tester.c +++ b/core/src/ten_runtime/test/extension_tester.c @@ -185,7 +185,11 @@ void test_app_ten_env_send_cmd(ten_env_t *ten_env, void *user_data) { static void ten_extension_tester_destroy_test_target( ten_extension_tester_t *self) { - TEN_ASSERT(self && ten_extension_tester_check_integrity(self, true), + TEN_ASSERT(self && + // TEN_NOLINTNEXTLINE(thread-check) + // thread-check: In TEN world, the destroy operations need to + // be performed in any threads. + ten_extension_tester_check_integrity(self, false), "Invalid argument."); if (self->test_mode == TEN_EXTENSION_TESTER_TEST_MODE_SINGLE) { @@ -197,7 +201,11 @@ static void ten_extension_tester_destroy_test_target( } void ten_extension_tester_destroy(ten_extension_tester_t *self) { - TEN_ASSERT(self && ten_extension_tester_check_integrity(self, true), + TEN_ASSERT(self && + // TEN_NOLINTNEXTLINE(thread-check) + // thread-check: In TEN world, the destroy operations need to + // be performed in any threads. + ten_extension_tester_check_integrity(self, false), "Invalid argument."); TEN_ASSERT(self->test_app_ten_env_proxy == NULL, diff --git a/tests/ten_runtime/integration/python/standalone_test_python/default_extension_python/tests/test_async_basic.py b/tests/ten_runtime/integration/python/standalone_test_python/default_extension_python/tests/test_async_basic_1.py similarity index 100% rename from tests/ten_runtime/integration/python/standalone_test_python/default_extension_python/tests/test_async_basic.py rename to tests/ten_runtime/integration/python/standalone_test_python/default_extension_python/tests/test_async_basic_1.py diff --git a/tests/ten_runtime/integration/python/standalone_test_python/default_extension_python/tests/test_async_basic_2.py b/tests/ten_runtime/integration/python/standalone_test_python/default_extension_python/tests/test_async_basic_2.py new file mode 100644 index 0000000000..2b17d2f9fc --- /dev/null +++ b/tests/ten_runtime/integration/python/standalone_test_python/default_extension_python/tests/test_async_basic_2.py @@ -0,0 +1,54 @@ +# +# Copyright © 2025 Agora +# This file is part of TEN Framework, an open source project. +# Licensed under the Apache License, Version 2.0, with certain conditions. +# Refer to the "LICENSE" file in the root directory for more information. +# +import asyncio +from ten import ( + Cmd, + Data, + AudioFrame, + VideoFrame, + StatusCode, + AsyncExtensionTester, + AsyncTenEnvTester, +) + + +class AsyncExtensionTesterBasic(AsyncExtensionTester): + async def on_start(self, ten_env: AsyncTenEnvTester) -> None: + await ten_env.send_data(Data.create("test")) + await ten_env.send_audio_frame(AudioFrame.create("test")) + await ten_env.send_video_frame(VideoFrame.create("test")) + + new_cmd = Cmd.create("hello_world") + + ten_env.log_info("send hello_world") + result, error = await ten_env.send_cmd( + new_cmd, + ) + if error is not None: + assert False, error + + assert result is not None + + statusCode = result.get_status_code() + ten_env.log_info("receive hello_world, status:" + str(statusCode)) + + ten_env.log_info("tester on_start_done") + + if statusCode == StatusCode.OK: + ten_env.stop_test() + + await asyncio.sleep(3) + + +def test_basic(): + tester = AsyncExtensionTesterBasic() + tester.set_test_mode_single("default_extension_python") + tester.run() + + +if __name__ == "__main__": + test_basic() From b26526cdf533ea6a4c8764ab40d4732d507f7e1e Mon Sep 17 00:00:00 2001 From: sunxilin Date: Tue, 14 Jan 2025 16:46:01 +0800 Subject: [PATCH 03/11] fix: join tester thread during stop stage --- .vscode/launch.json | 2 +- .../binding/python/test/env_tester.h | 3 + .../python/interface/ten/async_extension.py | 4 +- .../python/interface/ten/async_test.py | 34 +++++---- .../interface/ten/libten_runtime_python.pyi | 1 + .../binding/python/interface/ten/test.py | 15 +++- .../native/ten_env/ten_env_get_property.c | 24 +++++-- .../ten_env/ten_env_get_property_async.c | 4 +- .../native/ten_env/ten_env_init_property.c | 9 ++- .../python/native/ten_env/ten_env_log.c | 9 +-- .../ten_env/ten_env_on_configure_done.c | 10 +-- .../native/ten_env/ten_env_on_deinit_done.c | 18 +++-- .../native/ten_env/ten_env_on_init_done.c | 10 +-- .../native/ten_env/ten_env_on_start_done.c | 5 +- .../native/ten_env/ten_env_on_stop_done.c | 5 +- .../native/ten_env/ten_env_return_result.c | 8 ++- .../native/ten_env/ten_env_send_audio_frame.c | 4 +- .../python/native/ten_env/ten_env_send_cmd.c | 3 +- .../python/native/ten_env/ten_env_send_data.c | 3 +- .../native/ten_env/ten_env_send_video_frame.c | 4 +- .../native/ten_env/ten_env_set_property.c | 4 +- .../ten_env/ten_env_set_property_async.c | 20 ++++-- .../native/test/env_tester/env_tester.c | 10 +-- .../native/test/env_tester/env_tester_log.c | 5 +- .../env_tester/env_tester_on_start_done.c | 7 +- .../test/env_tester/env_tester_on_stop_done.c | 72 +++++++++++++++++++ .../test/env_tester/env_tester_stop_test.c | 6 +- .../test/env_tester/ten_env_return_result.c | 5 +- .../env_tester/ten_env_send_audio_frame.c | 5 +- .../native/test/env_tester/ten_env_send_cmd.c | 5 +- .../test/env_tester/ten_env_send_data.c | 5 +- .../env_tester/ten_env_send_video_frame.c | 5 +- .../python/native/test/extension_tester.c | 6 -- .../ten_runtime/extension/ten_env/on_xxx.c | 60 ++++++++++------ 34 files changed, 278 insertions(+), 112 deletions(-) create mode 100644 core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_on_stop_done.c diff --git a/.vscode/launch.json b/.vscode/launch.json index d00d50ef05..a1d58322a0 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -834,7 +834,7 @@ "name": "Python Debugger: Python File", "type": "debugpy", "request": "launch", - "program": "${workspaceFolder}/out/linux/x64/tests/ten_runtime/integration/python/standalone_test_python/default_extension_python/tests/test_async_outer_thread.py", + "program": "${workspaceFolder}/out/linux/x64/tests/ten_runtime/integration/python/standalone_test_python/default_extension_python/tests/test_basic.py", "env": { "PYTHONPATH": "${workspaceFolder}/out/linux/x64/tests/ten_runtime/integration/python/standalone_test_python/default_extension_python/.ten/app/ten_packages/system/ten_runtime_python/lib:${workspaceFolder}/out/linux/x64/tests/ten_runtime/integration/python/standalone_test_python/default_extension_python/.ten/app/ten_packages/system/ten_runtime_python/interface:${workspaceFolder}/out/linux/x64/tests/ten_runtime/integration/python/standalone_test_python/default_extension_python/.ten/app", "LD_PRELOAD": "${workspaceFolder}/out/linux/x64/tests/ten_runtime/integration/python/standalone_test_python/default_extension_python/.ten/app/ten_packages/system/ten_runtime/lib/libasan.so" diff --git a/core/include_internal/ten_runtime/binding/python/test/env_tester.h b/core/include_internal/ten_runtime/binding/python/test/env_tester.h index dd5f94448d..c0831b739d 100644 --- a/core/include_internal/ten_runtime/binding/python/test/env_tester.h +++ b/core/include_internal/ten_runtime/binding/python/test/env_tester.h @@ -44,6 +44,9 @@ TEN_RUNTIME_PRIVATE_API PyTypeObject *ten_py_ten_env_tester_type(void); TEN_RUNTIME_PRIVATE_API PyObject *ten_py_ten_env_tester_on_start_done( PyObject *self, PyObject *args); +TEN_RUNTIME_PRIVATE_API PyObject *ten_py_ten_env_tester_on_stop_done( + PyObject *self, PyObject *args); + TEN_RUNTIME_PRIVATE_API PyObject *ten_py_ten_env_tester_stop_test( PyObject *self, PyObject *args); diff --git a/core/src/ten_runtime/binding/python/interface/ten/async_extension.py b/core/src/ten_runtime/binding/python/interface/ten/async_extension.py index b9a467f713..76f7118119 100644 --- a/core/src/ten_runtime/binding/python/interface/ten/async_extension.py +++ b/core/src/ten_runtime/binding/python/interface/ten/async_extension.py @@ -27,9 +27,7 @@ def __init__(self, name: str) -> None: self._ten_stop_event = asyncio.Event() def __del__(self) -> None: - self._ten_stop_event.set() - if hasattr(self, "_ten_thread"): - self._ten_thread.join() + pass async def _thread_routine(self, ten_env: TenEnv): self._ten_loop = asyncio.get_running_loop() diff --git a/core/src/ten_runtime/binding/python/interface/ten/async_test.py b/core/src/ten_runtime/binding/python/interface/ten/async_test.py index 9ba36182c8..39e112d874 100644 --- a/core/src/ten_runtime/binding/python/interface/ten/async_test.py +++ b/core/src/ten_runtime/binding/python/interface/ten/async_test.py @@ -34,10 +34,26 @@ def __init__( self._ten_loop = loop self._ten_thread = thread + ten_env_tester._set_release_handler(lambda: self._on_release()) def __del__(self) -> None: pass + def _deinit_routine(self) -> None: + # Wait for the internal thread to finish. + self._ten_thread.join() + + self._internal.on_stop_done() + + def _on_release(self) -> None: + if hasattr(self, "_deinit_thread"): + self._deinit_thread.join() + + def _deinit(self) -> None: + # Start the deinit thread to avoid blocking the extension tester thread. + self._deinit_thread = threading.Thread(target=self._deinit_routine) + self._deinit_thread.start() + async def send_cmd(self, cmd: Cmd) -> CmdResultTuple: q = asyncio.Queue(maxsize=1) self._internal.send_cmd( @@ -121,21 +137,7 @@ def __init__(self) -> None: self._ten_stop_event = asyncio.Event() def __del__(self) -> None: - self._ten_stop_event.set() - - # TODO(Wei): The `__del__` method of `AsyncExtensionTester` might be - # called in the `self._ten_thread`, making it potentially unsuitable for - # invoking `self._ten_thread.join()`. Therefore, an explicit mechanism - # to trigger the termination of `AsyncExtensionTester` may be needed, - # where `self._ten_thread.join()` can be called instead. - if hasattr(self, "_ten_thread"): - current_thread = threading.current_thread() - if current_thread != self._ten_thread: - self._ten_thread.join() - else: - # If `__del__` is called in `self._ten_thread`, do not execute - # `join`. - pass + pass def _exit_on_exception( self, async_ten_env_tester: AsyncTenEnvTester, e: Exception @@ -158,6 +160,8 @@ async def _thread_routine(self, ten_env_tester: TenEnvTester) -> None: # Suspend the thread until stopEvent is set. await self._ten_stop_event.wait() + self._async_ten_env_tester._deinit() + async def _stop_thread(self): self._ten_stop_event.set() diff --git a/core/src/ten_runtime/binding/python/interface/ten/libten_runtime_python.pyi b/core/src/ten_runtime/binding/python/interface/ten/libten_runtime_python.pyi index 4bafb028c6..aad12bfba4 100644 --- a/core/src/ten_runtime/binding/python/interface/ten/libten_runtime_python.pyi +++ b/core/src/ten_runtime/binding/python/interface/ten/libten_runtime_python.pyi @@ -245,6 +245,7 @@ class _Addon: class _TenEnvTester: def on_start_done(self) -> None: ... + def on_stop_done(self) -> None: ... def send_cmd( self, cmd: _Cmd, result_handler: TestResultHandler ) -> None: ... diff --git a/core/src/ten_runtime/binding/python/interface/ten/test.py b/core/src/ten_runtime/binding/python/interface/ten/test.py index 817aa11a8b..e6505e4442 100644 --- a/core/src/ten_runtime/binding/python/interface/ten/test.py +++ b/core/src/ten_runtime/binding/python/interface/ten/test.py @@ -34,9 +34,19 @@ def __init__(self, internal_obj: _TenEnvTester) -> None: def __del__(self) -> None: pass + def _set_release_handler(self, handler: Callable[[], None]) -> None: + self._release_handler = handler + + def _on_release(self) -> None: + if hasattr(self, "_release_handler"): + self._release_handler() + def on_start_done(self) -> None: return self._internal.on_start_done() + def on_stop_done(self) -> None: + return self._internal.on_stop_done() + def send_cmd(self, cmd: Cmd, result_handler: ResultHandler) -> None: return self._internal.send_cmd(cmd, result_handler) @@ -89,7 +99,10 @@ def on_start(self, ten_env_tester: TenEnvTester) -> None: @final def _proxy_on_stop(self, ten_env_tester: TenEnvTester) -> None: - pass + self.on_stop(ten_env_tester) + + def on_stop(self, ten_env_tester: TenEnvTester) -> None: + ten_env_tester.on_stop_done() @final def _proxy_on_cmd(self, ten_env_tester: TenEnvTester, cmd: Cmd) -> None: diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_get_property.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_get_property.c index 5ce81b7591..532065652a 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_get_property.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_get_property.c @@ -119,7 +119,9 @@ PyObject *ten_py_ten_env_get_property_to_json(PyObject *self, PyObject *args) { } if (!py_ten_env->c_ten_env_proxy) { - Py_RETURN_NONE; + return ten_py_raise_py_value_error_exception( + "ten_env.get_property_to_json() failed because the c_ten_env_proxy is " + "invalid."); } ten_value_t *value = @@ -168,7 +170,9 @@ PyObject *ten_py_ten_env_get_property_int(PyObject *self, PyObject *args) { } if (!py_ten_env->c_ten_env_proxy) { - Py_RETURN_NONE; + return ten_py_raise_py_value_error_exception( + "ten_env.get_property_int() failed because the c_ten_env_proxy is " + "invalid."); } ten_value_t *value = @@ -211,7 +215,9 @@ PyObject *ten_py_ten_env_get_property_string(PyObject *self, PyObject *args) { } if (!py_ten_env->c_ten_env_proxy) { - Py_RETURN_NONE; + return ten_py_raise_py_value_error_exception( + "ten_env.get_property_string() failed because the c_ten_env_proxy is " + "invalid."); } ten_value_t *value = @@ -253,7 +259,9 @@ PyObject *ten_py_ten_env_get_property_bool(PyObject *self, PyObject *args) { } if (!py_ten_env->c_ten_env_proxy) { - Py_RETURN_NONE; + return ten_py_raise_py_value_error_exception( + "ten_env.get_property_bool() failed because the c_ten_env_proxy is " + "invalid."); } ten_value_t *value = @@ -296,7 +304,9 @@ PyObject *ten_py_ten_env_get_property_float(PyObject *self, PyObject *args) { } if (!py_ten_env->c_ten_env_proxy) { - Py_RETURN_NONE; + return ten_py_raise_py_value_error_exception( + "ten_env.get_property_float() failed because the c_ten_env_proxy is " + "invalid."); } ten_value_t *value = @@ -339,7 +349,9 @@ PyObject *ten_py_ten_env_is_property_exist(PyObject *self, PyObject *args) { } if (!py_ten_env->c_ten_env_proxy) { - Py_RETURN_NONE; + return ten_py_raise_py_value_error_exception( + "ten_env.is_property_exist() failed because the c_ten_env_proxy is " + "invalid."); } ten_value_t *value = diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_get_property_async.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_get_property_async.c index 2f66a600be..914d12f623 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_get_property_async.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_get_property_async.c @@ -427,7 +427,9 @@ static PyObject *ten_py_ten_env_get_property_async(PyObject *self, } if (!py_ten_env->c_ten_env_proxy) { - Py_RETURN_NONE; + return ten_py_raise_py_value_error_exception( + "ten_env.get_property_to_json_async() failed because the c_ten_env_proxy " + "is invalid."); } ten_error_t err; diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_init_property.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_init_property.c index 92f54ef001..e158cdff41 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_init_property.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_init_property.c @@ -9,7 +9,6 @@ #include "include_internal/ten_runtime/binding/python/common/common.h" #include "include_internal/ten_runtime/binding/python/common/error.h" #include "include_internal/ten_runtime/binding/python/ten_env/ten_env.h" -#include "object.h" #include "ten_runtime/ten_env/internal/metadata.h" #include "ten_runtime/ten_env_proxy/ten_env_proxy.h" #include "ten_utils/macro/memory.h" @@ -165,7 +164,9 @@ PyObject *ten_py_ten_env_init_property_from_json(PyObject *self, } if (!py_ten_env->c_ten_env_proxy) { - Py_RETURN_NONE; + return ten_py_raise_py_value_error_exception( + "ten_env.init_property_from_json() failed because the c_ten_env_proxy " + "is invalid."); } ten_error_t err; @@ -219,7 +220,9 @@ PyObject *ten_py_ten_env_init_property_from_json_async(PyObject *self, } if (!py_ten_env->c_ten_env_proxy) { - Py_RETURN_NONE; + return ten_py_raise_py_value_error_exception( + "ten_env.init_property_from_json_async() failed because the " + "c_ten_env_proxy is invalid."); } ten_error_t err; diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_log.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_log.c index f536e381d6..13c8e47f86 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_log.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_log.c @@ -98,10 +98,6 @@ PyObject *ten_py_ten_env_log(PyObject *self, PyObject *args) { "Failed to parse argument when ten_env.log."); } - if (!py_ten_env->c_ten_env_proxy) { - Py_RETURN_NONE; - } - ten_error_t err; ten_error_init(&err); @@ -115,6 +111,11 @@ PyObject *ten_py_ten_env_log(PyObject *self, PyObject *args) { ten_env_log_without_check_thread(py_ten_env->c_ten_env, level, func_name, file_name, line_no, msg); } else { + if (!py_ten_env->c_ten_env_proxy) { + return ten_py_raise_py_value_error_exception( + "ten_env.log() failed because the c_ten_env_proxy is invalid."); + } + ten_env_notify_log_ctx_t *ctx = ten_env_notify_log_ctx_create( level, func_name, file_name, line_no, msg); diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_configure_done.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_configure_done.c index 81dba3441b..536e809ed2 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_configure_done.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_configure_done.c @@ -38,10 +38,6 @@ PyObject *ten_py_ten_env_on_configure_done(PyObject *self, PyObject *args) { TEN_ASSERT(py_ten_env && ten_py_ten_env_check_integrity(py_ten_env), "Invalid argument."); - if (!py_ten_env->c_ten_env_proxy) { - Py_RETURN_NONE; - } - ten_error_t err; ten_error_init(&err); @@ -50,6 +46,12 @@ PyObject *ten_py_ten_env_on_configure_done(PyObject *self, PyObject *args) { if (py_ten_env->c_ten_env->attach_to == TEN_ENV_ATTACH_TO_ADDON) { rc = ten_env_on_configure_done(py_ten_env->c_ten_env, &err); } else { + if (!py_ten_env->c_ten_env_proxy) { + return ten_py_raise_py_value_error_exception( + "ten_env.on_configure_done() failed because the c_ten_env_proxy is " + "invalid."); + } + rc = ten_env_proxy_notify_async(py_ten_env->c_ten_env_proxy, ten_env_proxy_notify_on_configure_done, NULL, &err); diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_deinit_done.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_deinit_done.c index a62d70caa3..2e4c2854be 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_deinit_done.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_deinit_done.c @@ -45,12 +45,6 @@ static void ten_env_proxy_notify_on_deinit_done(ten_env_t *ten_env, bool err_occurred = ten_py_check_and_clear_py_error(); TEN_ASSERT(!err_occurred, "Should not happen."); - ten_py_gil_state_release_internal(prev_state); - - // TODO(Wei): Access to `c_ten_env_proxy` may result in threading issues. - // There is a possibility that it could be used simultaneously in a Python - // thread and released in a C pthread. A mechanism is needed to resolve this - // issue. if (py_ten_env->c_ten_env_proxy) { TEN_ASSERT( ten_env_proxy_get_thread_cnt(py_ten_env->c_ten_env_proxy, NULL) == 1, @@ -64,6 +58,8 @@ static void ten_env_proxy_notify_on_deinit_done(ten_env_t *ten_env, TEN_ASSERT(rc, "Should not happen."); } + ten_py_gil_state_release_internal(prev_state); + bool rc = ten_env_on_deinit_done(ten_env, &err); TEN_ASSERT(rc, "Should not happen."); @@ -92,10 +88,6 @@ PyObject *ten_py_ten_env_on_deinit_done(PyObject *self, TEN_ASSERT(py_ten_env && ten_py_ten_env_check_integrity(py_ten_env), "Invalid argument."); - if (!py_ten_env->c_ten_env_proxy) { - Py_RETURN_NONE; - } - ten_error_t err; ten_error_init(&err); @@ -103,6 +95,12 @@ PyObject *ten_py_ten_env_on_deinit_done(PyObject *self, if (py_ten_env->c_ten_env->attach_to == TEN_ENV_ATTACH_TO_ADDON) { rc = ten_env_on_deinit_done(py_ten_env->c_ten_env, &err); } else { + if (!py_ten_env->c_ten_env_proxy) { + return ten_py_raise_py_value_error_exception( + "ten_env.on_deinit_done() failed because the c_ten_env_proxy is " + "invalid."); + } + rc = ten_env_proxy_notify(py_ten_env->c_ten_env_proxy, ten_env_proxy_notify_on_deinit_done, py_ten_env, false, &err); diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_init_done.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_init_done.c index 2e5ce871ba..c7fa33072a 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_init_done.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_init_done.c @@ -38,10 +38,6 @@ PyObject *ten_py_ten_env_on_init_done(PyObject *self, PyObject *args) { TEN_ASSERT(py_ten_env && ten_py_ten_env_check_integrity(py_ten_env), "Invalid argument."); - if (!py_ten_env->c_ten_env_proxy) { - Py_RETURN_NONE; - } - ten_error_t err; ten_error_init(&err); @@ -50,6 +46,12 @@ PyObject *ten_py_ten_env_on_init_done(PyObject *self, PyObject *args) { if (py_ten_env->c_ten_env->attach_to == TEN_ENV_ATTACH_TO_ADDON) { rc = ten_env_on_init_done(py_ten_env->c_ten_env, &err); } else { + if (!py_ten_env->c_ten_env_proxy) { + return ten_py_raise_py_value_error_exception( + "ten_env.on_init_done() failed because the c_ten_env_proxy is " + "invalid."); + } + rc = ten_env_proxy_notify_async(py_ten_env->c_ten_env_proxy, ten_env_proxy_notify_on_init_done, NULL, &err); diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_start_done.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_start_done.c index 8d403c4cd2..9782e3ba6c 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_start_done.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_start_done.c @@ -6,6 +6,7 @@ // #include +#include "include_internal/ten_runtime/binding/python/common/error.h" #include "include_internal/ten_runtime/binding/python/ten_env/ten_env.h" #include "include_internal/ten_runtime/ten_env/ten_env.h" #include "ten_runtime/ten_env/internal/on_xxx_done.h" @@ -37,7 +38,9 @@ PyObject *ten_py_ten_env_on_start_done(PyObject *self, "Invalid argument."); if (!py_ten_env->c_ten_env_proxy) { - Py_RETURN_NONE; + return ten_py_raise_py_value_error_exception( + "ten_env.on_start_done() failed because the c_ten_env_proxy is " + "invalid."); } ten_error_t err; diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_stop_done.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_stop_done.c index f718e573ec..4ab48ad13f 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_stop_done.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_stop_done.c @@ -6,6 +6,7 @@ // #include +#include "include_internal/ten_runtime/binding/python/common/error.h" #include "include_internal/ten_runtime/binding/python/ten_env/ten_env.h" #include "include_internal/ten_runtime/ten_env/ten_env.h" #include "ten_runtime/msg/msg.h" @@ -37,7 +38,9 @@ PyObject *ten_py_ten_env_on_stop_done(PyObject *self, "Invalid argument."); if (!py_ten_env->c_ten_env_proxy) { - Py_RETURN_NONE; + return ten_py_raise_py_value_error_exception( + "ten_env.on_stop_done() failed because the c_ten_env_proxy is " + "invalid."); } ten_error_t err; diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_return_result.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_return_result.c index 0ba7d11a7c..3d8b57d3b4 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_return_result.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_return_result.c @@ -175,7 +175,9 @@ PyObject *ten_py_ten_env_return_result(PyObject *self, PyObject *args) { "Invalid argument."); if (!py_ten_env->c_ten_env_proxy) { - Py_RETURN_NONE; + return ten_py_raise_py_value_error_exception( + "ten_env.return_result() failed because the c_ten_env_proxy is " + "invalid."); } bool success = true; @@ -247,7 +249,9 @@ PyObject *ten_py_ten_env_return_result_directly(PyObject *self, "Invalid argument."); if (!py_ten_env->c_ten_env_proxy) { - Py_RETURN_NONE; + return ten_py_raise_py_value_error_exception( + "ten_env.return_result_directly() failed because the c_ten_env_proxy " + "is invalid."); } bool success = true; diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_audio_frame.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_audio_frame.c index acab850474..935fd99feb 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_audio_frame.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_audio_frame.c @@ -152,7 +152,9 @@ PyObject *ten_py_ten_env_send_audio_frame(PyObject *self, PyObject *args) { "Invalid argument."); if (!py_ten_env->c_ten_env_proxy) { - Py_RETURN_NONE; + return ten_py_raise_py_value_error_exception( + "ten_env.send_audio_frame() failed because the c_ten_env_proxy is " + "invalid."); } bool success = true; diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_cmd.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_cmd.c index 03fb2071cf..cde2254ad1 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_cmd.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_cmd.c @@ -182,7 +182,8 @@ PyObject *ten_py_ten_env_send_cmd(PyObject *self, PyObject *args) { } if (!py_ten_env->c_ten_env_proxy) { - Py_RETURN_NONE; + return ten_py_raise_py_value_error_exception( + "ten_env.send_cmd() failed because the c_ten_env_proxy is invalid."); } bool success = true; diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_data.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_data.c index d4c80a9d8e..311fab60db 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_data.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_data.c @@ -151,7 +151,8 @@ PyObject *ten_py_ten_env_send_data(PyObject *self, PyObject *args) { "Invalid argument."); if (!py_ten_env->c_ten_env_proxy) { - Py_RETURN_NONE; + return ten_py_raise_py_value_error_exception( + "ten_env.send_data() failed because the c_ten_env_proxy is invalid."); } bool success = true; diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_video_frame.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_video_frame.c index cd087461bd..07379dbc2f 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_video_frame.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_video_frame.c @@ -152,7 +152,9 @@ PyObject *ten_py_ten_env_send_video_frame(PyObject *self, PyObject *args) { "Invalid argument."); if (!py_ten_env->c_ten_env_proxy) { - Py_RETURN_NONE; + return ten_py_raise_py_value_error_exception( + "ten_env.send_video_frame() failed because the c_ten_env_proxy is " + "invalid."); } bool success = true; diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_set_property.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_set_property.c index 915bf5d30c..2ee2b45045 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_set_property.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_set_property.c @@ -113,7 +113,9 @@ PyObject *ten_py_ten_env_set_property_from_json(PyObject *self, } if (!py_ten_env->c_ten_env_proxy) { - Py_RETURN_NONE; + return ten_py_raise_py_value_error_exception( + "ten_env.set_property_from_json() failed because the c_ten_env_proxy is " + "invalid."); } ten_json_t *json = ten_json_from_string(json_str, NULL); diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_set_property_async.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_set_property_async.c index 90833b223d..37d8984e41 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_set_property_async.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_set_property_async.c @@ -152,7 +152,9 @@ PyObject *ten_py_ten_env_set_property_from_json_async(PyObject *self, } if (!py_ten_env->c_ten_env_proxy) { - Py_RETURN_NONE; + return ten_py_raise_py_value_error_exception( + "ten_env.set_property_from_json_async() failed because the c_ten_env_proxy is " + "invalid."); } ten_json_t *json = ten_json_from_string(json_str, NULL); @@ -209,7 +211,9 @@ PyObject *ten_py_ten_env_set_property_string_async(PyObject *self, } if (!py_ten_env->c_ten_env_proxy) { - Py_RETURN_NONE; + return ten_py_raise_py_value_error_exception( + "ten_env.set_property_string_async() failed because the c_ten_env_proxy is " + "invalid."); } ten_value_t *c_value = ten_value_create_string(value); @@ -257,7 +261,9 @@ PyObject *ten_py_ten_env_set_property_int_async(PyObject *self, } if (!py_ten_env->c_ten_env_proxy) { - Py_RETURN_NONE; + return ten_py_raise_py_value_error_exception( + "ten_env.set_property_int_async() failed because the c_ten_env_proxy is " + "invalid."); } ten_value_t *c_value = ten_value_create_int64(value); @@ -305,7 +311,9 @@ PyObject *ten_py_ten_env_set_property_bool_async(PyObject *self, } if (!py_ten_env->c_ten_env_proxy) { - Py_RETURN_NONE; + return ten_py_raise_py_value_error_exception( + "ten_env.set_property_bool_async() failed because the c_ten_env_proxy is " + "invalid."); } ten_value_t *c_value = ten_value_create_bool(value); @@ -353,7 +361,9 @@ PyObject *ten_py_ten_env_set_property_float_async(PyObject *self, } if (!py_ten_env->c_ten_env_proxy) { - Py_RETURN_NONE; + return ten_py_raise_py_value_error_exception( + "ten_env.set_property_float_async() failed because the c_ten_env_proxy is " + "invalid."); } ten_value_t *c_value = ten_value_create_float64(value); diff --git a/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester.c b/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester.c index acee6f95f6..2c3193f779 100644 --- a/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester.c +++ b/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester.c @@ -33,16 +33,7 @@ static void ten_py_ten_env_tester_c_part_destroyed( ten_py_ten_env_tester_check_integrity(ten_env_tester_bridge_), "Should not happen."); - // TODO(Wei): Access to `c_ten_env_tester_proxy` may result in threading - // issues. There is a possibility that it could be used simultaneously in a - // Python thread and released in a C pthread. A mechanism is needed to resolve - // this issue. ten_env_tester_bridge->c_ten_env_tester = NULL; - if (ten_env_tester_bridge->c_ten_env_tester_proxy) { - ten_env_tester_proxy_release(ten_env_tester_bridge->c_ten_env_tester_proxy, - NULL); - ten_env_tester_bridge->c_ten_env_tester_proxy = NULL; - } ten_py_ten_env_tester_invalidate(ten_env_tester_bridge); } @@ -150,6 +141,7 @@ PyTypeObject *ten_py_ten_env_tester_type(void) { static PyMethodDef ten_methods[] = { {"on_start_done", ten_py_ten_env_tester_on_start_done, METH_VARARGS, NULL}, + {"on_stop_done", ten_py_ten_env_tester_on_stop_done, METH_VARARGS, NULL}, {"stop_test", ten_py_ten_env_tester_stop_test, METH_VARARGS, NULL}, {"send_cmd", ten_py_ten_env_tester_send_cmd, METH_VARARGS, NULL}, {"send_data", ten_py_ten_env_tester_send_data, METH_VARARGS, NULL}, diff --git a/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_log.c b/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_log.c index 5c98d1192b..3c5fa83afd 100644 --- a/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_log.c +++ b/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_log.c @@ -99,7 +99,10 @@ PyObject *ten_py_ten_env_tester_log(PyObject *self, TEN_UNUSED PyObject *args) { } if (!py_ten_env_tester->c_ten_env_tester_proxy) { - Py_RETURN_NONE; + ten_py_raise_py_value_error_exception( + "ten_env_tester.log() failed because the " + "c_ten_env_tester_proxy is " + "invalid."); } ten_error_t err; diff --git a/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_on_start_done.c b/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_on_start_done.c index 993b3b0a3c..100fe28d6b 100644 --- a/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_on_start_done.c +++ b/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_on_start_done.c @@ -4,8 +4,8 @@ // Licensed under the Apache License, Version 2.0, with certain conditions. // Refer to the "LICENSE" file in the root directory for more information. // +#include "include_internal/ten_runtime/binding/python/common/error.h" #include "include_internal/ten_runtime/binding/python/test/env_tester.h" -#include "object.h" #include "ten_runtime/test/env_tester.h" #include "ten_runtime/test/env_tester_proxy.h" #include "ten_utils/lib/error.h" @@ -25,7 +25,10 @@ PyObject *ten_py_ten_env_tester_on_start_done(PyObject *self, "Invalid argument."); if (!py_ten_env_tester->c_ten_env_tester_proxy) { - Py_RETURN_NONE; + return ten_py_raise_py_value_error_exception( + "ten_env_tester.on_start_done() failed because the " + "c_ten_env_tester_proxy is " + "invalid."); } ten_error_t err; diff --git a/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_on_stop_done.c b/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_on_stop_done.c new file mode 100644 index 0000000000..5dd3917ef1 --- /dev/null +++ b/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_on_stop_done.c @@ -0,0 +1,72 @@ +// +// Copyright © 2025 Agora +// This file is part of TEN Framework, an open source project. +// Licensed under the Apache License, Version 2.0, with certain conditions. +// Refer to the "LICENSE" file in the root directory for more information. +// +#include "include_internal/ten_runtime/binding/python/common/common.h" +#include "include_internal/ten_runtime/binding/python/common/error.h" +#include "include_internal/ten_runtime/binding/python/test/env_tester.h" +#include "ten_runtime/test/env_tester.h" +#include "ten_runtime/test/env_tester_proxy.h" +#include "ten_utils/lib/error.h" +#include "ten_utils/macro/check.h" +#include "ten_utils/macro/mark.h" + +static void ten_py_ten_env_tester_on_stop_done_proxy_notify( + ten_env_tester_t *ten_env_tester, void *user_data) { + TEN_ASSERT( + ten_env_tester && ten_env_tester_check_integrity(ten_env_tester, true), + "Invalid argument."); + + ten_py_ten_env_tester_t *py_ten_env_tester = user_data; + TEN_ASSERT(py_ten_env_tester, "Should not happen."); + + // Notify the Python side to do the cleanup. + // + // About to call the Python function, so it's necessary to ensure that the + // GIL has been acquired. + PyGILState_STATE prev_state = ten_py_gil_state_ensure_internal(); + + PyObject *py_res = PyObject_CallMethod( + py_ten_env_tester->actual_py_ten_env_tester, "_on_release", NULL); + Py_XDECREF(py_res); + + bool err_occurred = ten_py_check_and_clear_py_error(); + TEN_ASSERT(!err_occurred, "Should not happen."); + + // Release the ten_env_tester_proxy. + ten_env_tester_proxy_release(py_ten_env_tester->c_ten_env_tester_proxy, NULL); + py_ten_env_tester->c_ten_env_tester_proxy = NULL; + + ten_py_gil_state_release_internal(prev_state); + + ten_env_tester_on_stop_done(ten_env_tester, NULL); +} + +PyObject *ten_py_ten_env_tester_on_stop_done(PyObject *self, + TEN_UNUSED PyObject *args) { + ten_py_ten_env_tester_t *py_ten_env_tester = (ten_py_ten_env_tester_t *)self; + TEN_ASSERT(py_ten_env_tester && + ten_py_ten_env_tester_check_integrity(py_ten_env_tester), + "Invalid argument."); + + if (!py_ten_env_tester->c_ten_env_tester_proxy) { + return ten_py_raise_py_value_error_exception( + "ten_env_tester.on_stop_done() failed because the " + "c_ten_env_tester_proxy is " + "invalid."); + } + + ten_error_t err; + ten_error_init(&err); + + bool rc = ten_env_tester_proxy_notify( + py_ten_env_tester->c_ten_env_tester_proxy, + ten_py_ten_env_tester_on_stop_done_proxy_notify, py_ten_env_tester, &err); + TEN_ASSERT(rc, "Should not happen."); + + ten_error_deinit(&err); + + Py_RETURN_NONE; +} diff --git a/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_stop_test.c b/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_stop_test.c index f500b85a6d..33a5ad8783 100644 --- a/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_stop_test.c +++ b/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_stop_test.c @@ -4,6 +4,7 @@ // Licensed under the Apache License, Version 2.0, with certain conditions. // Refer to the "LICENSE" file in the root directory for more information. // +#include "include_internal/ten_runtime/binding/python/common/error.h" #include "include_internal/ten_runtime/binding/python/test/env_tester.h" #include "ten_runtime/test/env_tester.h" #include "ten_runtime/test/env_tester_proxy.h" @@ -23,7 +24,10 @@ PyObject *ten_py_ten_env_tester_stop_test(PyObject *self, "Invalid argument."); if (!py_ten_env_tester->c_ten_env_tester_proxy) { - Py_RETURN_NONE; + ten_py_raise_py_value_error_exception( + "ten_env_tester.stop_test() failed because the " + "c_ten_env_tester_proxy is " + "invalid."); } ten_error_t err; diff --git a/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_return_result.c b/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_return_result.c index 0ded349668..df54ac05b6 100644 --- a/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_return_result.c +++ b/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_return_result.c @@ -126,7 +126,10 @@ PyObject *ten_py_ten_env_tester_return_result(PyObject *self, PyObject *args) { } if (!py_ten_env_tester->c_ten_env_tester_proxy) { - Py_RETURN_NONE; + return ten_py_raise_py_value_error_exception( + "ten_env_tester.return_result() failed because the " + "c_ten_env_tester_proxy is " + "invalid."); } bool success = true; diff --git a/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_audio_frame.c b/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_audio_frame.c index 917400e59b..bb89804407 100644 --- a/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_audio_frame.c +++ b/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_audio_frame.c @@ -120,7 +120,10 @@ PyObject *ten_py_ten_env_tester_send_audio_frame(PyObject *self, } if (!py_ten_env_tester->c_ten_env_tester_proxy) { - Py_RETURN_NONE; + return ten_py_raise_py_value_error_exception( + "ten_env_tester.send_audio_frame() failed because the " + "c_ten_env_tester_proxy is " + "invalid."); } bool success = true; diff --git a/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_cmd.c b/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_cmd.c index 8501a1c898..a339407de6 100644 --- a/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_cmd.c +++ b/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_cmd.c @@ -137,7 +137,10 @@ PyObject *ten_py_ten_env_tester_send_cmd(PyObject *self, PyObject *args) { } if (!py_ten_env_tester->c_ten_env_tester_proxy) { - Py_RETURN_NONE; + return ten_py_raise_py_value_error_exception( + "ten_env_tester.send_cmd() failed because the " + "c_ten_env_tester_proxy is " + "invalid."); } bool success = true; diff --git a/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_data.c b/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_data.c index 2bdcd99aaf..ec7b425993 100644 --- a/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_data.c +++ b/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_data.c @@ -116,7 +116,10 @@ PyObject *ten_py_ten_env_tester_send_data(PyObject *self, PyObject *args) { } if (!py_ten_env_tester->c_ten_env_tester_proxy) { - Py_RETURN_NONE; + return ten_py_raise_py_value_error_exception( + "ten_env_tester.send_data() failed because the " + "c_ten_env_tester_proxy is " + "invalid."); } bool success = true; diff --git a/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_video_frame.c b/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_video_frame.c index 3f7f1ec95a..75710492b6 100644 --- a/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_video_frame.c +++ b/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_video_frame.c @@ -120,7 +120,10 @@ PyObject *ten_py_ten_env_tester_send_video_frame(PyObject *self, } if (!py_ten_env_tester->c_ten_env_tester_proxy) { - Py_RETURN_NONE; + return ten_py_raise_py_value_error_exception( + "ten_env_tester.send_video_frame() failed because the " + "c_ten_env_tester_proxy is " + "invalid."); } bool success = true; diff --git a/core/src/ten_runtime/binding/python/native/test/extension_tester.c b/core/src/ten_runtime/binding/python/native/test/extension_tester.c index 5f78601fd3..d31c0c6b3b 100644 --- a/core/src/ten_runtime/binding/python/native/test/extension_tester.c +++ b/core/src/ten_runtime/binding/python/native/test/extension_tester.c @@ -125,12 +125,6 @@ static void proxy_on_stop(ten_extension_tester_t *extension_tester, TEN_ASSERT(!err_occurred, "Should not happen."); ten_py_gil_state_release_internal(prev_state); - - // Release the ten_env_tester_proxy. - ten_env_tester_proxy_release(py_ten_env_tester->c_ten_env_tester_proxy, NULL); - py_ten_env_tester->c_ten_env_tester_proxy = NULL; - - ten_env_tester_on_stop_done(ten_env_tester, NULL); } static void proxy_on_cmd(ten_extension_tester_t *extension_tester, diff --git a/core/src/ten_runtime/extension/ten_env/on_xxx.c b/core/src/ten_runtime/extension/ten_env/on_xxx.c index e4487f1c17..97c3ec8be6 100644 --- a/core/src/ten_runtime/extension/ten_env/on_xxx.c +++ b/core/src/ten_runtime/extension/ten_env/on_xxx.c @@ -22,6 +22,7 @@ #include "include_internal/ten_runtime/msg/msg.h" #include "include_internal/ten_runtime/ten_env/ten_env.h" #include "include_internal/ten_runtime/timer/timer.h" +#include "ten_utils/log/log.h" #include "ten_utils/macro/check.h" static bool ten_extension_parse_interface_schema(ten_extension_t *self, @@ -84,17 +85,6 @@ bool ten_extension_on_configure_done(ten_env_t *self) { TEN_ASSERT(ten_extension_check_integrity(extension, true), "Invalid use of extension %p.", extension); - TEN_LOGD("[%s] on_configure() done.", - ten_extension_get_name(extension, true)); - - if (extension->state != TEN_EXTENSION_STATE_ON_CONFIGURE) { - TEN_LOGI("[%s] Failed to on_configure_done() because of incorrect timing.", - ten_extension_get_name(extension, true)); - return false; - } - - extension->state = TEN_EXTENSION_STATE_ON_CONFIGURE_DONE; - ten_extension_thread_t *extension_thread = extension->extension_thread; TEN_ASSERT(extension_thread && ten_extension_thread_check_integrity(extension_thread, true), @@ -103,9 +93,22 @@ bool ten_extension_on_configure_done(ten_env_t *self) { if (extension_thread->is_close_triggered) { // Do not proceed with the subsequent init/start flow, as the extension // thread is about to shut down. + TEN_LOGD("[%s] on_configure() is skipped because of close triggered.", + ten_extension_get_name(extension, true)); return true; } + if (extension->state != TEN_EXTENSION_STATE_ON_CONFIGURE) { + TEN_LOGI("[%s] Failed to on_configure_done() because of incorrect timing.", + ten_extension_get_name(extension, true)); + return false; + } + + TEN_LOGD("[%s] on_configure() done.", + ten_extension_get_name(extension, true)); + + extension->state = TEN_EXTENSION_STATE_ON_CONFIGURE_DONE; + ten_error_t err; ten_error_init(&err); @@ -183,7 +186,16 @@ bool ten_extension_on_init_done(ten_env_t *self) { TEN_ASSERT(ten_extension_check_integrity(extension, true), "Invalid use of extension %p.", extension); - TEN_LOGD("[%s] on_init() done.", ten_extension_get_name(extension, true)); + ten_extension_thread_t *extension_thread = extension->extension_thread; + TEN_ASSERT(extension_thread && + ten_extension_thread_check_integrity(extension_thread, true), + "Should not happen."); + + if (extension_thread->is_close_triggered) { + TEN_LOGD("[%s] on_init_done() is skipped because of close triggered.", + ten_extension_get_name(extension, true)); + return true; + } if (extension->state != TEN_EXTENSION_STATE_ON_INIT) { // `on_init_done` can only be called at specific times. @@ -192,16 +204,9 @@ bool ten_extension_on_init_done(ten_env_t *self) { return false; } - extension->state = TEN_EXTENSION_STATE_ON_INIT_DONE; - - ten_extension_thread_t *extension_thread = extension->extension_thread; - TEN_ASSERT(extension_thread && - ten_extension_thread_check_integrity(extension_thread, true), - "Should not happen."); + TEN_LOGD("[%s] on_init() done.", ten_extension_get_name(extension, true)); - if (extension_thread->is_close_triggered) { - return true; - } + extension->state = TEN_EXTENSION_STATE_ON_INIT_DONE; // Trigger on_start of extension. ten_extension_on_start(extension); @@ -251,7 +256,16 @@ bool ten_extension_on_start_done(ten_env_t *self) { TEN_ASSERT(ten_extension_check_integrity(extension, true), "Invalid use of extension %p.", extension); - TEN_LOGI("[%s] on_start() done.", ten_extension_get_name(extension, true)); + ten_extension_thread_t *extension_thread = extension->extension_thread; + TEN_ASSERT(extension_thread && + ten_extension_thread_check_integrity(extension_thread, true), + "Should not happen."); + + if (extension_thread->is_close_triggered) { + TEN_LOGD("[%s] on_start_done() is skipped because of close triggered.", + ten_extension_get_name(extension, true)); + return true; + } if (extension->state != TEN_EXTENSION_STATE_ON_START) { TEN_LOGI("[%s] Failed to on_start_done() because of incorrect timing.", @@ -259,6 +273,8 @@ bool ten_extension_on_start_done(ten_env_t *self) { return false; } + TEN_LOGI("[%s] on_start() done.", ten_extension_get_name(extension, true)); + extension->state = TEN_EXTENSION_STATE_ON_START_DONE; ten_extension_flush_all_pending_msgs(extension); From d69369f3676efb5bf60f3cf273b51885d1de510d Mon Sep 17 00:00:00 2001 From: sunxilin Date: Tue, 14 Jan 2025 16:52:47 +0800 Subject: [PATCH 04/11] feat: support on_stop in Python tester --- .../binding/python/interface/ten/async_test.py | 11 +++++++++++ .../tests/test_async_basic_1.py | 3 +++ .../default_extension_python/tests/test_basic.py | 4 ++++ 3 files changed, 18 insertions(+) diff --git a/core/src/ten_runtime/binding/python/interface/ten/async_test.py b/core/src/ten_runtime/binding/python/interface/ten/async_test.py index 39e112d874..f483db7e83 100644 --- a/core/src/ten_runtime/binding/python/interface/ten/async_test.py +++ b/core/src/ten_runtime/binding/python/interface/ten/async_test.py @@ -160,6 +160,8 @@ async def _thread_routine(self, ten_env_tester: TenEnvTester) -> None: # Suspend the thread until stopEvent is set. await self._ten_stop_event.wait() + await self._wrapper_on_stop(self._async_ten_env_tester) + self._async_ten_env_tester._deinit() async def _stop_thread(self): @@ -180,6 +182,12 @@ async def _wrapper_on_start( except Exception as e: self._exit_on_exception(ten_env_tester, e) + async def _wrapper_on_stop(self, ten_env_tester: AsyncTenEnvTester) -> None: + try: + await self.on_stop(ten_env_tester) + except Exception as e: + self._exit_on_exception(ten_env_tester, e) + @final def _proxy_on_stop(self, ten_env_tester: TenEnvTester) -> None: asyncio.run_coroutine_threadsafe(self._stop_thread(), self._ten_loop) @@ -267,6 +275,9 @@ def run(self) -> None: async def on_start(self, ten_env_tester: AsyncTenEnvTester) -> None: pass + async def on_stop(self, ten_env_tester: AsyncTenEnvTester) -> None: + pass + async def on_cmd(self, ten_env_tester: AsyncTenEnvTester, cmd: Cmd) -> None: pass diff --git a/tests/ten_runtime/integration/python/standalone_test_python/default_extension_python/tests/test_async_basic_1.py b/tests/ten_runtime/integration/python/standalone_test_python/default_extension_python/tests/test_async_basic_1.py index a443009cfa..529fd885b8 100644 --- a/tests/ten_runtime/integration/python/standalone_test_python/default_extension_python/tests/test_async_basic_1.py +++ b/tests/ten_runtime/integration/python/standalone_test_python/default_extension_python/tests/test_async_basic_1.py @@ -40,6 +40,9 @@ async def on_start(self, ten_env: AsyncTenEnvTester) -> None: if statusCode == StatusCode.OK: ten_env.stop_test() + async def on_stop(self, ten_env: AsyncTenEnvTester) -> None: + ten_env.log_info("tester on_stop") + def test_basic(): tester = AsyncExtensionTesterBasic() diff --git a/tests/ten_runtime/integration/python/standalone_test_python/default_extension_python/tests/test_basic.py b/tests/ten_runtime/integration/python/standalone_test_python/default_extension_python/tests/test_basic.py index 867c7205cf..c39966a5f3 100644 --- a/tests/ten_runtime/integration/python/standalone_test_python/default_extension_python/tests/test_basic.py +++ b/tests/ten_runtime/integration/python/standalone_test_python/default_extension_python/tests/test_basic.py @@ -54,6 +54,10 @@ def on_start(self, ten_env: TenEnvTester) -> None: ten_env.log_info("tester on_start_done") ten_env.on_start_done() + def on_stop(self, ten_env: TenEnvTester) -> None: + ten_env.log_info("tester on_stop") + ten_env.on_stop_done() + def test_basic(): tester = ExtensionTesterBasic() From 1c3d416feb3705ce2111a6b47916bbeeb968b074 Mon Sep 17 00:00:00 2001 From: Hu Yueh-Wei Date: Tue, 14 Jan 2025 18:30:14 +0800 Subject: [PATCH 05/11] fix: refine codes --- core/src/ten_runtime/binding/python/manifest.json | 2 +- .../binding/python/native/test/env_tester/env_tester_log.c | 6 ++---- .../native/test/env_tester/env_tester_on_start_done.c | 3 +-- .../native/test/env_tester/env_tester_on_stop_done.c | 3 +-- .../core_addon_loaders/python_addon_loader/manifest.json | 2 +- tools/version/update_version_in_ten_framework.py | 7 +++++++ 6 files changed, 13 insertions(+), 10 deletions(-) diff --git a/core/src/ten_runtime/binding/python/manifest.json b/core/src/ten_runtime/binding/python/manifest.json index e47e1e64be..27937eb7a2 100644 --- a/core/src/ten_runtime/binding/python/manifest.json +++ b/core/src/ten_runtime/binding/python/manifest.json @@ -11,7 +11,7 @@ { "type": "addon_loader", "name": "python_addon_loader", - "version": "0.6.0" + "version": "0.7.1" } ], "package": { diff --git a/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_log.c b/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_log.c index 3c5fa83afd..8977e2b285 100644 --- a/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_log.c +++ b/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_log.c @@ -99,10 +99,8 @@ PyObject *ten_py_ten_env_tester_log(PyObject *self, TEN_UNUSED PyObject *args) { } if (!py_ten_env_tester->c_ten_env_tester_proxy) { - ten_py_raise_py_value_error_exception( - "ten_env_tester.log() failed because the " - "c_ten_env_tester_proxy is " - "invalid."); + return ten_py_raise_py_value_error_exception( + "ten_env_tester.log() failed because ten_env_tester_proxy is invalid."); } ten_error_t err; diff --git a/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_on_start_done.c b/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_on_start_done.c index 100fe28d6b..3a555ee845 100644 --- a/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_on_start_done.c +++ b/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_on_start_done.c @@ -26,8 +26,7 @@ PyObject *ten_py_ten_env_tester_on_start_done(PyObject *self, if (!py_ten_env_tester->c_ten_env_tester_proxy) { return ten_py_raise_py_value_error_exception( - "ten_env_tester.on_start_done() failed because the " - "c_ten_env_tester_proxy is " + "ten_env_tester.on_start_done() failed because ten_env_tester_proxy is " "invalid."); } diff --git a/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_on_stop_done.c b/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_on_stop_done.c index 5dd3917ef1..ad76593870 100644 --- a/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_on_stop_done.c +++ b/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_on_stop_done.c @@ -53,8 +53,7 @@ PyObject *ten_py_ten_env_tester_on_stop_done(PyObject *self, if (!py_ten_env_tester->c_ten_env_tester_proxy) { return ten_py_raise_py_value_error_exception( - "ten_env_tester.on_stop_done() failed because the " - "c_ten_env_tester_proxy is " + "ten_env_tester.on_stop_done() failed because ten_env_tester_proxy is " "invalid."); } diff --git a/packages/core_addon_loaders/python_addon_loader/manifest.json b/packages/core_addon_loaders/python_addon_loader/manifest.json index d21d9855f4..a356dcd499 100644 --- a/packages/core_addon_loaders/python_addon_loader/manifest.json +++ b/packages/core_addon_loaders/python_addon_loader/manifest.json @@ -1,7 +1,7 @@ { "type": "addon_loader", "name": "python_addon_loader", - "version": "0.6.0", + "version": "0.7.1", "dependencies": [ { "type": "system", diff --git a/tools/version/update_version_in_ten_framework.py b/tools/version/update_version_in_ten_framework.py index 4fbb6c3895..4cb2800fde 100644 --- a/tools/version/update_version_in_ten_framework.py +++ b/tools/version/update_version_in_ten_framework.py @@ -208,17 +208,24 @@ def collect_and_update_version_of_core_packages( "packages", "core_protocols", ) + core_addon_loaders_dir_path = os.path.join( + repo_base_dir, + "packages", + "core_addon_loaders", + ) manifest_files = ( __collect_manifest_files(core_apps_dir_path) + __collect_manifest_files(core_extensions_dir_path) + __collect_manifest_files(core_protocols_dir_path) + + __collect_manifest_files(core_addon_loaders_dir_path) ) manifest_template_files = ( __collect_manifest_tent_files(core_apps_dir_path) + __collect_manifest_tent_files(core_extensions_dir_path) + __collect_manifest_tent_files(core_protocols_dir_path) + + __collect_manifest_tent_files(core_addon_loaders_dir_path) ) pkg_infos = [] From ce881388021a9af781edcf9d061a3350e79a755b Mon Sep 17 00:00:00 2001 From: Hu Yueh-Wei Date: Tue, 14 Jan 2025 18:48:06 +0800 Subject: [PATCH 06/11] fix: refine codes --- .../test/env_tester/env_tester_stop_test.c | 3 +- .../test/env_tester/ten_env_return_result.c | 30 +++++++------------ .../env_tester/ten_env_send_audio_frame.c | 30 +++++++------------ .../native/test/env_tester/ten_env_send_cmd.c | 30 +++++++------------ .../test/env_tester/ten_env_send_data.c | 30 +++++++------------ .../env_tester/ten_env_send_video_frame.c | 30 +++++++------------ .../python/native/test/extension_tester.c | 9 ++++++ 7 files changed, 65 insertions(+), 97 deletions(-) diff --git a/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_stop_test.c b/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_stop_test.c index 33a5ad8783..b8a765a918 100644 --- a/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_stop_test.c +++ b/core/src/ten_runtime/binding/python/native/test/env_tester/env_tester_stop_test.c @@ -25,8 +25,7 @@ PyObject *ten_py_ten_env_tester_stop_test(PyObject *self, if (!py_ten_env_tester->c_ten_env_tester_proxy) { ten_py_raise_py_value_error_exception( - "ten_env_tester.stop_test() failed because the " - "c_ten_env_tester_proxy is " + "ten_env_tester.stop_test() failed because ten_env_tester_proxy is " "invalid."); } diff --git a/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_return_result.c b/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_return_result.c index df54ac05b6..59623ed6d7 100644 --- a/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_return_result.c +++ b/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_return_result.c @@ -125,29 +125,20 @@ PyObject *ten_py_ten_env_tester_return_result(PyObject *self, PyObject *args) { "Invalid argument count when ten_env_tester.return_result."); } - if (!py_ten_env_tester->c_ten_env_tester_proxy) { - return ten_py_raise_py_value_error_exception( - "ten_env_tester.return_result() failed because the " - "c_ten_env_tester_proxy is " - "invalid."); - } - - bool success = true; - - ten_error_t err; - ten_error_init(&err); - ten_py_cmd_result_t *py_cmd_result = NULL; ten_py_cmd_t *py_target_cmd = NULL; PyObject *cb_func = NULL; - if (!PyArg_ParseTuple(args, "O!O!O", ten_py_cmd_result_py_type(), &py_cmd_result, ten_py_cmd_py_type(), &py_target_cmd, &cb_func)) { - success = false; - ten_py_raise_py_type_error_exception( + return ten_py_raise_py_type_error_exception( "Invalid argument type when return result."); - goto done; + } + + if (!py_ten_env_tester->c_ten_env_tester_proxy) { + return ten_py_raise_py_value_error_exception( + "ten_env_tester.return_result() failed because ten_env_tester_proxy is " + "invalid."); } // Check if cb_func is callable. @@ -155,11 +146,14 @@ PyObject *ten_py_ten_env_tester_return_result(PyObject *self, PyObject *args) { cb_func = NULL; } + ten_error_t err; + ten_error_init(&err); + ten_py_ten_env_tester_notify_return_result_ctx_t *ctx = ten_py_ten_env_tester_notify_return_result_ctx_create( py_cmd_result->msg.c_msg, py_target_cmd->msg.c_msg, cb_func); - success = ten_env_tester_proxy_notify( + bool success = ten_env_tester_proxy_notify( py_ten_env_tester->c_ten_env_tester_proxy, ten_py_ten_env_tester_notify_return_result_proxy_notify, ctx, &err); @@ -167,7 +161,6 @@ PyObject *ten_py_ten_env_tester_return_result(PyObject *self, PyObject *args) { ten_py_ten_env_tester_notify_return_result_ctx_destroy(ctx); ten_py_raise_py_runtime_error_exception("Failed to return result."); - goto done; } else { if (ten_cmd_result_is_final(py_cmd_result->msg.c_msg, &err)) { // Remove the C message from the python target message if it is the final @@ -178,7 +171,6 @@ PyObject *ten_py_ten_env_tester_return_result(PyObject *self, PyObject *args) { ten_py_msg_destroy_c_msg(&py_cmd_result->msg); } -done: ten_error_deinit(&err); if (success) { diff --git a/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_audio_frame.c b/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_audio_frame.c index bb89804407..45c8febae5 100644 --- a/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_audio_frame.c +++ b/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_audio_frame.c @@ -119,27 +119,18 @@ PyObject *ten_py_ten_env_tester_send_audio_frame(PyObject *self, "Invalid argument count when ten_env_tester.send_audio_frame."); } - if (!py_ten_env_tester->c_ten_env_tester_proxy) { - return ten_py_raise_py_value_error_exception( - "ten_env_tester.send_audio_frame() failed because the " - "c_ten_env_tester_proxy is " - "invalid."); - } - - bool success = true; - - ten_error_t err; - ten_error_init(&err); - ten_py_audio_frame_t *py_audio_frame = NULL; PyObject *cb_func = NULL; - if (!PyArg_ParseTuple(args, "O!O", ten_py_audio_frame_py_type(), &py_audio_frame, &cb_func)) { - success = false; - ten_py_raise_py_type_error_exception( + return ten_py_raise_py_type_error_exception( "Invalid argument type when send audio_frame."); - goto done; + } + + if (!py_ten_env_tester->c_ten_env_tester_proxy) { + return ten_py_raise_py_value_error_exception( + "ten_env_tester.send_audio_frame() failed because env_tester_proxy is " + "invalid."); } // Check if cb_func is callable. @@ -147,11 +138,14 @@ PyObject *ten_py_ten_env_tester_send_audio_frame(PyObject *self, cb_func = NULL; } + ten_error_t err; + ten_error_init(&err); + ten_py_ten_env_tester_send_audio_frame_ctx_t *ctx = ten_py_ten_env_tester_send_audio_frame_ctx_create( py_audio_frame->msg.c_msg, cb_func); - success = ten_env_tester_proxy_notify( + bool success = ten_env_tester_proxy_notify( py_ten_env_tester->c_ten_env_tester_proxy, ten_py_ten_env_tester_send_audio_frame_proxy_notify, ctx, &err); @@ -159,14 +153,12 @@ PyObject *ten_py_ten_env_tester_send_audio_frame(PyObject *self, ten_py_ten_env_tester_send_audio_frame_ctx_destroy(ctx); ten_py_raise_py_runtime_error_exception("Failed to send audio_frame."); - goto done; } else { // Destroy the C message from the Python message as the ownership has been // transferred to the notify_info. ten_py_msg_destroy_c_msg(&py_audio_frame->msg); } -done: ten_error_deinit(&err); if (success) { diff --git a/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_cmd.c b/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_cmd.c index a339407de6..057befef02 100644 --- a/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_cmd.c +++ b/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_cmd.c @@ -136,26 +136,17 @@ PyObject *ten_py_ten_env_tester_send_cmd(PyObject *self, PyObject *args) { "Invalid argument count when ten_env_tester.send_cmd."); } - if (!py_ten_env_tester->c_ten_env_tester_proxy) { - return ten_py_raise_py_value_error_exception( - "ten_env_tester.send_cmd() failed because the " - "c_ten_env_tester_proxy is " - "invalid."); - } - - bool success = true; - - ten_error_t err; - ten_error_init(&err); - ten_py_cmd_t *py_cmd = NULL; PyObject *cb_func = NULL; - if (!PyArg_ParseTuple(args, "O!O", ten_py_cmd_py_type(), &py_cmd, &cb_func)) { - success = false; - ten_py_raise_py_type_error_exception( + return ten_py_raise_py_type_error_exception( "Invalid argument type when send cmd."); - goto done; + } + + if (!py_ten_env_tester->c_ten_env_tester_proxy) { + return ten_py_raise_py_value_error_exception( + "ten_env_tester.send_cmd() failed because ten_env_tester_proxy is " + "invalid."); } // Check if cb_func is callable. @@ -163,10 +154,13 @@ PyObject *ten_py_ten_env_tester_send_cmd(PyObject *self, PyObject *args) { cb_func = NULL; } + ten_error_t err; + ten_error_init(&err); + ten_py_ten_env_tester_send_cmd_ctx_t *ctx = ten_py_ten_env_tester_send_cmd_ctx_create(py_cmd->msg.c_msg, cb_func); - success = ten_env_tester_proxy_notify( + bool success = ten_env_tester_proxy_notify( py_ten_env_tester->c_ten_env_tester_proxy, ten_py_ten_env_tester_send_cmd_proxy_notify, ctx, &err); @@ -174,14 +168,12 @@ PyObject *ten_py_ten_env_tester_send_cmd(PyObject *self, PyObject *args) { ten_py_ten_env_tester_send_cmd_ctx_destroy(ctx); ten_py_raise_py_runtime_error_exception("Failed to send cmd."); - goto done; } else { // Destroy the C message from the Python message as the ownership has been // transferred to the notify_info. ten_py_msg_destroy_c_msg(&py_cmd->msg); } -done: ten_error_deinit(&err); if (success) { diff --git a/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_data.c b/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_data.c index ec7b425993..6658a26c96 100644 --- a/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_data.c +++ b/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_data.c @@ -115,27 +115,18 @@ PyObject *ten_py_ten_env_tester_send_data(PyObject *self, PyObject *args) { "Invalid argument count when ten_env_tester.send_data."); } - if (!py_ten_env_tester->c_ten_env_tester_proxy) { - return ten_py_raise_py_value_error_exception( - "ten_env_tester.send_data() failed because the " - "c_ten_env_tester_proxy is " - "invalid."); - } - - bool success = true; - - ten_error_t err; - ten_error_init(&err); - ten_py_data_t *py_data = NULL; PyObject *cb_func = NULL; - if (!PyArg_ParseTuple(args, "O!O", ten_py_data_py_type(), &py_data, &cb_func)) { - success = false; - ten_py_raise_py_type_error_exception( + return ten_py_raise_py_type_error_exception( "Invalid argument type when send data."); - goto done; + } + + if (!py_ten_env_tester->c_ten_env_tester_proxy) { + return ten_py_raise_py_value_error_exception( + "ten_env_tester.send_data() failed because ten_env_tester_proxy is " + "invalid."); } // Check if cb_func is callable. @@ -143,10 +134,13 @@ PyObject *ten_py_ten_env_tester_send_data(PyObject *self, PyObject *args) { cb_func = NULL; } + ten_error_t err; + ten_error_init(&err); + ten_py_ten_env_tester_send_data_ctx_t *ctx = ten_py_ten_env_tester_send_data_ctx_create(py_data->msg.c_msg, cb_func); - success = ten_env_tester_proxy_notify( + bool success = ten_env_tester_proxy_notify( py_ten_env_tester->c_ten_env_tester_proxy, ten_py_ten_env_tester_send_data_proxy_notify, ctx, &err); @@ -154,14 +148,12 @@ PyObject *ten_py_ten_env_tester_send_data(PyObject *self, PyObject *args) { ten_py_ten_env_tester_send_data_ctx_destroy(ctx); ten_py_raise_py_runtime_error_exception("Failed to send data."); - goto done; } else { // Destroy the C message from the Python message as the ownership has been // transferred to the notify_info. ten_py_msg_destroy_c_msg(&py_data->msg); } -done: ten_error_deinit(&err); if (success) { diff --git a/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_video_frame.c b/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_video_frame.c index 75710492b6..0455042af1 100644 --- a/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_video_frame.c +++ b/core/src/ten_runtime/binding/python/native/test/env_tester/ten_env_send_video_frame.c @@ -119,27 +119,18 @@ PyObject *ten_py_ten_env_tester_send_video_frame(PyObject *self, "Invalid argument count when ten_env_tester.send_video_frame."); } - if (!py_ten_env_tester->c_ten_env_tester_proxy) { - return ten_py_raise_py_value_error_exception( - "ten_env_tester.send_video_frame() failed because the " - "c_ten_env_tester_proxy is " - "invalid."); - } - - bool success = true; - - ten_error_t err; - ten_error_init(&err); - ten_py_video_frame_t *py_video_frame = NULL; PyObject *cb_func = NULL; - if (!PyArg_ParseTuple(args, "O!O", ten_py_video_frame_py_type(), &py_video_frame, &cb_func)) { - success = false; - ten_py_raise_py_type_error_exception( + return ten_py_raise_py_type_error_exception( "Invalid argument type when send video_frame."); - goto done; + } + + if (!py_ten_env_tester->c_ten_env_tester_proxy) { + return ten_py_raise_py_value_error_exception( + "ten_env_tester.send_video_frame() failed because ten_env_tester_proxy " + "is invalid."); } // Check if cb_func is callable. @@ -147,11 +138,14 @@ PyObject *ten_py_ten_env_tester_send_video_frame(PyObject *self, cb_func = NULL; } + ten_error_t err; + ten_error_init(&err); + ten_py_ten_env_tester_send_video_frame_ctx_t *ctx = ten_py_ten_env_tester_send_video_frame_ctx_create( py_video_frame->msg.c_msg, cb_func); - success = ten_env_tester_proxy_notify( + bool success = ten_env_tester_proxy_notify( py_ten_env_tester->c_ten_env_tester_proxy, ten_py_ten_env_tester_send_video_frame_proxy_notify, ctx, &err); @@ -159,14 +153,12 @@ PyObject *ten_py_ten_env_tester_send_video_frame(PyObject *self, ten_py_ten_env_tester_send_video_frame_ctx_destroy(ctx); ten_py_raise_py_runtime_error_exception("Failed to send video_frame."); - goto done; } else { // Destroy the C message from the Python message as the ownership has been // transferred to the notify_info. ten_py_msg_destroy_c_msg(&py_video_frame->msg); } -done: ten_error_deinit(&err); if (success) { diff --git a/core/src/ten_runtime/binding/python/native/test/extension_tester.c b/core/src/ten_runtime/binding/python/native/test/extension_tester.c index d31c0c6b3b..140397f5c1 100644 --- a/core/src/ten_runtime/binding/python/native/test/extension_tester.c +++ b/core/src/ten_runtime/binding/python/native/test/extension_tester.c @@ -125,6 +125,15 @@ static void proxy_on_stop(ten_extension_tester_t *extension_tester, TEN_ASSERT(!err_occurred, "Should not happen."); ten_py_gil_state_release_internal(prev_state); + + // Do not release `py_ten_env_tester->c_ten_env_tester_proxy` here, because + // the upper layer may still need to call the API of `ten_env` (e.g., some + // asynchronous operations) before `on_stop_done`. Therefore, the proxy + // should only be released after `on_stop_done`. + // + // This practice of releasing `ten_env_proxy` at the very end (i.e., after the + // `on_deinit_done` of the extension and the `on_stop_done` of the app) is a + // common feature across all language bindings of TEN. } static void proxy_on_cmd(ten_extension_tester_t *extension_tester, From 08b712a408a9769f5f37f6d45816237fe84f1a3f Mon Sep 17 00:00:00 2001 From: Hu Yueh-Wei Date: Tue, 14 Jan 2025 18:51:46 +0800 Subject: [PATCH 07/11] fix: refine codes --- .../python/native/ten_env/ten_env_get_property.c | 15 ++++++--------- .../native/ten_env/ten_env_get_property_async.c | 4 ++-- .../python/native/ten_env/ten_env_init_property.c | 8 ++++---- .../binding/python/native/ten_env/ten_env_log.c | 3 ++- .../native/ten_env/ten_env_on_configure_done.c | 2 +- 5 files changed, 15 insertions(+), 17 deletions(-) diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_get_property.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_get_property.c index 532065652a..9f6cbe2c55 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_get_property.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_get_property.c @@ -120,7 +120,7 @@ PyObject *ten_py_ten_env_get_property_to_json(PyObject *self, PyObject *args) { if (!py_ten_env->c_ten_env_proxy) { return ten_py_raise_py_value_error_exception( - "ten_env.get_property_to_json() failed because the c_ten_env_proxy is " + "ten_env.get_property_to_json() failed because ten_env_proxy is " "invalid."); } @@ -171,8 +171,7 @@ PyObject *ten_py_ten_env_get_property_int(PyObject *self, PyObject *args) { if (!py_ten_env->c_ten_env_proxy) { return ten_py_raise_py_value_error_exception( - "ten_env.get_property_int() failed because the c_ten_env_proxy is " - "invalid."); + "ten_env.get_property_int() failed because ten_env_proxy is invalid."); } ten_value_t *value = @@ -216,7 +215,7 @@ PyObject *ten_py_ten_env_get_property_string(PyObject *self, PyObject *args) { if (!py_ten_env->c_ten_env_proxy) { return ten_py_raise_py_value_error_exception( - "ten_env.get_property_string() failed because the c_ten_env_proxy is " + "ten_env.get_property_string() failed because ten_env_proxy is " "invalid."); } @@ -260,8 +259,7 @@ PyObject *ten_py_ten_env_get_property_bool(PyObject *self, PyObject *args) { if (!py_ten_env->c_ten_env_proxy) { return ten_py_raise_py_value_error_exception( - "ten_env.get_property_bool() failed because the c_ten_env_proxy is " - "invalid."); + "ten_env.get_property_bool() failed because ten_env_proxy is invalid."); } ten_value_t *value = @@ -305,7 +303,7 @@ PyObject *ten_py_ten_env_get_property_float(PyObject *self, PyObject *args) { if (!py_ten_env->c_ten_env_proxy) { return ten_py_raise_py_value_error_exception( - "ten_env.get_property_float() failed because the c_ten_env_proxy is " + "ten_env.get_property_float() failed because ten_env_proxy is " "invalid."); } @@ -350,8 +348,7 @@ PyObject *ten_py_ten_env_is_property_exist(PyObject *self, PyObject *args) { if (!py_ten_env->c_ten_env_proxy) { return ten_py_raise_py_value_error_exception( - "ten_env.is_property_exist() failed because the c_ten_env_proxy is " - "invalid."); + "ten_env.is_property_exist() failed because ten_env_proxy is invalid."); } ten_value_t *value = diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_get_property_async.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_get_property_async.c index 914d12f623..e10d58c1fb 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_get_property_async.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_get_property_async.c @@ -428,8 +428,8 @@ static PyObject *ten_py_ten_env_get_property_async(PyObject *self, if (!py_ten_env->c_ten_env_proxy) { return ten_py_raise_py_value_error_exception( - "ten_env.get_property_to_json_async() failed because the c_ten_env_proxy " - "is invalid."); + "ten_env.get_property_to_json_async() failed because ten_env_proxy is " + "invalid."); } ten_error_t err; diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_init_property.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_init_property.c index e158cdff41..26ba141a8f 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_init_property.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_init_property.c @@ -165,8 +165,8 @@ PyObject *ten_py_ten_env_init_property_from_json(PyObject *self, if (!py_ten_env->c_ten_env_proxy) { return ten_py_raise_py_value_error_exception( - "ten_env.init_property_from_json() failed because the c_ten_env_proxy " - "is invalid."); + "ten_env.init_property_from_json() failed because ten_env_proxy is " + "invalid."); } ten_error_t err; @@ -221,8 +221,8 @@ PyObject *ten_py_ten_env_init_property_from_json_async(PyObject *self, if (!py_ten_env->c_ten_env_proxy) { return ten_py_raise_py_value_error_exception( - "ten_env.init_property_from_json_async() failed because the " - "c_ten_env_proxy is invalid."); + "ten_env.init_property_from_json_async() failed because ten_env_proxy " + "is invalid."); } ten_error_t err; diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_log.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_log.c index 13c8e47f86..83e803f642 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_log.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_log.c @@ -113,7 +113,7 @@ PyObject *ten_py_ten_env_log(PyObject *self, PyObject *args) { } else { if (!py_ten_env->c_ten_env_proxy) { return ten_py_raise_py_value_error_exception( - "ten_env.log() failed because the c_ten_env_proxy is invalid."); + "ten_env.log() failed because ten_env_proxy is invalid."); } ten_env_notify_log_ctx_t *ctx = ten_env_notify_log_ctx_create( @@ -126,5 +126,6 @@ PyObject *ten_py_ten_env_log(PyObject *self, PyObject *args) { } ten_error_deinit(&err); + Py_RETURN_NONE; } diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_configure_done.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_configure_done.c index 536e809ed2..0031e0e9f7 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_configure_done.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_configure_done.c @@ -48,7 +48,7 @@ PyObject *ten_py_ten_env_on_configure_done(PyObject *self, PyObject *args) { } else { if (!py_ten_env->c_ten_env_proxy) { return ten_py_raise_py_value_error_exception( - "ten_env.on_configure_done() failed because the c_ten_env_proxy is " + "ten_env.on_configure_done() failed because ten_env_proxy is " "invalid."); } From 3708b164b8c8bf9d2c60b7598c9d1f601ca9fe4c Mon Sep 17 00:00:00 2001 From: Hu Yueh-Wei Date: Tue, 14 Jan 2025 19:21:53 +0800 Subject: [PATCH 08/11] fix: refine codes --- .../native/ten_env/ten_env_on_deinit_done.c | 9 +++- .../native/ten_env/ten_env_on_init_done.c | 4 +- .../native/ten_env/ten_env_on_start_done.c | 3 +- .../native/ten_env/ten_env_on_stop_done.c | 3 +- .../native/ten_env/ten_env_return_result.c | 46 ++++++++----------- .../native/ten_env/ten_env_send_audio_frame.c | 21 ++++----- .../python/native/ten_env/ten_env_send_cmd.c | 23 ++++------ .../python/native/ten_env/ten_env_send_data.c | 21 ++++----- .../native/ten_env/ten_env_send_video_frame.c | 21 ++++----- .../native/ten_env/ten_env_set_property.c | 16 +++++-- .../ten_env/ten_env_set_property_async.c | 17 +++---- 11 files changed, 79 insertions(+), 105 deletions(-) diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_deinit_done.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_deinit_done.c index 2e4c2854be..9546f34733 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_deinit_done.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_deinit_done.c @@ -45,6 +45,9 @@ static void ten_env_proxy_notify_on_deinit_done(ten_env_t *ten_env, bool err_occurred = ten_py_check_and_clear_py_error(); TEN_ASSERT(!err_occurred, "Should not happen."); + // This is already the very end, so releasing `ten_env_proxy` here is + // appropriate. Additionally, since the Python GIL is held, it ensures that no + // other Python code is currently using `ten_env`. if (py_ten_env->c_ten_env_proxy) { TEN_ASSERT( ten_env_proxy_get_thread_cnt(py_ten_env->c_ten_env_proxy, NULL) == 1, @@ -96,9 +99,11 @@ PyObject *ten_py_ten_env_on_deinit_done(PyObject *self, rc = ten_env_on_deinit_done(py_ten_env->c_ten_env, &err); } else { if (!py_ten_env->c_ten_env_proxy) { + // Avoid memory leak. + ten_error_deinit(&err); + return ten_py_raise_py_value_error_exception( - "ten_env.on_deinit_done() failed because the c_ten_env_proxy is " - "invalid."); + "ten_env.on_deinit_done() failed because ten_env_proxy is invalid."); } rc = ten_env_proxy_notify(py_ten_env->c_ten_env_proxy, diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_init_done.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_init_done.c index c7fa33072a..dc65dd817a 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_init_done.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_init_done.c @@ -47,9 +47,9 @@ PyObject *ten_py_ten_env_on_init_done(PyObject *self, PyObject *args) { rc = ten_env_on_init_done(py_ten_env->c_ten_env, &err); } else { if (!py_ten_env->c_ten_env_proxy) { + ten_error_deinit(&err); return ten_py_raise_py_value_error_exception( - "ten_env.on_init_done() failed because the c_ten_env_proxy is " - "invalid."); + "ten_env.on_init_done() failed because ten_env_proxy is invalid."); } rc = ten_env_proxy_notify_async(py_ten_env->c_ten_env_proxy, diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_start_done.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_start_done.c index 9782e3ba6c..543ead7cc7 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_start_done.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_start_done.c @@ -39,8 +39,7 @@ PyObject *ten_py_ten_env_on_start_done(PyObject *self, if (!py_ten_env->c_ten_env_proxy) { return ten_py_raise_py_value_error_exception( - "ten_env.on_start_done() failed because the c_ten_env_proxy is " - "invalid."); + "ten_env.on_start_done() failed because ten_env_proxy is invalid."); } ten_error_t err; diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_stop_done.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_stop_done.c index 4ab48ad13f..f1c8cb0fc5 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_stop_done.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_on_stop_done.c @@ -39,8 +39,7 @@ PyObject *ten_py_ten_env_on_stop_done(PyObject *self, if (!py_ten_env->c_ten_env_proxy) { return ten_py_raise_py_value_error_exception( - "ten_env.on_stop_done() failed because the c_ten_env_proxy is " - "invalid."); + "ten_env.on_stop_done() failed because ten_env_proxy is invalid."); } ten_error_t err; diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_return_result.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_return_result.c index 3d8b57d3b4..a8ddbf2caf 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_return_result.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_return_result.c @@ -174,6 +174,16 @@ PyObject *ten_py_ten_env_return_result(PyObject *self, PyObject *args) { TEN_ASSERT(py_ten_env && ten_py_ten_env_check_integrity(py_ten_env), "Invalid argument."); + ten_py_cmd_t *py_target_cmd = NULL; + ten_py_cmd_result_t *py_cmd_result = NULL; + PyObject *cb_func = NULL; + if (!PyArg_ParseTuple(args, "O!O!O", ten_py_cmd_result_py_type(), + &py_cmd_result, ten_py_cmd_py_type(), &py_target_cmd, + &cb_func)) { + return ten_py_raise_py_type_error_exception( + "Invalid argument type when return result."); + } + if (!py_ten_env->c_ten_env_proxy) { return ten_py_raise_py_value_error_exception( "ten_env.return_result() failed because the c_ten_env_proxy is " @@ -185,19 +195,6 @@ PyObject *ten_py_ten_env_return_result(PyObject *self, PyObject *args) { ten_error_t err; ten_error_init(&err); - ten_py_cmd_t *py_target_cmd = NULL; - ten_py_cmd_result_t *py_cmd_result = NULL; - PyObject *cb_func = NULL; - - if (!PyArg_ParseTuple(args, "O!O!O", ten_py_cmd_result_py_type(), - &py_cmd_result, ten_py_cmd_py_type(), &py_target_cmd, - &cb_func)) { - success = false; - ten_py_raise_py_type_error_exception( - "Invalid argument type when return result."); - goto done; - } - // Check if cb_func is callable. if (!PyCallable_Check(cb_func)) { cb_func = NULL; @@ -219,7 +216,6 @@ PyObject *ten_py_ten_env_return_result(PyObject *self, PyObject *args) { ten_env_notify_return_result_ctx_destroy(notify_info); success = false; ten_py_raise_py_runtime_error_exception("Failed to return result."); - goto done; } else { if (ten_cmd_result_is_final(py_cmd_result->msg.c_msg, &err)) { // Remove the C message from the python target message if it is the final @@ -232,7 +228,6 @@ PyObject *ten_py_ten_env_return_result(PyObject *self, PyObject *args) { ten_py_msg_destroy_c_msg(&py_cmd_result->msg); } -done: ten_error_deinit(&err); if (success) { @@ -248,6 +243,14 @@ PyObject *ten_py_ten_env_return_result_directly(PyObject *self, TEN_ASSERT(py_ten_env && ten_py_ten_env_check_integrity(py_ten_env), "Invalid argument."); + ten_py_cmd_result_t *py_cmd_result = NULL; + PyObject *cb_func = NULL; + if (!PyArg_ParseTuple(args, "O!O", ten_py_cmd_result_py_type(), + &py_cmd_result, &cb_func)) { + return ten_py_raise_py_type_error_exception( + "Invalid argument type when return result directly."); + } + if (!py_ten_env->c_ten_env_proxy) { return ten_py_raise_py_value_error_exception( "ten_env.return_result_directly() failed because the c_ten_env_proxy " @@ -259,17 +262,6 @@ PyObject *ten_py_ten_env_return_result_directly(PyObject *self, ten_error_t err; ten_error_init(&err); - ten_py_cmd_result_t *py_cmd_result = NULL; - PyObject *cb_func = NULL; - - if (!PyArg_ParseTuple(args, "O!O", ten_py_cmd_result_py_type(), - &py_cmd_result, &cb_func)) { - success = false; - ten_py_raise_py_type_error_exception( - "Invalid argument type when return result directly."); - goto done; - } - // Check if cb_func is callable. if (!PyCallable_Check(cb_func)) { cb_func = NULL; @@ -288,14 +280,12 @@ PyObject *ten_py_ten_env_return_result_directly(PyObject *self, success = false; ten_py_raise_py_runtime_error_exception( "Failed to return result directly."); - goto done; } else { // Destroy the C message from the Python message as the ownership has been // transferred to the notify_info. ten_py_msg_destroy_c_msg(&py_cmd_result->msg); } -done: ten_error_deinit(&err); if (success) { diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_audio_frame.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_audio_frame.c index 935fd99feb..e46f0239a4 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_audio_frame.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_audio_frame.c @@ -151,6 +151,14 @@ PyObject *ten_py_ten_env_send_audio_frame(PyObject *self, PyObject *args) { TEN_ASSERT(py_ten_env && ten_py_ten_env_check_integrity(py_ten_env), "Invalid argument."); + ten_py_audio_frame_t *py_audio_frame = NULL; + PyObject *cb_func = NULL; + if (!PyArg_ParseTuple(args, "O!O", ten_py_audio_frame_py_type(), + &py_audio_frame, &cb_func)) { + return ten_py_raise_py_type_error_exception( + "Invalid argument type when send audio_frame."); + } + if (!py_ten_env->c_ten_env_proxy) { return ten_py_raise_py_value_error_exception( "ten_env.send_audio_frame() failed because the c_ten_env_proxy is " @@ -162,17 +170,6 @@ PyObject *ten_py_ten_env_send_audio_frame(PyObject *self, PyObject *args) { ten_error_t err; ten_error_init(&err); - ten_py_audio_frame_t *py_audio_frame = NULL; - PyObject *cb_func = NULL; - - if (!PyArg_ParseTuple(args, "O!O", ten_py_audio_frame_py_type(), - &py_audio_frame, &cb_func)) { - success = false; - ten_py_raise_py_type_error_exception( - "Invalid argument type when send audio_frame."); - goto done; - } - // Check if cb_func is callable. if (!PyCallable_Check(cb_func)) { cb_func = NULL; @@ -193,14 +190,12 @@ PyObject *ten_py_ten_env_send_audio_frame(PyObject *self, PyObject *args) { ten_env_notify_send_audio_frame_ctx_destroy(notify_info); success = false; ten_py_raise_py_runtime_error_exception("Failed to send audio_frame."); - goto done; } else { // Destroy the C message from the Python message as the ownership has been // transferred to the notify_info. ten_py_msg_destroy_c_msg(&py_audio_frame->msg); } -done: ten_error_deinit(&err); if (success) { diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_cmd.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_cmd.c index cde2254ad1..26f0c09690 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_cmd.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_cmd.c @@ -181,6 +181,15 @@ PyObject *ten_py_ten_env_send_cmd(PyObject *self, PyObject *args) { "Invalid argument count when ten_env.send_cmd."); } + ten_py_cmd_t *py_cmd = NULL; + PyObject *cb_func = NULL; + int is_ex = false; + if (!PyArg_ParseTuple(args, "O!Op", ten_py_cmd_py_type(), &py_cmd, &cb_func, + &is_ex)) { + return ten_py_raise_py_type_error_exception( + "Invalid argument type when send cmd."); + } + if (!py_ten_env->c_ten_env_proxy) { return ten_py_raise_py_value_error_exception( "ten_env.send_cmd() failed because the c_ten_env_proxy is invalid."); @@ -191,18 +200,6 @@ PyObject *ten_py_ten_env_send_cmd(PyObject *self, PyObject *args) { ten_error_t err; ten_error_init(&err); - ten_py_cmd_t *py_cmd = NULL; - PyObject *cb_func = NULL; - int is_ex = false; - - if (!PyArg_ParseTuple(args, "O!Op", ten_py_cmd_py_type(), &py_cmd, &cb_func, - &is_ex)) { - success = false; - ten_py_raise_py_type_error_exception( - "Invalid argument type when send cmd."); - goto done; - } - // Check if cb_func is callable. if (!PyCallable_Check(cb_func)) { cb_func = NULL; @@ -222,14 +219,12 @@ PyObject *ten_py_ten_env_send_cmd(PyObject *self, PyObject *args) { ten_env_notify_send_cmd_ctx_destroy(notify_info); success = false; ten_py_raise_py_runtime_error_exception("Failed to send cmd."); - goto done; } else { // Destroy the C message from the Python message as the ownership has been // transferred to the notify_info. ten_py_msg_destroy_c_msg(&py_cmd->msg); } -done: ten_error_deinit(&err); if (success) { diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_data.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_data.c index 311fab60db..5e232e4857 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_data.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_data.c @@ -150,6 +150,14 @@ PyObject *ten_py_ten_env_send_data(PyObject *self, PyObject *args) { TEN_ASSERT(py_ten_env && ten_py_ten_env_check_integrity(py_ten_env), "Invalid argument."); + ten_py_data_t *py_data = NULL; + PyObject *cb_func = NULL; + if (!PyArg_ParseTuple(args, "O!O", ten_py_data_py_type(), &py_data, + &cb_func)) { + return ten_py_raise_py_type_error_exception( + "Invalid argument type when send data."); + } + if (!py_ten_env->c_ten_env_proxy) { return ten_py_raise_py_value_error_exception( "ten_env.send_data() failed because the c_ten_env_proxy is invalid."); @@ -160,17 +168,6 @@ PyObject *ten_py_ten_env_send_data(PyObject *self, PyObject *args) { ten_error_t err; ten_error_init(&err); - ten_py_data_t *py_data = NULL; - PyObject *cb_func = NULL; - - if (!PyArg_ParseTuple(args, "O!O", ten_py_data_py_type(), &py_data, - &cb_func)) { - success = false; - ten_py_raise_py_type_error_exception( - "Invalid argument type when send data."); - goto done; - } - // Check if cb_func is callable. if (!PyCallable_Check(cb_func)) { cb_func = NULL; @@ -190,14 +187,12 @@ PyObject *ten_py_ten_env_send_data(PyObject *self, PyObject *args) { ten_env_notify_send_data_ctx_destroy(notify_info); success = false; ten_py_raise_py_runtime_error_exception("Failed to send data."); - goto done; } else { // Destroy the C message from the Python message as the ownership has been // transferred to the notify_info. ten_py_msg_destroy_c_msg(&py_data->msg); } -done: ten_error_deinit(&err); if (success) { diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_video_frame.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_video_frame.c index 07379dbc2f..db8e6b35bb 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_video_frame.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_send_video_frame.c @@ -151,6 +151,14 @@ PyObject *ten_py_ten_env_send_video_frame(PyObject *self, PyObject *args) { TEN_ASSERT(py_ten_env && ten_py_ten_env_check_integrity(py_ten_env), "Invalid argument."); + ten_py_video_frame_t *py_video_frame = NULL; + PyObject *cb_func = NULL; + if (!PyArg_ParseTuple(args, "O!O", ten_py_video_frame_py_type(), + &py_video_frame, &cb_func)) { + return ten_py_raise_py_type_error_exception( + "Invalid argument type when send video_frame."); + } + if (!py_ten_env->c_ten_env_proxy) { return ten_py_raise_py_value_error_exception( "ten_env.send_video_frame() failed because the c_ten_env_proxy is " @@ -162,17 +170,6 @@ PyObject *ten_py_ten_env_send_video_frame(PyObject *self, PyObject *args) { ten_error_t err; ten_error_init(&err); - ten_py_video_frame_t *py_video_frame = NULL; - PyObject *cb_func = NULL; - - if (!PyArg_ParseTuple(args, "O!O", ten_py_video_frame_py_type(), - &py_video_frame, &cb_func)) { - success = false; - ten_py_raise_py_type_error_exception( - "Invalid argument type when send video_frame."); - goto done; - } - // Check if cb_func is callable. if (!PyCallable_Check(cb_func)) { cb_func = NULL; @@ -193,14 +190,12 @@ PyObject *ten_py_ten_env_send_video_frame(PyObject *self, PyObject *args) { ten_env_notify_send_video_frame_ctx_destroy(notify_info); success = false; ten_py_raise_py_runtime_error_exception("Failed to send video_frame."); - goto done; } else { // Destroy the C message from the Python message as the ownership has been // transferred to the notify_info. ten_py_msg_destroy_c_msg(&py_video_frame->msg); } -done: ten_error_deinit(&err); if (success) { diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_set_property.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_set_property.c index 2ee2b45045..bc9da6be04 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_set_property.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_set_property.c @@ -114,7 +114,7 @@ PyObject *ten_py_ten_env_set_property_from_json(PyObject *self, if (!py_ten_env->c_ten_env_proxy) { return ten_py_raise_py_value_error_exception( - "ten_env.set_property_from_json() failed because the c_ten_env_proxy is " + "ten_env.set_property_from_json() failed because ten_env_proxy is " "invalid."); } @@ -155,7 +155,8 @@ PyObject *ten_py_ten_env_set_property_int(PyObject *self, PyObject *args) { } if (!py_ten_env->c_ten_env_proxy) { - Py_RETURN_NONE; + return ten_py_raise_py_value_error_exception( + "ten_env.set_property_int() failed because ten_env_proxy is invalid."); } ten_value_t *c_value = ten_value_create_int64(value); @@ -187,7 +188,9 @@ PyObject *ten_py_ten_env_set_property_string(PyObject *self, PyObject *args) { } if (!py_ten_env->c_ten_env_proxy) { - Py_RETURN_NONE; + return ten_py_raise_py_value_error_exception( + "ten_env.set_property_string() failed because ten_env_proxy is " + "invalid."); } ten_value_t *c_value = ten_value_create_string(value); @@ -219,7 +222,8 @@ PyObject *ten_py_ten_env_set_property_bool(PyObject *self, PyObject *args) { } if (!py_ten_env->c_ten_env_proxy) { - Py_RETURN_NONE; + return ten_py_raise_py_value_error_exception( + "ten_env.set_property_bool() failed because ten_env_proxy is invalid."); } ten_value_t *c_value = ten_value_create_bool(value > 0); @@ -251,7 +255,9 @@ PyObject *ten_py_ten_env_set_property_float(PyObject *self, PyObject *args) { } if (!py_ten_env->c_ten_env_proxy) { - Py_RETURN_NONE; + return ten_py_raise_py_value_error_exception( + "ten_env.set_property_float() failed because ten_env_proxy is " + "invalid."); } ten_value_t *c_value = ten_value_create_float64(value); diff --git a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_set_property_async.c b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_set_property_async.c index 37d8984e41..e4f1581f50 100644 --- a/core/src/ten_runtime/binding/python/native/ten_env/ten_env_set_property_async.c +++ b/core/src/ten_runtime/binding/python/native/ten_env/ten_env_set_property_async.c @@ -153,8 +153,8 @@ PyObject *ten_py_ten_env_set_property_from_json_async(PyObject *self, if (!py_ten_env->c_ten_env_proxy) { return ten_py_raise_py_value_error_exception( - "ten_env.set_property_from_json_async() failed because the c_ten_env_proxy is " - "invalid."); + "ten_env.set_property_from_json_async() failed because ten_env_proxy " + "is invalid."); } ten_json_t *json = ten_json_from_string(json_str, NULL); @@ -177,7 +177,6 @@ PyObject *ten_py_ten_env_set_property_from_json_async(PyObject *self, bool rc = ten_py_ten_env_set_property_async(py_ten_env, path, value, py_cb_func, &err); - if (!rc) { ten_value_destroy(value); } @@ -212,7 +211,7 @@ PyObject *ten_py_ten_env_set_property_string_async(PyObject *self, if (!py_ten_env->c_ten_env_proxy) { return ten_py_raise_py_value_error_exception( - "ten_env.set_property_string_async() failed because the c_ten_env_proxy is " + "ten_env.set_property_string_async() failed because ten_env_proxy is " "invalid."); } @@ -227,7 +226,6 @@ PyObject *ten_py_ten_env_set_property_string_async(PyObject *self, bool rc = ten_py_ten_env_set_property_async(py_ten_env, path, c_value, py_cb_func, &err); - if (!rc) { ten_value_destroy(c_value); } @@ -262,7 +260,7 @@ PyObject *ten_py_ten_env_set_property_int_async(PyObject *self, if (!py_ten_env->c_ten_env_proxy) { return ten_py_raise_py_value_error_exception( - "ten_env.set_property_int_async() failed because the c_ten_env_proxy is " + "ten_env.set_property_int_async() failed because ten_env_proxy is " "invalid."); } @@ -277,7 +275,6 @@ PyObject *ten_py_ten_env_set_property_int_async(PyObject *self, bool rc = ten_py_ten_env_set_property_async(py_ten_env, path, c_value, py_cb_func, &err); - if (!rc) { ten_value_destroy(c_value); } @@ -312,7 +309,7 @@ PyObject *ten_py_ten_env_set_property_bool_async(PyObject *self, if (!py_ten_env->c_ten_env_proxy) { return ten_py_raise_py_value_error_exception( - "ten_env.set_property_bool_async() failed because the c_ten_env_proxy is " + "ten_env.set_property_bool_async() failed because ten_env_proxy is " "invalid."); } @@ -327,7 +324,6 @@ PyObject *ten_py_ten_env_set_property_bool_async(PyObject *self, bool rc = ten_py_ten_env_set_property_async(py_ten_env, path, c_value, py_cb_func, &err); - if (!rc) { ten_value_destroy(c_value); } @@ -362,7 +358,7 @@ PyObject *ten_py_ten_env_set_property_float_async(PyObject *self, if (!py_ten_env->c_ten_env_proxy) { return ten_py_raise_py_value_error_exception( - "ten_env.set_property_float_async() failed because the c_ten_env_proxy is " + "ten_env.set_property_float_async() failed because ten_env_proxy is " "invalid."); } @@ -377,7 +373,6 @@ PyObject *ten_py_ten_env_set_property_float_async(PyObject *self, bool rc = ten_py_ten_env_set_property_async(py_ten_env, path, c_value, py_cb_func, &err); - if (!rc) { ten_value_destroy(c_value); } From d0eb15eee4e41fc5f08a6b4926b5e5b28a3654e2 Mon Sep 17 00:00:00 2001 From: Hu Yueh-Wei Date: Tue, 14 Jan 2025 19:42:29 +0800 Subject: [PATCH 09/11] fix: refine codes --- .../binding/python/interface/ten/async_test.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/core/src/ten_runtime/binding/python/interface/ten/async_test.py b/core/src/ten_runtime/binding/python/interface/ten/async_test.py index f483db7e83..e0fad4b256 100644 --- a/core/src/ten_runtime/binding/python/interface/ten/async_test.py +++ b/core/src/ten_runtime/binding/python/interface/ten/async_test.py @@ -43,6 +43,13 @@ def _deinit_routine(self) -> None: # Wait for the internal thread to finish. self._ten_thread.join() + # Since the `_ten_thread` used by the asyncio task queue has already + # ended, we can be confident that no Python code will be using `ten_env` + # at this point. (Of course, if the user has created their own Python + # threads that are holding onto `ten_env`, they will need to handle the + # thread-safety issues themselves.) Therefore, it is safe to call + # `on_stop_done`, during which `ten_env` (_proxy) will be released. + self._internal.on_stop_done() def _on_release(self) -> None: @@ -162,6 +169,12 @@ async def _thread_routine(self, ten_env_tester: TenEnvTester) -> None: await self._wrapper_on_stop(self._async_ten_env_tester) + # We cannot directly call `on_stop_done` here as above, because after + # `on_stop_done`, `ten_env_proxy` will be released. Therefore, we need + # to wait until certain essential tasks are completed before calling + # `on_stop_done`. Otherwise, if anything needs to use `ten_env` (_proxy) + # after `on_stop_done`, it will cause issues. + self._async_ten_env_tester._deinit() async def _stop_thread(self): From be095e0e4ac1c42d606603e47fc48bb1b8088a89 Mon Sep 17 00:00:00 2001 From: Hu Yueh-Wei Date: Tue, 14 Jan 2025 19:51:23 +0800 Subject: [PATCH 10/11] fix: refine codes --- .../ten_runtime/extension/ten_env/on_xxx.c | 76 ++++++++++--------- 1 file changed, 41 insertions(+), 35 deletions(-) diff --git a/core/src/ten_runtime/extension/ten_env/on_xxx.c b/core/src/ten_runtime/extension/ten_env/on_xxx.c index 97c3ec8be6..8a003e57d2 100644 --- a/core/src/ten_runtime/extension/ten_env/on_xxx.c +++ b/core/src/ten_runtime/extension/ten_env/on_xxx.c @@ -85,19 +85,6 @@ bool ten_extension_on_configure_done(ten_env_t *self) { TEN_ASSERT(ten_extension_check_integrity(extension, true), "Invalid use of extension %p.", extension); - ten_extension_thread_t *extension_thread = extension->extension_thread; - TEN_ASSERT(extension_thread && - ten_extension_thread_check_integrity(extension_thread, true), - "Should not happen."); - - if (extension_thread->is_close_triggered) { - // Do not proceed with the subsequent init/start flow, as the extension - // thread is about to shut down. - TEN_LOGD("[%s] on_configure() is skipped because of close triggered.", - ten_extension_get_name(extension, true)); - return true; - } - if (extension->state != TEN_EXTENSION_STATE_ON_CONFIGURE) { TEN_LOGI("[%s] Failed to on_configure_done() because of incorrect timing.", ten_extension_get_name(extension, true)); @@ -109,6 +96,21 @@ bool ten_extension_on_configure_done(ten_env_t *self) { extension->state = TEN_EXTENSION_STATE_ON_CONFIGURE_DONE; + ten_extension_thread_t *extension_thread = extension->extension_thread; + TEN_ASSERT(extension_thread && + ten_extension_thread_check_integrity(extension_thread, true), + "Should not happen."); + + if (extension_thread->is_close_triggered) { + // Do not proceed with the subsequent init/start flow, as the extension + // thread is about to shut down. + TEN_LOGD( + "[%s] Since the close process has already been triggered, no further " + "steps will be carried out after `on_configure_done`.", + ten_extension_get_name(extension, true)); + return true; + } + ten_error_t err; ten_error_init(&err); @@ -186,17 +188,6 @@ bool ten_extension_on_init_done(ten_env_t *self) { TEN_ASSERT(ten_extension_check_integrity(extension, true), "Invalid use of extension %p.", extension); - ten_extension_thread_t *extension_thread = extension->extension_thread; - TEN_ASSERT(extension_thread && - ten_extension_thread_check_integrity(extension_thread, true), - "Should not happen."); - - if (extension_thread->is_close_triggered) { - TEN_LOGD("[%s] on_init_done() is skipped because of close triggered.", - ten_extension_get_name(extension, true)); - return true; - } - if (extension->state != TEN_EXTENSION_STATE_ON_INIT) { // `on_init_done` can only be called at specific times. TEN_LOGI("[%s] Failed to on_init_done() because of incorrect timing.", @@ -208,6 +199,19 @@ bool ten_extension_on_init_done(ten_env_t *self) { extension->state = TEN_EXTENSION_STATE_ON_INIT_DONE; + ten_extension_thread_t *extension_thread = extension->extension_thread; + TEN_ASSERT(extension_thread && + ten_extension_thread_check_integrity(extension_thread, true), + "Should not happen."); + + if (extension_thread->is_close_triggered) { + TEN_LOGD( + "[%s] Since the close process has already been triggered, no further " + "steps will be carried out after `on_init_done`.", + ten_extension_get_name(extension, true)); + return true; + } + // Trigger on_start of extension. ten_extension_on_start(extension); @@ -256,17 +260,6 @@ bool ten_extension_on_start_done(ten_env_t *self) { TEN_ASSERT(ten_extension_check_integrity(extension, true), "Invalid use of extension %p.", extension); - ten_extension_thread_t *extension_thread = extension->extension_thread; - TEN_ASSERT(extension_thread && - ten_extension_thread_check_integrity(extension_thread, true), - "Should not happen."); - - if (extension_thread->is_close_triggered) { - TEN_LOGD("[%s] on_start_done() is skipped because of close triggered.", - ten_extension_get_name(extension, true)); - return true; - } - if (extension->state != TEN_EXTENSION_STATE_ON_START) { TEN_LOGI("[%s] Failed to on_start_done() because of incorrect timing.", ten_extension_get_name(extension, true)); @@ -277,6 +270,19 @@ bool ten_extension_on_start_done(ten_env_t *self) { extension->state = TEN_EXTENSION_STATE_ON_START_DONE; + ten_extension_thread_t *extension_thread = extension->extension_thread; + TEN_ASSERT(extension_thread && + ten_extension_thread_check_integrity(extension_thread, true), + "Should not happen."); + + if (extension_thread->is_close_triggered) { + TEN_LOGD( + "[%s] Since the close process has already been triggered, no further " + "steps will be carried out after `on_start_done`.", + ten_extension_get_name(extension, true)); + return true; + } + ten_extension_flush_all_pending_msgs(extension); return true; From 45f4a7d50928bdd0ce8532306b3a35d7571525c7 Mon Sep 17 00:00:00 2001 From: Hu Yueh-Wei Date: Tue, 14 Jan 2025 20:30:41 +0800 Subject: [PATCH 11/11] fix: refine codes --- .../ten_runtime/extension/ten_env/on_xxx.c | 21 ++++++++++--------- .../tests/test_async_basic_2.py | 3 ++- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/core/src/ten_runtime/extension/ten_env/on_xxx.c b/core/src/ten_runtime/extension/ten_env/on_xxx.c index 8a003e57d2..99426e5c02 100644 --- a/core/src/ten_runtime/extension/ten_env/on_xxx.c +++ b/core/src/ten_runtime/extension/ten_env/on_xxx.c @@ -86,8 +86,9 @@ bool ten_extension_on_configure_done(ten_env_t *self) { "Invalid use of extension %p.", extension); if (extension->state != TEN_EXTENSION_STATE_ON_CONFIGURE) { - TEN_LOGI("[%s] Failed to on_configure_done() because of incorrect timing.", - ten_extension_get_name(extension, true)); + TEN_LOGI( + "[%s] Failed to on_configure_done() because of incorrect timing: %d", + ten_extension_get_name(extension, true), extension->state); return false; } @@ -190,8 +191,8 @@ bool ten_extension_on_init_done(ten_env_t *self) { if (extension->state != TEN_EXTENSION_STATE_ON_INIT) { // `on_init_done` can only be called at specific times. - TEN_LOGI("[%s] Failed to on_init_done() because of incorrect timing.", - ten_extension_get_name(extension, true)); + TEN_LOGI("[%s] Failed to on_init_done() because of incorrect timing: %d", + ten_extension_get_name(extension, true), extension->state); return false; } @@ -261,8 +262,8 @@ bool ten_extension_on_start_done(ten_env_t *self) { "Invalid use of extension %p.", extension); if (extension->state != TEN_EXTENSION_STATE_ON_START) { - TEN_LOGI("[%s] Failed to on_start_done() because of incorrect timing.", - ten_extension_get_name(extension, true)); + TEN_LOGI("[%s] Failed to on_start_done() because of incorrect timing: %d", + ten_extension_get_name(extension, true), extension->state); return false; } @@ -301,8 +302,8 @@ bool ten_extension_on_stop_done(ten_env_t *self) { TEN_LOGI("[%s] on_stop() done.", ten_extension_get_name(extension, true)); if (extension->state != TEN_EXTENSION_STATE_ON_STOP) { - TEN_LOGI("[%s] Failed to on_stop_done() because of incorrect timing.", - ten_extension_get_name(extension, true)); + TEN_LOGI("[%s] Failed to on_stop_done() because of incorrect timing: %d", + ten_extension_get_name(extension, true), extension->state); return false; } @@ -369,8 +370,8 @@ bool ten_extension_on_deinit_done(ten_env_t *self) { "Invalid use of extension %p.", extension); if (extension->state != TEN_EXTENSION_STATE_ON_DEINIT) { - TEN_LOGI("[%s] Failed to on_deinit_done() because of incorrect timing.", - ten_extension_get_name(extension, true)); + TEN_LOGI("[%s] Failed to on_deinit_done() because of incorrect timing: %d", + ten_extension_get_name(extension, true), extension->state); return false; } diff --git a/tests/ten_runtime/integration/python/standalone_test_python/default_extension_python/tests/test_async_basic_2.py b/tests/ten_runtime/integration/python/standalone_test_python/default_extension_python/tests/test_async_basic_2.py index 2b17d2f9fc..adf7969221 100644 --- a/tests/ten_runtime/integration/python/standalone_test_python/default_extension_python/tests/test_async_basic_2.py +++ b/tests/ten_runtime/integration/python/standalone_test_python/default_extension_python/tests/test_async_basic_2.py @@ -41,7 +41,8 @@ async def on_start(self, ten_env: AsyncTenEnvTester) -> None: if statusCode == StatusCode.OK: ten_env.stop_test() - await asyncio.sleep(3) + # TODO(Wei): Enable this when we done all right. + # await asyncio.sleep(3) def test_basic():