after running valgrind again with --leak-check=full and
--show-reachable=yes, it appears that a great deal of the
formally still reachable, but probably quite lost memory originates from
e_cal_backend_cache_get_components() (e-cal-backend-cache.c line 473
specifically, which calls icalparser_parse_string())
It seems this function is identical in SVN

==1641== 5,393,785 bytes in 181,741 blocks are still reachable in loss
record 102 of 107
==1641==    at 0x4C1FFAB: malloc (vg_replace_malloc.c:207)
==1641==    by 0x9D16DE1: strdup (strdup.c:43)
==1641==    by 0x6C61604: icalvalue_set_text
(in /usr/lib/libecal-1.2.so.7.2.0)
==1641==    by 0x6C6167D: icalvalue_new_text
(in /usr/lib/libecal-1.2.so.7.2.0)
==1641==    by 0x6C769E2: icalvalue_new_from_string_with_error
(in /usr/lib/libecal-1.2.so.7.2.0)
==1641==    by 0x6C688BA: icalparser_add_line
(in /usr/lib/libecal-1.2.so.7.2.0)
==1641==    by 0x6C68CB8: icalparser_parse
(in /usr/lib/libecal-1.2.so.7.2.0)
==1641==    by 0x6C68F20: icalparser_parse_string
(in /usr/lib/libecal-1.2.so.7.2.0)
==1641==    by 0x69DE5D6: e_cal_backend_cache_get_components
(e-cal-backend-cache.c:473)
==1641==    by 0xF4D20EA: synch_slave_loop (e-cal-backend-caldav.c:1259)
==1641==    by 0x8FDDCA3: g_thread_create_proxy (gthread.c:635)
==1641==    by 0x9A8C016: start_thread (pthread_create.c:297)
==1641== 
==1641== 
==1641== 7,568,054 bytes in 39,280 blocks are still reachable in loss
record 103 of 107
==1641==    at 0x4C1F0BC: calloc (vg_replace_malloc.c:397)
==1641==    by 0x8FBFA52: g_malloc0 (gmem.c:151)
==1641==    by 0x8FABCC8: g_hash_table_new_full (ghash.c:358)
==1641==    by 0x8FCE136: g_scanner_new (gscanner.c:228)
==1641==    by 0x6ED64CA: e_sexp_new
(in /usr/lib/libedataserver-1.2.so.9.1.0)
==1641==    by 0x69DF470: e_cal_backend_sexp_new
(e-cal-backend-sexp.c:1362)
==1641==    by 0x69E61E7: impl_Cal_getQuery (e-data-cal.c:415)
==1641==    by 0x82B3FA5: ORBit_small_invoke_adaptor
(in /usr/lib/libORBit-2.so.0.1.0)
==1641==    by 0x82C327F: (within /usr/lib/libORBit-2.so.0.1.0)
==1641==    by 0x82C3839: (within /usr/lib/libORBit-2.so.0.1.0)
==1641==    by 0x82AD374: giop_thread_queue_process
(in /usr/lib/libORBit-2.so.0.1.0)
==1641==    by 0x82ADB4E: (within /usr/lib/libORBit-2.so.0.1.0)
==1641== 
==1641== 
==1641== 10,416,032 bytes in 325,501 blocks are still reachable in loss
record 104 of 107
==1641==    at 0x4C1FFAB: malloc (vg_replace_malloc.c:207)
==1641==    by 0x6C7763A: pvl_new_element
(in /usr/lib/libecal-1.2.so.7.2.0)
==1641==    by 0x6C776A1: pvl_push (in /usr/lib/libecal-1.2.so.7.2.0)
==1641==    by 0x6C6864C: icalparser_add_line
(in /usr/lib/libecal-1.2.so.7.2.0)
==1641==    by 0x6C68CB8: icalparser_parse
(in /usr/lib/libecal-1.2.so.7.2.0)
==1641==    by 0x6C68F20: icalparser_parse_string
(in /usr/lib/libecal-1.2.so.7.2.0)
==1641==    by 0x69DE5D6: e_cal_backend_cache_get_components
(e-cal-backend-cache.c:473)
==1641==    by 0xF4D20EA: synch_slave_loop (e-cal-backend-caldav.c:1259)
==1641==    by 0x8FDDCA3: g_thread_create_proxy (gthread.c:635)
==1641==    by 0x9A8C016: start_thread (pthread_create.c:297)
==1641==    by 0x9D665BC: clone (in /usr/lib/debug/libc-2.7.so)
==1641== 
==1641== 
==1641== 11,273,560 bytes in 281,839 blocks are still reachable in loss
record 105 of 107
==1641==    at 0x4C1FFAB: malloc (vg_replace_malloc.c:207)
==1641==    by 0x6C778DA: pvl_newlist (in /usr/lib/libecal-1.2.so.7.2.0)
==1641==    by 0x6C6A093: icalproperty_new_impl
(in /usr/lib/libecal-1.2.so.7.2.0)
==1641==    by 0x6C68617: icalparser_add_line
(in /usr/lib/libecal-1.2.so.7.2.0)
==1641==    by 0x6C68CB8: icalparser_parse
(in /usr/lib/libecal-1.2.so.7.2.0)
==1641==    by 0x6C68F20: icalparser_parse_string
(in /usr/lib/libecal-1.2.so.7.2.0)
==1641==    by 0x69DE5D6: e_cal_backend_cache_get_components
(e-cal-backend-cache.c:473)
==1641==    by 0xF4D20EA: synch_slave_loop (e-cal-backend-caldav.c:1259)
==1641==    by 0x8FDDCA3: g_thread_create_proxy (gthread.c:635)
==1641==    by 0x9A8C016: start_thread (pthread_create.c:297)
==1641==    by 0x9D665BC: clone (in /usr/lib/debug/libc-2.7.so)
==1641== 
==1641== 
==1641== 13,541,304 bytes in 241,809 blocks are still reachable in loss
record 106 of 107
==1641==    at 0x4C1FFAB: malloc (vg_replace_malloc.c:207)
==1641==    by 0x6C6A079: icalproperty_new_impl
(in /usr/lib/libecal-1.2.so.7.2.0)
==1641==    by 0x6C68617: icalparser_add_line
(in /usr/lib/libecal-1.2.so.7.2.0)
==1641==    by 0x6C68CB8: icalparser_parse
(in /usr/lib/libecal-1.2.so.7.2.0)
==1641==    by 0x6C68F20: icalparser_parse_string
(in /usr/lib/libecal-1.2.so.7.2.0)
==1641==    by 0x69DE5D6: e_cal_backend_cache_get_components
(e-cal-backend-cache.c:473)
==1641==    by 0xF4D20EA: synch_slave_loop (e-cal-backend-caldav.c:1259)
==1641==    by 0x8FDDCA3: g_thread_create_proxy (gthread.c:635)
==1641==    by 0x9A8C016: start_thread (pthread_create.c:297)
==1641==    by 0x9D665BC: clone (in /usr/lib/debug/libc-2.7.so)
==1641== 
==1641== 
==1641== 36,754,968 bytes in 241,809 blocks are still reachable in loss
record 107 of 107
==1641==    at 0x4C1FFAB: malloc (vg_replace_malloc.c:207)
==1641==    by 0x6C764A9: icalvalue_new_impl
(in /usr/lib/libecal-1.2.so.7.2.0)
==1641==    by 0x6C6166A: icalvalue_new_text
(in /usr/lib/libecal-1.2.so.7.2.0)
==1641==    by 0x6C769E2: icalvalue_new_from_string_with_error
(in /usr/lib/libecal-1.2.so.7.2.0)
==1641==    by 0x6C688BA: icalparser_add_line
(in /usr/lib/libecal-1.2.so.7.2.0)
==1641==    by 0x6C68CB8: icalparser_parse
(in /usr/lib/libecal-1.2.so.7.2.0)
==1641==    by 0x6C68F20: icalparser_parse_string
(in /usr/lib/libecal-1.2.so.7.2.0)
==1641==    by 0x69DE5D6: e_cal_backend_cache_get_components
(e-cal-backend-cache.c:473)
==1641==    by 0xF4D20EA: synch_slave_loop (e-cal-backend-caldav.c:1259)
==1641==    by 0x8FDDCA3: g_thread_create_proxy (gthread.c:635)
==1641==    by 0x9A8C016: start_thread (pthread_create.c:297)
==1641==    by 0x9D665BC: clone (in /usr/lib/debug/libc-2.7.so)

