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

Implement Message Queue Limit to Prevent Memory Exhaustion in Embedded Devices #629

Merged
merged 35 commits into from
Jun 20, 2024
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
2a9d523
Issue 626: Implement Message Queue Limit to Prevent Memory Exhaustion…
sp-milos May 20, 2024
00bcf01
- block event processing when the network event queue is full
sp-martin May 28, 2024
9c9d562
- separete control-flow (signal) socket handling
sp-martin May 29, 2024
544f82e
- per device queue limit handling
sp-martin May 30, 2024
da71883
- fixed formatting and static analysis
sp-martin May 31, 2024
4eec493
- separate define for device concurent requests
sp-martin May 31, 2024
7877fd4
-send wakeup only to certain device network thread
sp-martin Jun 3, 2024
cbfcc01
- fixed android and esp32 builds
sp-martin Jun 3, 2024
eba31db
- renamed shutdown_pipe to wakeup_pipe
sp-martin Jun 3, 2024
cf6bac9
- optimized traversal of file descriptors
sp-martin Jun 3, 2024
a82dc4a
- fixed android and esp32 build breaks
sp-martin Jun 4, 2024
8170cad
- calculate max fd value from the recent device file descriptor set
sp-martin Jun 4, 2024
0607c59
- improved error handling and logging for signal_event_thread
sp-martin Jun 5, 2024
5419e5b
- logging the error code instead of a string using strerror()
sp-martin Jun 5, 2024
4747dee
- android port of Message Queue Limit
sp-martin Jun 5, 2024
6a25e74
- formatting
sp-martin Jun 5, 2024
fcc5352
- fixed build break after automerge
sp-martin Jun 5, 2024
2b2f467
- fixed build break when DOC_DYNAMIC_ALLOCATION_ENABLED=OFF
sp-martin Jun 6, 2024
e3199dc
- fixed android builds
sp-martin Jun 6, 2024
497f503
- fixed handling of tcp controlflow sockets on android
sp-martin Jun 6, 2024
129c206
- formatting, android build break fix
sp-martin Jun 6, 2024
65ffb5d
- linux build break fix
sp-martin Jun 6, 2024
ec4dac2
- unix amd64/arm64 build break fix
sp-martin Jun 6, 2024
0b456a5
- esp32 port of Message Queue Limit
sp-martin Jun 7, 2024
95e6cda
Added Windows port of message queue limit.
sp-milos Jun 10, 2024
3153809
Allow to set OC_DEVICE_MAX_NUM_CONCURRENT_REQUESTS in CMake
Danielius1922 Jun 12, 2024
98e3782
- tests for the network event queue, wakeup connectivity tests
sp-martin Jun 12, 2024
26df754
Automatic format commit
CascodaBot Jun 13, 2024
e6338d2
- fixed OC_DYNAMIC_ALLOCATION=OFF builds
sp-martin Jun 13, 2024
718ce71
- generic solution for comparing fd_set
sp-martin Jun 13, 2024
4b254d8
Run tests with OC_DEVICE_MAX_NUM_CONCURRENT_REQUESTS=1 on GitHub
Danielius1922 Jun 13, 2024
30cace2
- fixed generation of random negative numbers causing the pick_random…
sp-martin Jun 13, 2024
72f5d63
- corrected issues reported by SonarCloud
sp-martin Jun 14, 2024
584a756
- addressed sonar cloud issues
sp-martin Jun 14, 2024
bbdd320
- run tests on GitHub with thread sanitizer
Danielius1922 Jun 14, 2024
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
60 changes: 58 additions & 2 deletions api/oc_network_events.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,37 @@ static bool g_interface_up;
static bool g_interface_down;
#endif /* OC_NETWORK_MONITOR */

#ifdef OC_DYNAMIC_ALLOCATION
static size_t
get_events_queue_length(size_t device, oc_list_t events)
{
size_t msg_count = 0;
for (oc_message_t *msg = (oc_message_t *)oc_list_head(events); msg != NULL;
msg = msg->next) {
if (msg->endpoint.device == device) {
++msg_count;
}
}
return msg_count;
}

