https://bugs.kde.org/show_bug.cgi?id=521060
Bug ID: 521060
Summary: kalendarac: unbounded memory growth in
ETMCalendar::mItemsByCollection
Classification: Applications
Product: konsolekalendar
Version First unspecified
Reported In:
Platform: Other
OS: Linux
Status: REPORTED
Severity: normal
Priority: NOR
Component: general
Assignee: [email protected]
Reporter: [email protected]
Target Milestone: ---
PROBLEM
-------
The kalendarac daemon exhibits unbounded memory growth over time, with RSS
reaching 2 GB or more under normal use. The issue is more pronounced with
calendars that produce frequent item updates (e.g., a work calendar with
recurring changes). A workaround of restarting the service once it exceeded
~400 MB has been necessary.
ROOT CAUSE
----------
mItemsByCollection in CalendarBasePrivate is a
QMultiHash<CollectionId, Akonadi::Item> used to index items by their
collection. At runtime, ETMCalendarPrivate::updateItem() is the path
called for every item-change notification from the Akonadi ETM, and the
code did:
// Before (leaks):
mItemsByCollection.insert(item.storageCollectionId(), item);
This always appends and never removes the stale entry. Worse, implicit
remove() calls elsewhere also fail silently, because
QMultiHash::remove(key, value) uses Akonadi::Item::operator==, which
compares both id and revision. Since the revision changes on every
Akonadi update, the old entry is never found and never erased.
Since itemsAdded() only runs at startup and updateItem() is the exclusive
runtime path, every single update accumulates a duplicate entry. Memory
growth is proportional to the total number of updates over the daemon's
lifetime, not the number of distinct items.
VALIDATION (BEFORE FIX)
-----------------------
Tested with a work calendar source over 7 hours of continuous operation:
- RSS: unbounded growth, 2 GB+
- memCal vs itemById size: divergent
- Duplicate entries in mItemsByCollection: accumulate indefinitely
- Updates processed: ~25,827 with no growth plateau
Heaptrack confirmed the leak site; icalmemory_new_buffer fragmentation
from libical is expected parser behavior, not the leak.
FIX
---
A merge request is already open with a fix:
https://invent.kde.org/pim/akonadi-calendar/-/merge_requests/176
The fix introduces CalendarBasePrivate::upsertItemInCollectionIndex(),
which:
1. Looks up the existing item by id() in mItemById.
2. Uses equalRange(collectionId) and iterates to find the entry
matching item.id() (revision-independent lookup).
3. Erases the old entry via iterator.
4. Inserts the new entry.
Applied in both internalInsert() and updateItem().
After the fix on the same workload:
- RSS: stable ~300 KB
- memCal vs itemById: consistent
- Duplicate entries: zero drift
AFFECTED VERSIONS
-----------------
Reproducible on master / current akonadi-calendar (KF6). Likely also
affects the KF5-based releases shipped by distributions.
REPRODUCTION
------------
1. Run kalendarac connected to an Akonadi resource that emits frequent
item changes (e.g., a calendar synced with a server, or a local
resource that is being edited repeatedly).
2. Observe RSS over several hours:
watch -n 60 ps -o rss= -C kalendarac
RSS grows monotonically and without bound, correlated with the number
of item-change notifications received.
3. Inspect mItemsByCollection via debugger or logging; the number of
entries diverges from mItemById, with one new duplicate accumulated
per update.
--
You are receiving this mail because:
You are watching all bug changes.