Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix memory leak in z_declare_subscriber #262

Merged
merged 5 commits into from
Oct 18, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ include(GNUInstallDirs)
option(BUILD_SHARED_LIBS "Build shared libraries if ON, otherwise build static libraries" ON)
option(ZENOH_DEBUG "Use this to set the ZENOH_DEBUG variable." 0)
option(WITH_ZEPHYR "Build for Zephyr RTOS" OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE INTERNAL "")
if(CMAKE_EXPORT_COMPILE_COMMANDS)
set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES
${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES})
endif()

if(CMAKE_SYSTEM_NAME MATCHES "Windows")
set(BUILD_SHARED_LIBS "OFF")
Expand Down
1 change: 1 addition & 0 deletions include/zenoh-pico/session/session.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ typedef void (*_z_data_handler_t)(const _z_sample_t *sample, void *arg);

typedef struct {
_z_keyexpr_t _key;
uint16_t _key_id;
uint32_t _id;
_z_data_handler_t _callback;
_z_drop_handler_t _dropper;
Expand Down
20 changes: 13 additions & 7 deletions src/api/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -810,6 +810,7 @@ z_owned_subscriber_t z_declare_subscriber(z_session_t zs, z_keyexpr_t keyexpr, z
const z_subscriber_options_t *options) {
void *ctx = callback->context;
callback->context = NULL;
char *suffix = NULL;

z_keyexpr_t key = keyexpr;
// TODO: Currently, if resource declarations are done over multicast transports, the current protocol definition
Expand All @@ -824,11 +825,13 @@ z_owned_subscriber_t z_declare_subscriber(z_session_t zs, z_keyexpr_t keyexpr, z
if (wild != NULL && wild != keyexpr._suffix) {
wild -= 1;
size_t len = wild - keyexpr._suffix;
char *suffix = z_malloc(len + 1);
memcpy(suffix, keyexpr._suffix, len);
suffix[len] = 0;
keyexpr._suffix = suffix;
_z_keyexpr_set_owns_suffix(&keyexpr, true);
suffix = z_malloc(len + 1);
p-avital marked this conversation as resolved.
Show resolved Hide resolved
if (suffix != NULL) {
memcpy(suffix, keyexpr._suffix, len);
suffix[len] = 0;
keyexpr._suffix = suffix;
_z_keyexpr_set_owns_suffix(&keyexpr, false);
}
}
uint16_t id = _z_declare_resource(zs._val, keyexpr);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is declared if suffix allocation fails? It seems that it will declare a keyexpr with id but no suffix...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will declare the exact keyexpr that was passed to the subscriber, but will keep the wild suffix, so the bug is not the one you expected, but it is buggy

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually was a bug, but not the one you expected. Let's just cancel attempting to declare the resource if we failed to allocate for the suffix, the other steps would probably also fail anyway.

key = _z_rid_with_suffix(id, wild);
Expand All @@ -841,9 +844,12 @@ z_owned_subscriber_t z_declare_subscriber(z_session_t zs, z_keyexpr_t keyexpr, z
if (options != NULL) {
subinfo.reliability = options->reliability;
}
_z_subscriber_t *sub = _z_declare_subscriber(zs._val, key, subinfo, callback->call, callback->drop, ctx);
if (suffix != NULL) {
z_free(suffix);
}

return (z_owned_subscriber_t){
._value = _z_declare_subscriber(zs._val, key, subinfo, callback->call, callback->drop, ctx)};
return (z_owned_subscriber_t){._value = sub};
}

z_owned_pull_subscriber_t z_declare_pull_subscriber(z_session_t zs, z_keyexpr_t keyexpr,
Expand Down
2 changes: 2 additions & 0 deletions src/net/primitives.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ _z_subscriber_t *_z_declare_subscriber(_z_session_t *zn, _z_keyexpr_t keyexpr, _
_z_data_handler_t callback, _z_drop_handler_t dropper, void *arg) {
_z_subscription_t s;
s._id = _z_get_entity_id(zn);
s._key_id = keyexpr._id;
s._key = _z_get_expanded_key_from_key(zn, &keyexpr);
s._info = sub_info;
s._callback = callback;
Expand Down Expand Up @@ -175,6 +176,7 @@ int8_t _z_undeclare_subscriber(_z_subscriber_t *sub) {
_z_network_message_t n_msg = _z_n_msg_make_declare(declaration);
if (_z_send_n_msg(sub->_zn, &n_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) == _Z_RES_OK) {
// Only if message is successfully send, local subscription state can be removed
_z_undeclare_resource(sub->_zn, s->ptr->_key_id);
_z_unregister_subscription(sub->_zn, _Z_RESOURCE_IS_LOCAL, s);
} else {
ret = _Z_ERR_ENTITY_UNKNOWN;
Expand Down
Loading