static void
send_wakeup_signal(oc_list_t events)
{
size_t msg_total = oc_list_length(events);

int deviceId = 0;
while (msg_total >= OC_DEVICE_MAX_NUM_CONCURRENT_REQUESTS) {
size_t msg_device_count = get_events_queue_length(deviceId, events);
if (msg_device_count >= OC_DEVICE_MAX_NUM_CONCURRENT_REQUESTS) {
oc_connectivity_wakeup(deviceId);
}
msg_total -= msg_device_count;
++deviceId; // advance to the next device
}
}
#endif /* OC_DYNAMIC_ALLOCATION */

static void
oc_process_network_event(void)
{
Expand All @@ -65,6 +96,11 @@ oc_process_network_event(void)
#endif /* OC_NETWORK_MONITOR */
oc_network_event_handler_mutex_unlock();

#ifdef OC_DYNAMIC_ALLOCATION
// send a wake-up signal in case the queue might reach the limit for a device
send_wakeup_signal(network_events);
#endif /* OC_DYNAMIC_ALLOCATION */

#ifdef OC_HAS_FEATURE_TCP_ASYNC_CONNECT
oc_tcp_on_connect_event_t *event =
(oc_tcp_on_connect_event_t *)oc_list_pop(network_tcp_connect_events);
Expand Down Expand Up @@ -153,10 +189,10 @@ oc_network_tcp_connect_event(oc_tcp_on_connect_event_t *event)
}
#endif /* OC_HAS_FEATURE_TCP_ASYNC_CONNECT */

int
size_t
oc_network_drop_receive_events(const oc_endpoint_t *endpoint)
{
int dropped = 0;
size_t dropped = 0;
oc_network_event_handler_mutex_lock();
for (oc_message_t *message = (oc_message_t *)oc_list_head(g_network_events);
message != NULL;) {
Expand All @@ -178,6 +214,15 @@ oc_network_drop_receive_events(const oc_endpoint_t *endpoint)
}
message = next;
}

#ifdef OC_DYNAMIC_ALLOCATION
if (get_events_queue_length(endpoint->device, g_network_events) + dropped >=
OC_DEVICE_MAX_NUM_CONCURRENT_REQUESTS) {
// send a wake-up signal in case the queue for the device was full
oc_connectivity_wakeup(endpoint->device);
}
#endif /* OC_DYNAMIC_ALLOCATION */

oc_network_event_handler_mutex_unlock();
return dropped;
}
Expand All @@ -204,3 +249,14 @@ oc_network_interface_event(oc_interface_event_t event)
_oc_signal_event_loop();
}
#endif /* OC_NETWORK_MONITOR */

#ifdef OC_DYNAMIC_ALLOCATION
size_t
oc_network_get_event_queue_length(size_t device)
{
oc_network_event_handler_mutex_lock();
size_t msg_count = get_events_queue_length(device, g_network_events);
oc_network_event_handler_mutex_unlock();
return msg_count;
}
#endif /* OC_DYNAMIC_ALLOCATION */
11 changes: 10 additions & 1 deletion api/oc_network_events_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ void oc_network_tcp_connect_event(oc_tcp_on_connect_event_t *event)
* @param endpoint the endpoint (cannot be NULL)
* @return number of events dropped
*/
int oc_network_drop_receive_events(const oc_endpoint_t *endpoint) OC_NONNULL();
size_t oc_network_drop_receive_events(const oc_endpoint_t *endpoint)
OC_NONNULL();

#ifdef OC_NETWORK_MONITOR
/**
Expand All @@ -78,6 +79,14 @@ typedef struct oc_network_interface_cb
void oc_network_interface_event(oc_interface_event_t event);
#endif /* OC_NETWORK_MONITOR */

/**
* @brief Returns the network event queue length for the device
*
* @param device valid device index
* @return number of events in the queue
*/
size_t oc_network_get_event_queue_length(size_t device);

#ifdef __cplusplus
}
#endif
Expand Down
Loading
Loading