line #473 is calling icalparser_parse_string(), which parses a string
and builds a complex icalcomponent* structure, which is then to be
wrapped into an ECalComponent object and stashed into a list. The
ECalComponent's destructor is responsible for deallocating the
icalcomponent* structure.

Line 1259 of e-cal-backend-caldav.c falls (again) within static void
synchronize_cache().
synchronize_cache() attempts to match the GList of ECalComponent
obtained from the ecal backend cache with items retrieved from the
server (using caldav_server_list_objects). 

Initially, a hash table of all cached ECalComponent entries is built
(L1262-L1274), without incrementing the ECalComponent refcounts.
For each (server side) CalDAVObject, a match is attempted with the hash
table. 
    Each hit causes synchronize_object() to be called, in order to
replicate the remote state into the local ECalComponent. The
ECalComponent is also removed from the GList (and no refcount activity
happens) [**]
    Each miss causes a leak of the CalDAVObject (image of the remote),
as previously noted. The ECalComponent remains in both the GList and the
GHashTable.
At this point, the GList still contains all the ECalComponent for which
either no match from server side was found, or for which matches failed.
Each of these ECalComponent instances is removed from the backend cache,
and if a notification needs to be raised, it is raised. Finally, the
ECalComponent is unref'd.

In the end, both the GList and the GHash are destroyed. In my copy of
libglib2.0-0, neither is unreffing the contained values, since the hash
table is built with a NULL last parameter.

Sketch of a solution:
    * each addition to the hash table should g_object_ref(comp)
    * the hash table should be built with g_object_unref as its last
parameter
    * caldav_object_free(object, FALSE) should also be called in the
"object->status != 200" case.
    * the sobjs lists should be g_free()'d.


            -- Cyrille


Reply via email to