Don't erase elements if multiple subscriptions use them - #425
Don't erase elements if multiple subscriptions use them#425kilativ-dotcom wants to merge 18 commits into
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #425 +/- ##
==========================================
+ Coverage 95.70% 95.76% +0.05%
==========================================
Files 237 237
Lines 26965 27315 +350
Branches 1863 1880 +17
==========================================
+ Hits 25808 26157 +349
- Misses 1157 1158 +1 🚀 New features to boost your workflow:
|
| sc_uint32 * count = (sc_uint32 *)sc_hash_table_get( | ||
| manager->emitted_erase_events, GUINT_TO_POINTER(SC_ADDR_LOCAL_TO_INT(connector_addr))); | ||
| if (count == null_ptr) | ||
| { | ||
| count = sc_mem_new(sc_uint32, 1); | ||
| *count = 0; | ||
| } | ||
| ++(*count); | ||
| sc_hash_table_insert(manager->emitted_erase_events, GUINT_TO_POINTER(SC_ADDR_LOCAL_TO_INT(connector_addr)), count); |
There was a problem hiding this comment.
| sc_uint32 * count = (sc_uint32 *)sc_hash_table_get( | |
| manager->emitted_erase_events, GUINT_TO_POINTER(SC_ADDR_LOCAL_TO_INT(connector_addr))); | |
| if (count == null_ptr) | |
| { | |
| count = sc_mem_new(sc_uint32, 1); | |
| *count = 0; | |
| } | |
| ++(*count); | |
| sc_hash_table_insert(manager->emitted_erase_events, GUINT_TO_POINTER(SC_ADDR_LOCAL_TO_INT(connector_addr)), count); | |
| sc_uint32 count = (sc_uint32)(sc_uint64)sc_hash_table_get( | |
| manager->emitted_erase_events, GUINT_TO_POINTER(SC_ADDR_LOCAL_TO_INT(connector_addr))); | |
| ++count; | |
| sc_hash_table_insert(manager->emitted_erase_events, GUINT_TO_POINTER(SC_ADDR_LOCAL_TO_INT(connector_addr)), count); |
|
|
||
| sc_result _sc_storage_element_erase_with_incoming_outgoing_connectors( | ||
| sc_memory_context const * ctx, | ||
| sc_addr connector_chain_begin_addr, |
There was a problem hiding this comment.
chain is like sequence of connectors next connector of which cannot exist without previous(previous element is source/target of next connector)
… event linked to subscription
…stency for agents responding to sc-events of erasing sc-elements
c8eebff to
ad6d130
Compare
| sc_event_emission_manager * emission_manager = sc_storage_get_event_emission_manager(); | ||
| if (subscription_manager == null_ptr) | ||
| return SC_RESULT_NO; |
There was a problem hiding this comment.
⚠️ Bug: Wrong variable in null check leaves emission_manager unchecked
In sc_event_subscription_destroy, after fetching emission_manager, the guard at line 211 mistakenly re-checks subscription_manager == null_ptr instead of emission_manager == null_ptr (copy-paste error). If emission_manager is null while subscription_manager and storage are non-null, the code reaches line 236 and dereferences emission_manager->pool_monitor, causing a null-pointer crash. Change the check to test emission_manager.
Check emission_manager instead of re-checking subscription_manager.:
sc_event_emission_manager * emission_manager = sc_storage_get_event_emission_manager();
if (emission_manager == null_ptr)
return SC_RESULT_NO;
- Apply fix
Check the box to apply the fix or reply for a change | Was this helpful? React with 👍 / 👎
| sc_monitor_acquire_read(&emission_manager->pool_monitor); | ||
| sc_uint32 count = (sc_uint32)(sc_uint64)sc_hash_table_get( | ||
| emission_manager->emitted_erase_events, GUINT_TO_POINTER(SC_ADDR_LOCAL_TO_INT(addr))); | ||
| if (count == 0) | ||
| sc_hash_table_insert(incident_elements_under_erasure, key, element); | ||
| sc_monitor_release_read(&emission_manager->pool_monitor); |
There was a problem hiding this comment.
⚠️ Bug: emitted_erase_events accessed under two different monitors (data race)
The emitted_erase_events hash table is written by the worker and by _sc_event_emission_manager_add while holding emitted_erase_events_monitor, but sc_storage.c reads it while holding only pool_monitor (read). Because readers and the worker never share a common lock, concurrent erase + event processing produces unsynchronized concurrent access to a GHashTable, which is undefined behavior and can corrupt the table or crash. The storage reads should acquire emitted_erase_events_monitor (not pool_monitor) to match the writers.
Guard reads of emitted_erase_events with emitted_erase_events_monitor at both sc_storage.c sites.:
sc_monitor_acquire_read(&emission_manager->emitted_erase_events_monitor);
sc_uint32 count = (sc_uint32)(sc_uint64)sc_hash_table_get(
emission_manager->emitted_erase_events, GUINT_TO_POINTER(SC_ADDR_LOCAL_TO_INT(addr)));
...
sc_monitor_release_read(&emission_manager->emitted_erase_events_monitor);
- Apply fix
Check the box to apply the fix or reply for a change | Was this helpful? React with 👍 / 👎
|
|
||
| if (queue->running == SC_FALSE) | ||
| if (manager->running == SC_FALSE) | ||
| goto end; |
There was a problem hiding this comment.
💡 Bug: running flag read/written without synchronization
sc_event_emission_manager_stop now reads and writes manager->running with no lock, while the worker reads manager->running under destroy_monitor. This is an unsynchronized concurrent access to running; previously it was protected by destroy_monitor. In practice this is a benign torn-read of a bool, but it is a data race per the memory model and could delay a worker observing the shutdown. Re-acquire destroy_monitor around the update or make the flag atomic.
Was this helpful? React with 👍 / 👎
Code Review
|
| Auto-apply | Compact |
|
|
Was this helpful? React with 👍 / 👎 | Gitar
Summary by Gitar
sc_storage_element_eraseby preventing premature element deletion if active subscriptions are present._sc_storage_element_erase_with_incoming_outgoing_connectors_and_hanging_nodesto recursively manage element erasure.emitted_erase_eventstracking tosc_event_emission_managerto prevent race conditions during concurrent deletions.sc_event_emission_managerto safely wait for pending events during shutdown.test_sc_event.cppto verify stability of concurrent subscriptions during erasure.test_sc_specified_agents.cppandtest_sc_event.cppusingScMemoryContextEventsPendingGuard.This will update automatically on new commits.