From 30540b7f67975c7ec335a4a5a7cf0cc7618cc9da Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Thu, 8 Aug 2024 15:24:21 +0200 Subject: [PATCH 01/11] added pub sub test for memory leaks --- tests/CMakeLists.txt | 6 ++- tests/run_leak_check.sh | 19 ++++++++ tests/z_leak_pub_sub_test.c | 91 +++++++++++++++++++++++++++++++++++++ 3 files changed, 115 insertions(+), 1 deletion(-) create mode 100755 tests/run_leak_check.sh create mode 100644 tests/z_leak_pub_sub_test.c diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 69e7e1530..4164ae24d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -29,6 +29,8 @@ foreach(file ${files}) set(test_type "integration") elseif (${file} MATCHES "^.*z_build_.*$") set(test_type "build") + elseif (${file} MATCHES "^.*z_leak_.*$") + set(test_type "leak") else() message(FATAL_ERROR "Test file ${file} does not match any known type (z_api_ or z_int_ or z_build)") endif() @@ -39,6 +41,8 @@ foreach(file ${files}) target_link_libraries(${target} PRIVATE zenohc::lib Threads::Threads) copy_dlls(${target}) set_property(TARGET ${target} PROPERTY C_STANDARD 11) - add_test(NAME "${test_type}_${target}" COMMAND ${target}) + if (NOT(test_type STREQUAL ${CMAKE_CURRENT_SOURCE_DIR})) + add_test(NAME "${test_type}_${target}" COMMAND ${target}) + endif() endforeach() diff --git a/tests/run_leak_check.sh b/tests/run_leak_check.sh new file mode 100755 index 000000000..54504ffe5 --- /dev/null +++ b/tests/run_leak_check.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +set -e +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +function check_leaks { + echo "Checking $1 for memory leaks" + valgrind --leak-check=full --num-callers=50 --log-file="$SCRIPT_DIR/$1_leaks.log" $SCRIPT_DIR/target/debug/$1 + num_leaks=$(grep 'ERROR SUMMARY: [0-9]+' -Eo "$SCRIPT_DIR/$1_leaks.log" | grep '[0-9]+' -Eo) + echo "Detected $num_leaks memory leaks" + if (( num_leaks == 0 )) + then + return 0 + else + cat $SCRIPT_DIR/$1_leaks.log + return -1 + fi +} + +check_leaks $1 \ No newline at end of file diff --git a/tests/z_leak_pub_sub_test.c b/tests/z_leak_pub_sub_test.c new file mode 100644 index 000000000..e314e678d --- /dev/null +++ b/tests/z_leak_pub_sub_test.c @@ -0,0 +1,91 @@ +// +// Copyright (c) 2022 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, + +#include +#include +#include +#include + +#include "zenoh.h" + +#undef NDEBUG +#include + +const char *PUB_KEY_EXPR = "test/valgrind/data"; +const char *SUB_KEY_EXPR = "test/valgrind/**"; + +void data_handler(const z_loaned_sample_t *sample, void *arg) { + z_view_string_t key_string; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &key_string); + + z_owned_string_t payload_string; + z_bytes_deserialize_into_string(z_sample_payload(sample), &payload_string); + + printf(">> [Subscriber] Received ('%.*s': '%.*s')\n", (int)z_string_len(z_loan(key_string)), + z_string_data(z_loan(key_string)), (int)z_string_len(z_loan(payload_string)), + z_string_data(z_loan(payload_string))); + z_drop(z_move(payload_string)); +} + +int main(int argc, char **argv) { + // let _z = zenoh_runtime::ZRuntimePoolGuard; + // zenoh_util::init_log_test(); + printf("Declaring Publisher on %s\n", PUB_KEY_EXPR); + + z_owned_keyexpr_t pub_keyexpr; + z_keyexpr_from_str(&pub_keyexpr, PUB_KEY_EXPR); + + z_owned_config_t pub_config; + z_config_default(&pub_config); + + z_owned_session_t pub_session; + z_open(&pub_session, z_move(pub_config)); + + z_owned_publisher_t publisher; + z_declare_publisher(&publisher, z_loan(pub_session), z_loan(pub_keyexpr), NULL); + + printf("Declaring Subscriber on %s\n", SUB_KEY_EXPR); + + z_view_keyexpr_t sub_keyexpr; + z_view_keyexpr_from_str(&sub_keyexpr, SUB_KEY_EXPR); + + z_owned_config_t sub_config; + z_config_default(&sub_config); + + z_owned_session_t sub_session; + z_open(&sub_session, z_move(sub_config)); + + z_owned_closure_sample_t callback; + z_closure(&callback, data_handler, NULL, NULL); + + z_owned_subscriber_t subscriber; + z_declare_subscriber(&subscriber, z_loan(sub_session), z_loan(sub_keyexpr), z_move(callback), NULL); + + z_sleep_s(1); + + char buf[32] = {0}; + for (int i = 0; i < 5; ++i) { + sprintf(buf, "data [%4d]", i); + printf("Putting Data ('%s': '%s')...\n", PUB_KEY_EXPR, buf); + z_publisher_put_options_t options; + z_publisher_put_options_default(&options); + + z_owned_bytes_t payload; + z_bytes_serialize_from_str(&payload, buf); + + z_publisher_put(z_loan(publisher), z_move(payload), &options); + z_sleep_s(1); + } + + return 0; +} \ No newline at end of file From e7df8d6192e43d3626bf47c0ab7a673cf1325718 Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Thu, 8 Aug 2024 18:29:25 +0000 Subject: [PATCH 02/11] added valgrind test --- .github/workflows/ci.yml | 14 +++++++++++++- Cargo.lock | 1 + Cargo.toml | 1 + Cargo.toml.in | 1 + include/zenoh_commons.h | 1 + src/lib.rs | 5 +++++ tests/CMakeLists.txt | 6 +++++- tests/run_leak_check.sh | 6 +++--- tests/z_leak_pub_sub_test.c | 10 ++++++++-- 9 files changed, 38 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d3566327b..776969393 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,6 +19,17 @@ jobs: - name: Run clang-format dry-run run: find include/ src/ tests/ examples/ -iname "*.h" -o -iname "*.c" | xargs clang-format -n -Werror + valgrind: + name: Install Valgrind for memory leak checks + runs-on: ubuntu-latest + needs: check + steps: + - name: Clone this repository + uses: actions/checkout@v4 + + - name: Install valgrind + uses: taiki-e/install-action@valgrind + build: name: Build on ${{ matrix.os }} runs-on: ${{ matrix.os }} @@ -103,6 +114,7 @@ jobs: !target/release/.* !target/release/*.d + # NOTE: In GitHub repository settings, the "Require status checks to pass # before merging" branch protection rule ensures that commits are only merged # from branches where specific status checks have passed. These checks are @@ -111,7 +123,7 @@ jobs: ci: name: CI status checks runs-on: ubuntu-latest - needs: build + needs: [build, valgrind] if: always() steps: - name: Check whether all jobs pass diff --git a/Cargo.lock b/Cargo.lock index c6557bf0e..52e2b5422 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3683,6 +3683,7 @@ dependencies = [ "unwrap-infallible", "zenoh", "zenoh-ext", + "zenoh-runtime", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index ce05412b4..711b2986e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,6 +54,7 @@ unwrap-infallible = "0.1.5" const_format = "0.2.32" zenoh = { version = "0.11.0-dev", git = "https://github.com/eclipse-zenoh/zenoh.git", branch = "dev/1.0.0", default-features = false, features = ["internal"] } zenoh-ext = { version = "0.11.0-dev", git = "https://github.com/eclipse-zenoh/zenoh.git", branch = "dev/1.0.0" , optional = true } +zenoh-runtime = { version = "0.11.0-dev", git = "https://github.com/eclipse-zenoh/zenoh.git", branch = "dev/1.0.0" } flume = "*" [build-dependencies] diff --git a/Cargo.toml.in b/Cargo.toml.in index 34d98ecfd..98fb93190 100644 --- a/Cargo.toml.in +++ b/Cargo.toml.in @@ -54,6 +54,7 @@ unwrap-infallible = "0.1.5" const_format = "0.2.32" zenoh = { version = "0.11.0-dev", git = "https://github.com/eclipse-zenoh/zenoh.git", branch = "dev/1.0.0", default-features = false, features = ["internal"] } zenoh-ext = { version = "0.11.0-dev", git = "https://github.com/eclipse-zenoh/zenoh.git", branch = "dev/1.0.0" , optional = true } +zenoh-runtime = { version = "0.11.0-dev", git = "https://github.com/eclipse-zenoh/zenoh.git", branch = "dev/1.0.0" } flume = "*" [build-dependencies] diff --git a/include/zenoh_commons.h b/include/zenoh_commons.h index ae89b03b6..ec432412c 100644 --- a/include/zenoh_commons.h +++ b/include/zenoh_commons.h @@ -4492,6 +4492,7 @@ ZENOHC_API void zc_shm_client_list_new(zc_owned_shm_client_list_t *this_); #if (defined(SHARED_MEMORY) && defined(UNSTABLE)) ZENOHC_API void zc_shm_client_list_null(zc_owned_shm_client_list_t *this_); #endif +ZENOHC_API void zc_stop_z_runtime(void); /** * Constructs and declares a publication cache. * diff --git a/src/lib.rs b/src/lib.rs index ab777dfa4..1f087d0e7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -134,3 +134,8 @@ impl CopyableToCArray for &str { self.as_bytes().copy_to_c_array(buf, len) } } + +#[no_mangle] +pub extern "C" fn zc_stop_z_runtime() { + let _z = zenoh_runtime::ZRuntimePoolGuard; +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 4164ae24d..263dc8676 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,6 +1,7 @@ message(STATUS "zenoh-c tests") add_custom_target(tests) +configure_file(${PROJECT_SOURCE_DIR}/tests/run_leak_check.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/run_leak_check.sh COPYONLY) find_package(Threads REQUIRED) @@ -41,8 +42,11 @@ foreach(file ${files}) target_link_libraries(${target} PRIVATE zenohc::lib Threads::Threads) copy_dlls(${target}) set_property(TARGET ${target} PROPERTY C_STANDARD 11) - if (NOT(test_type STREQUAL ${CMAKE_CURRENT_SOURCE_DIR})) + find_program(VALGRIND valgrind) + if (NOT(test_type STREQUAL leak)) add_test(NAME "${test_type}_${target}" COMMAND ${target}) + elseif(VALGRIND) + add_test(NAME "${test_type}_${target}" COMMAND bash ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/run_leak_check.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${target}) endif() endforeach() diff --git a/tests/run_leak_check.sh b/tests/run_leak_check.sh index 54504ffe5..13daa2b39 100755 --- a/tests/run_leak_check.sh +++ b/tests/run_leak_check.sh @@ -4,14 +4,14 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) function check_leaks { echo "Checking $1 for memory leaks" - valgrind --leak-check=full --num-callers=50 --log-file="$SCRIPT_DIR/$1_leaks.log" $SCRIPT_DIR/target/debug/$1 - num_leaks=$(grep 'ERROR SUMMARY: [0-9]+' -Eo "$SCRIPT_DIR/$1_leaks.log" | grep '[0-9]+' -Eo) + valgrind --leak-check=full --num-callers=50 --log-file="$1.leaks.log" $1 + num_leaks=$(grep 'ERROR SUMMARY: [0-9]+' -Eo "$1.leaks.log" | grep '[0-9]+' -Eo) echo "Detected $num_leaks memory leaks" if (( num_leaks == 0 )) then return 0 else - cat $SCRIPT_DIR/$1_leaks.log + cat $1.leaks.log return -1 fi } diff --git a/tests/z_leak_pub_sub_test.c b/tests/z_leak_pub_sub_test.c index e314e678d..01344b5a6 100644 --- a/tests/z_leak_pub_sub_test.c +++ b/tests/z_leak_pub_sub_test.c @@ -38,8 +38,6 @@ void data_handler(const z_loaned_sample_t *sample, void *arg) { } int main(int argc, char **argv) { - // let _z = zenoh_runtime::ZRuntimePoolGuard; - // zenoh_util::init_log_test(); printf("Declaring Publisher on %s\n", PUB_KEY_EXPR); z_owned_keyexpr_t pub_keyexpr; @@ -87,5 +85,13 @@ int main(int argc, char **argv) { z_sleep_s(1); } + z_undeclare_publisher(z_move(publisher)); + z_undeclare_subscriber(z_move(subscriber)); + z_close(z_move(pub_session)); + z_close(z_move(sub_session)); + z_drop(z_move(pub_keyexpr)); + + zc_stop_z_runtime(); + return 0; } \ No newline at end of file From b64d9186f7381bcf66e3dfe2722e1ac48f0565e3 Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Thu, 8 Aug 2024 20:31:51 +0200 Subject: [PATCH 03/11] format --- build-resources/opaque-types/src/lib.rs | 1 - tests/z_leak_pub_sub_test.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/build-resources/opaque-types/src/lib.rs b/build-resources/opaque-types/src/lib.rs index b0370ceef..1c1a8b7c6 100644 --- a/build-resources/opaque-types/src/lib.rs +++ b/build-resources/opaque-types/src/lib.rs @@ -63,7 +63,6 @@ pub struct CSlice { _context: *mut c_void, } - get_opaque_type_data!(CSlice, z_owned_slice_t); /// A contiguous sequence of bytes owned by some other entity. get_opaque_type_data!(CSlice, z_view_slice_t); diff --git a/tests/z_leak_pub_sub_test.c b/tests/z_leak_pub_sub_test.c index 01344b5a6..0f4c46120 100644 --- a/tests/z_leak_pub_sub_test.c +++ b/tests/z_leak_pub_sub_test.c @@ -94,4 +94,4 @@ int main(int argc, char **argv) { zc_stop_z_runtime(); return 0; -} \ No newline at end of file +} From 7d62ec6e798701b78a0fe20e60a1ed5093e10e4d Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Thu, 8 Aug 2024 20:37:34 +0200 Subject: [PATCH 04/11] ci fix --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 776969393..1b822cfa1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: valgrind: name: Install Valgrind for memory leak checks runs-on: ubuntu-latest - needs: check + needs: check_format steps: - name: Clone this repository uses: actions/checkout@v4 From 60f81fa1f888254acbb0d1248e4f9a5eeceb43d3 Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Thu, 8 Aug 2024 20:41:43 +0200 Subject: [PATCH 05/11] ci fix --- .github/workflows/ci.yml | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1b822cfa1..3777c97ee 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,17 +19,6 @@ jobs: - name: Run clang-format dry-run run: find include/ src/ tests/ examples/ -iname "*.h" -o -iname "*.c" | xargs clang-format -n -Werror - valgrind: - name: Install Valgrind for memory leak checks - runs-on: ubuntu-latest - needs: check_format - steps: - - name: Clone this repository - uses: actions/checkout@v4 - - - name: Install valgrind - uses: taiki-e/install-action@valgrind - build: name: Build on ${{ matrix.os }} runs-on: ${{ matrix.os }} @@ -60,6 +49,10 @@ jobs: cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=~/local cmake --build . --target install --config Release + - name: Install valgrind + uses: taiki-e/install-action@valgrind + if: matrix.os == 'ubuntu-latest' + - name: Run cmake tests with zenoh-c as dynamic library shell: bash run: | @@ -123,7 +116,7 @@ jobs: ci: name: CI status checks runs-on: ubuntu-latest - needs: [build, valgrind] + needs: build if: always() steps: - name: Check whether all jobs pass From 46929f664799e9b397de7dde807c5a0c5ef843a0 Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Thu, 8 Aug 2024 21:27:33 +0200 Subject: [PATCH 06/11] add queryable-get memory leaks test --- tests/z_leak_pub_sub_test.c | 5 +- tests/z_leak_queryable_get_test.c | 131 ++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 tests/z_leak_queryable_get_test.c diff --git a/tests/z_leak_pub_sub_test.c b/tests/z_leak_pub_sub_test.c index 0f4c46120..231d8b39e 100644 --- a/tests/z_leak_pub_sub_test.c +++ b/tests/z_leak_pub_sub_test.c @@ -1,5 +1,5 @@ // -// Copyright (c) 2022 ZettaScale Technology +// Copyright (c) 2024 ZettaScale Technology // // This program and the accompanying materials are made available under the // terms of the Eclipse Public License 2.0 which is available at @@ -24,7 +24,8 @@ const char *PUB_KEY_EXPR = "test/valgrind/data"; const char *SUB_KEY_EXPR = "test/valgrind/**"; -void data_handler(const z_loaned_sample_t *sample, void *arg) { +void data_handler(const z_loaned_sample_t *sample, void *context) { + (void)context; z_view_string_t key_string; z_keyexpr_as_view_string(z_sample_keyexpr(sample), &key_string); diff --git a/tests/z_leak_queryable_get_test.c b/tests/z_leak_queryable_get_test.c new file mode 100644 index 000000000..58f755950 --- /dev/null +++ b/tests/z_leak_queryable_get_test.c @@ -0,0 +1,131 @@ +// +// Copyright (c) 2024 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, + +#include +#include +#include +#include + +#include "zenoh.h" + +#undef NDEBUG +#include + +const char *GET_KEY_EXPR = "test/valgrind/data"; +const char *QUERYABLE_KEY_EXPR = "test/valgrind/**"; + +void query_handler(const z_loaned_query_t *query, void *context) { + (void)context; + z_view_string_t key_string; + z_keyexpr_as_view_string(z_query_keyexpr(query), &key_string); + + z_view_string_t params; + z_query_parameters(query, ¶ms); + + const z_loaned_bytes_t *payload = z_query_payload(query); + + z_owned_string_t payload_string; + z_bytes_deserialize_into_string(payload, &payload_string); + + printf(">> [Queryable ] Received Query '%.*s' with value '%.*s'\n", (int)z_string_len(z_loan(key_string)), + z_string_data(z_loan(key_string)), (int)z_string_len(z_loan(payload_string)), + z_string_data(z_loan(payload_string))); + z_drop(z_move(payload_string)); + z_query_reply_options_t options; + z_query_reply_options_default(&options); + + z_owned_bytes_t reply_payload; + z_bytes_clone(&reply_payload, payload); + + z_query_reply(query, z_query_keyexpr(query), z_move(reply_payload), &options); +} + +int main(int argc, char **argv) { + printf("Declaring Queryable on %s\n", QUERYABLE_KEY_EXPR); + + z_owned_keyexpr_t queryable_keyexpr; + z_keyexpr_from_str(&queryable_keyexpr, QUERYABLE_KEY_EXPR); + + z_owned_config_t queryable_config; + z_config_default(&queryable_config); + + z_owned_session_t queryable_session; + z_open(&queryable_session, z_move(queryable_config)); + + z_owned_closure_query_t callback; + z_closure(&callback, query_handler, NULL, NULL); + z_owned_queryable_t queryable; + z_declare_queryable(&queryable, z_loan(queryable_session), z_loan(queryable_keyexpr), z_move(callback), NULL); + + z_view_keyexpr_t get_keyexpr; + z_view_keyexpr_from_str(&get_keyexpr, GET_KEY_EXPR); + + z_owned_config_t get_config; + z_config_default(&get_config); + + z_owned_session_t get_session; + z_open(&get_session, z_move(get_config)); + + z_sleep_s(1); + + size_t received_replies = 0; + char buf[32] = {0}; + for (int i = 0; i < 5; ++i) { + sprintf(buf, "data [%4d]", i); + printf("Get with Data ('%s': '%s')...\n", GET_KEY_EXPR, buf); + z_get_options_t options; + z_get_options_default(&options); + + z_owned_bytes_t payload; + z_bytes_serialize_from_str(&payload, buf); + + options.payload = z_move(payload); + + z_owned_fifo_handler_reply_t handler; + z_owned_closure_reply_t closure; + z_fifo_channel_reply_new(&closure, &handler, 16); + + z_get(z_loan(get_session), z_loan(get_keyexpr), "", z_move(closure), &options); + + z_owned_reply_t reply; + while (z_recv(z_loan(handler), &reply) == Z_OK) { + received_replies++; + const z_loaned_sample_t *sample = z_reply_ok(z_loan(reply)); + assert(sample != NULL); + + z_view_string_t key_str; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &key_str); + + z_owned_string_t reply_str; + z_bytes_deserialize_into_string(z_sample_payload(sample), &reply_str); + + printf(">> Received ('%.*s': '%.*s')\n", (int)z_string_len(z_loan(key_str)), z_string_data(z_loan(key_str)), + (int)z_string_len(z_loan(reply_str)), z_string_data(z_loan(reply_str))); + z_drop(z_move(reply_str)); + z_drop(z_move(reply)); + } + + z_drop(z_move(handler)); + z_sleep_s(1); + } + assert(received_replies == 5); + + z_undeclare_queryable(z_move(queryable)); + z_close(z_move(get_session)); + z_close(z_move(queryable_session)); + z_drop(z_move(queryable_keyexpr)); + + zc_stop_z_runtime(); + + return 0; +} From 0f6558d493f30f0ccc648f0e686c85d5de41657c Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Thu, 8 Aug 2024 21:37:01 +0200 Subject: [PATCH 07/11] do not copy memory leaks script --- tests/CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 263dc8676..64f2bbc5c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,7 +1,6 @@ message(STATUS "zenoh-c tests") add_custom_target(tests) -configure_file(${PROJECT_SOURCE_DIR}/tests/run_leak_check.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/run_leak_check.sh COPYONLY) find_package(Threads REQUIRED) @@ -46,7 +45,7 @@ foreach(file ${files}) if (NOT(test_type STREQUAL leak)) add_test(NAME "${test_type}_${target}" COMMAND ${target}) elseif(VALGRIND) - add_test(NAME "${test_type}_${target}" COMMAND bash ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/run_leak_check.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${target}) + add_test(NAME "${test_type}_${target}" COMMAND bash ${PROJECT_SOURCE_DIR}/tests/run_leak_check.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${target}) endif() endforeach() From ff6a0c74b0f363b0a17108b1c0bb317a256f16c9 Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Thu, 8 Aug 2024 20:01:33 +0000 Subject: [PATCH 08/11] fixed memory leak in handlers --- src/closures/query_channel.rs | 2 +- src/closures/response_channel.rs | 2 +- src/closures/sample_channel.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/closures/query_channel.rs b/src/closures/query_channel.rs index f24f7033b..1b3c9cccb 100644 --- a/src/closures/query_channel.rs +++ b/src/closures/query_channel.rs @@ -61,7 +61,7 @@ extern "C" fn __z_handler_query_send(query: &z_loaned_query_t, context: *mut c_v extern "C" fn __z_handler_query_drop(context: *mut c_void) { unsafe { - let f = (context as *mut Arc).read(); + let f = Box::from_raw(context as *mut Arc); std::mem::drop(f); } } diff --git a/src/closures/response_channel.rs b/src/closures/response_channel.rs index f106a56a2..518d3eb7b 100644 --- a/src/closures/response_channel.rs +++ b/src/closures/response_channel.rs @@ -61,7 +61,7 @@ extern "C" fn __z_handler_reply_send(reply: &z_loaned_reply_t, context: *mut c_v extern "C" fn __z_handler_reply_drop(context: *mut c_void) { unsafe { - let f = (context as *mut Arc).read(); + let f = Box::from_raw(context as *mut Arc); std::mem::drop(f); } } diff --git a/src/closures/sample_channel.rs b/src/closures/sample_channel.rs index b74fc9b28..6f84f3b3d 100644 --- a/src/closures/sample_channel.rs +++ b/src/closures/sample_channel.rs @@ -63,7 +63,7 @@ extern "C" fn __z_handler_sample_send(sample: &z_loaned_sample_t, context: *mut extern "C" fn __z_handler_sample_drop(context: *mut c_void) { unsafe { - let f = (context as *mut Arc).read(); + let f = Box::from_raw(context as *mut Arc); std::mem::drop(f); } } From d4f42ea0aa95271072f530be7207fc17d98e5df3 Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Thu, 8 Aug 2024 20:09:08 +0000 Subject: [PATCH 09/11] docs update --- docs/api.rst | 8 ++++++++ include/zenoh_commons.h | 9 ++++++++- src/lib.rs | 4 ++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/docs/api.rst b/docs/api.rst index 9364c81a6..1f6a6a0b8 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -896,3 +896,11 @@ Functions .. doxygenfunction:: zc_init_logging .. doxygenfunction:: zc_init_logging_with_callback + + +Other +===== + +Functions +--------- +.. doxygenfunction:: zc_stop_z_runtime \ No newline at end of file diff --git a/include/zenoh_commons.h b/include/zenoh_commons.h index b06b625c2..24bfc5817 100644 --- a/include/zenoh_commons.h +++ b/include/zenoh_commons.h @@ -4599,7 +4599,14 @@ ZENOHC_API void zc_shm_client_list_new(zc_owned_shm_client_list_t *this_); #if (defined(SHARED_MEMORY) && defined(UNSTABLE)) ZENOHC_API void zc_shm_client_list_null(zc_owned_shm_client_list_t *this_); #endif -ZENOHC_API void zc_stop_z_runtime(void); +/** + * Stops all Zenoh tasks and drops all related static variables. + * All Zenoh-related structures should be properly dropped/undeclared PRIOR to this call. + * None of Zenoh functionality can be used after this call. + * Useful to suppress memory leaks messages due to Zenoh static variables (since they are never destroyed due to Rust language design). + */ +ZENOHC_API +void zc_stop_z_runtime(void); /** * Constructs and declares a publication cache. * diff --git a/src/lib.rs b/src/lib.rs index 7003be861..3ff20ae0f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -163,6 +163,10 @@ impl CopyableToCArray for &str { } } +/// Stops all Zenoh tasks and drops all related static variables. +/// All Zenoh-related structures should be properly dropped/undeclared PRIOR to this call. +/// None of Zenoh functionality can be used after this call. +/// Useful to suppress memory leaks messages due to Zenoh static variables (since they are never destroyed due to Rust language design). #[no_mangle] pub extern "C" fn zc_stop_z_runtime() { let _z = zenoh_runtime::ZRuntimePoolGuard; From 8d196791aeb7b41c22bad14572e7e940b78e4787 Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Thu, 8 Aug 2024 20:10:55 +0000 Subject: [PATCH 10/11] format --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3777c97ee..c7032a88a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -107,7 +107,6 @@ jobs: !target/release/.* !target/release/*.d - # NOTE: In GitHub repository settings, the "Require status checks to pass # before merging" branch protection rule ensures that commits are only merged # from branches where specific status checks have passed. These checks are From 1a769f12258a80f444106a07da54eac7c8618bca Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Fri, 9 Aug 2024 10:10:46 +0200 Subject: [PATCH 11/11] format --- tests/run_leak_check.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/run_leak_check.sh b/tests/run_leak_check.sh index 13daa2b39..7ce533bd8 100755 --- a/tests/run_leak_check.sh +++ b/tests/run_leak_check.sh @@ -16,4 +16,4 @@ function check_leaks { fi } -check_leaks $1 \ No newline at end of file +check_leaks $1