tdlib / td

Cross-platform library for building Telegram clients
https://core.telegram.org/tdlib
Boost Software License 1.0
7.11k stars 1.44k forks source link

How to properly close TDLib instances without memory leak #2608

Closed micl2e2 closed 1 year ago

micl2e2 commented 1 year ago

After running valgrind's memcheck against the original example example/cpp/td_example, it detects memory leak, the reproduciable steps are:

# start
valgrind --tool=memcheck ./build/td_example

# after entering interative mode...
close  # press Enter
q # press Enter

# td_example now exits with 0...

# valgrind report
...
==43823== LEAK SUMMARY:
==43823==    definitely lost: 62 bytes in 2 blocks
==43823==    indirectly lost: 0 bytes in 0 blocks
...

, where we close before [q] quit, which might be the correct way to end the TDLib instance, but it seems not. There are still 62 bytes "Definitely lost" in one of my tests(the most common one, sometimes 80+ bytes, few times 90+ bytes). As per valgrind docs, this should be fixed otherwise causing memory leak.

Even with close action, the original example seems not strictly following the official guidelines, which suggests that the event authorizationStateClosed shall be the actual signal of TDLib instance closing.

Additionally, even though following the guideline, meaning our program exits only after authorizationStateClosed event received (my modified and simplified version of td_example.cpp implements it), that 62 bytes lost still exists. And the those lost positions are identical in both original one and my modified one, two 31-byte blocks, one starting from td::create_story_db_sync, the other starting from td::detail::LambdaPromise::set_value, the details are:

31 bytes in 1 blocks are definitely lost in loss record 6 of 8
   at 0x484282F: malloc (vg_replace_malloc.c:431)
   by 0x13EE1D3: tdsqlite3MemMalloc 
   by 0x13AAE4C: sqlcipher_mem_malloc 
   by 0x148494D: tdsqlite3_exec 
   by 0x1325297: td::SqliteDb::exec(td::CSlice) 
   by 0x1325C7D: td::SqliteDb::check_encryption() 
   by 0x1326C5B: td::SqliteDb::do_open_with_key(td::CSlice, bool, td::DbKey const&, int) 
   by 0x1327247: td::SqliteDb::open_with_key(td::CSlice, bool, td::DbKey const&, td::optional<int, true>) 
   by 0x1329373: td::SqliteDb::change_key(td::CSlice, bool, td::DbKey const&, td::DbKey const&) 
   by 0x5995B0: td::TdDb::init_sqlite(td::TdDb::Parameters const&, td::DbKey const&, td::DbKey const&, td::BinlogKeyValue<td::Binlog>&) 
   by 0x59BB49: td::TdDb::open_impl(td::TdDb::Parameters, td::Promise<td::TdDb::OpenedDatabase>&&) 
   by 0x59D16D: td::detail::LambdaPromise<td::Unit, td::TdDb::open(int, td::TdDb::Parameters, td::Promise<td::TdDb::OpenedDatabase>&&)::{lambda(td::Unit)#1}>::set_value(td::Unit&&) 

31 bytes in 1 blocks are definitely lost in loss record 7 of 8
   at 0x484282F: malloc (vg_replace_malloc.c:431)
   by 0x13EE1D3: tdsqlite3MemMalloc 
   by 0x13AAE4C: sqlcipher_mem_malloc 
   by 0x148494D: tdsqlite3_exec 
   by 0x1325297: td::SqliteDb::exec(td::CSlice) 
   by 0x1325C7D: td::SqliteDb::check_encryption() 
   by 0x1326C5B: td::SqliteDb::do_open_with_key(td::CSlice, bool, td::DbKey const&, int) 
   by 0x1327247: td::SqliteDb::open_with_key(td::CSlice, bool, td::DbKey const&, td::optional<int, true>) 
   by 0x1321683: std::_Function_handler<td::SqliteDb (), td::SqliteConnectionSafe::SqliteConnectionSafe(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, td::DbKey, td::optional<int, true>)::{lambda()#1}>::_M_invoke(std::_Any_data const&) 
   by 0x1323525: td::SqliteConnectionSafe::get() 
   by 0x10B81B8: std::_Function_handler<td::unique_ptr<td::StoryDbSyncInterface> (), td::create_story_db_sync(std::shared_ptr<td::SqliteConnectionSafe>)::StoryDbSyncSafe::StoryDbSyncSafe(std::shared_ptr<td::SqliteConnectionSafe>)::{lambda()#1}>::_M_invoke(std::_Any_data const&) 
   by 0x10B5566: td::create_story_db_sync(std::shared_ptr<td::SqliteConnectionSafe>)::StoryDbSyncSafe::get() 
levlam commented 1 year ago

You correctly close the instance. The data leaks inside SQLCipher code, so you can try to find the cause and report the issue to them, if it isn't fixed yet.

Anyway, given that < 100 bytes leaks per created and closed instance, it will take centuries to make the leak noticeable in a real app.

micl2e2 commented 1 year ago

Thanks for the clarification!

Thom123450 commented 1 year ago

Xin code trải nghiệm

Vào 23:20, Th 2, 18 thg 9, 2023 Michael Lee @.***> đã viết:

Closed #2608 https://github.com/tdlib/td/issues/2608 as completed.

— Reply to this email directly, view it on GitHub https://github.com/tdlib/td/issues/2608#event-10400235657, or unsubscribe https://github.com/notifications/unsubscribe-auth/A5AUF4W2E2HQBCXU7YNUIUTX3BYDFANCNFSM6AAAAAA44P2L7U . You are receiving this because you are subscribed to this thread.Message ID: @.***>