Bug 148851 - Android Viewer crashes because it runs out of memory when scrolling up and down in Chinese Calc doc
Summary: Android Viewer crashes because it runs out of memory when scrolling up and do...
Status: RESOLVED FIXED
Alias: None
Product: LibreOffice
Classification: Unclassified
Component: Android Viewer (show other bugs)
Version:
(earliest affected)
7.4.0.0 alpha0+
Hardware: All All
: medium normal
Assignee: Michael Weghorn
URL:
Whiteboard: target:7.4.0
Keywords:
Depends on:
Blocks:
 
Reported: 2022-04-29 12:59 UTC by Michael Weghorn
Modified: 2022-04-29 19:14 UTC (History)
1 user (show)

See Also:
Crash report or crash signature:


Attachments
Sample file (16.05 KB, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet)
2022-04-29 12:59 UTC, Michael Weghorn
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Michael Weghorn 2022-04-29 12:59:42 UTC
Created attachment 179845 [details]
Sample file

This was originally reported on the dev mailing list, s. thread starting at
https://lists.freedesktop.org/archives/libreoffice/2022-April/088794.html

Steps to reproduce:

1) open attached document "test.xlsx" in Android Viewer
2) scroll down the document, then up again
3) repeat step 2 over and over again

Actual result:

At some point in time (in my case, I usually had to repeat step 2 about 2-10 times, depending on the device), the app crashes because it runs out of memory.

This is with git master as of commit 6c724e18c2af227c2ad865342531ff35b0d511ac.
Comment 1 Michael Weghorn 2022-04-29 13:06:43 UTC
In a memory profile created with perfetto's "heap_profile" tool, the xdictionary ctor clearly showed up as allocating memory that was not freed, easily more than 1GB after a while.

For the Chinese sample doc, it get's called when painting a tile with this backtrace:

> i18npool::xdictionary::xdictionary(char const*) xdictionary.cxx:69
> std::__ndk1::__unique_if<i18npool::xdictionary>::__unique_single std::__ndk1::make_unique<i18npool::xdictionary, char const (&) [3]>(char const (&) [3]) memory:3132
> i18npool::BreakIterator_zh::BreakIterator_zh() breakiterator_cjk.cxx:147
> ::i18npool_BreakIterator_zh_get_implementation(com::sun::star::uno::XComponentContext *, const com::sun::star::uno::Sequence<com::sun::star::uno::Any> &) registerservices.cxx:242
> decltype(std::__ndk1::forward<com::sun::star::uno::XInterface* (*&)(com::sun::star::uno::XComponentContext*, com::sun::star::uno::Sequence<com::sun::star::uno::Any> const&)>(fp)(std::__ndk1::forward<com::sun::star::uno::XComponentContext*>(fp0), std::__ndk1::forward<com::sun::star::uno::Sequence<com::sun::star::uno::Any> const&>(fp0))) std::__ndk1::__invoke<com::sun::star::uno::XInterface* (*&)(com::sun::star::uno::XComponentContext*, com::sun::star::uno::Sequence<com::sun::star::uno::Any> const&), com::sun::star::uno::XComponentContext*, com::sun::star::uno::Sequence<com::sun::star::uno::Any> const&>(com::sun::star::uno::XInterface* (*&)(com::sun::star::uno::XComponentContext*, com::sun::star::uno::Sequence<com::sun::star::uno::Any> const&), com::sun::star::uno::XComponentContext*&&, com::sun::star::uno::Sequence<com::sun::star::uno::Any> const&) type_traits:4353
> com::sun::star::uno::XInterface* std::__ndk1::__invoke_void_return_wrapper<com::sun::star::uno::XInterface*>::__call<com::sun::star::uno::XInterface* (*&)(com::sun::star::uno::XComponentContext*, com::sun::star::uno::Sequence<com::sun::star::uno::Any> const&), com::sun::star::uno::XComponentContext*, com::sun::star::uno::Sequence<com::sun::star::uno::Any> const&>(com::sun::star::uno::XInterface* (*&)(com::sun::star::uno::XComponentContext*, com::sun::star::uno::Sequence<com::sun::star::uno::Any> const&), com::sun::star::uno::XComponentContext*&&, com::sun::star::uno::Sequence<com::sun::star::uno::Any> const&) __functional_base:318
> std::__ndk1::__function::__alloc_func<com::sun::star::uno::XInterface* (*)(com::sun::star::uno::XComponentContext*, com::sun::star::uno::Sequence<com::sun::star::uno::Any> const&), std::__ndk1::allocator<com::sun::star::uno::XInterface* (*)(com::sun::star::uno::XComponentContext*, com::sun::star::uno::Sequence<com::sun::star::uno::Any> const&)>, com::sun::star::uno::XInterface* (com::sun::star::uno::XComponentContext*, com::sun::star::uno::Sequence<com::sun::star::uno::Any> const&)>::operator()(com::sun::star::uno::XComponentContext*&&, com::sun::star::uno::Sequence<com::sun::star::uno::Any> const&) functional:1527
> std::__ndk1::__function::__func<com::sun::star::uno::XInterface* (*)(com::sun::star::uno::XComponentContext*, com::sun::star::uno::Sequence<com::sun::star::uno::Any> const&), std::__ndk1::allocator<com::sun::star::uno::XInterface* (*)(com::sun::star::uno::XComponentContext*, com::sun::star::uno::Sequence<com::sun::star::uno::Any> const&)>, com::sun::star::uno::XInterface* (com::sun::star::uno::XComponentContext*, com::sun::star::uno::Sequence<com::sun::star::uno::Any> const&)>::operator()(com::sun::star::uno::XComponentContext*&&, com::sun::star::uno::Sequence<com::sun::star::uno::Any> const&) functional:1651
> std::__ndk1::__function::__value_func<com::sun::star::uno::XInterface* (com::sun::star::uno::XComponentContext*, com::sun::star::uno::Sequence<com::sun::star::uno::Any> const&)>::operator()(com::sun::star::uno::XComponentContext*&&, com::sun::star::uno::Sequence<com::sun::star::uno::Any> const&) const functional:1799
> std::__ndk1::function<com::sun::star::uno::XInterface* (com::sun::star::uno::XComponentContext*, com::sun::star::uno::Sequence<com::sun::star::uno::Any> const&)>::operator()(com::sun::star::uno::XComponentContext*, com::sun::star::uno::Sequence<com::sun::star::uno::Any> const&) const functional:2347
> cppuhelper::ServiceManager::Data::Implementation::doCreateInstance(com::sun::star::uno::Reference<com::sun::star::uno::XComponentContext> const&) servicemanager.cxx:705
> cppuhelper::ServiceManager::Data::Implementation::createInstance(com::sun::star::uno::Reference<com::sun::star::uno::XComponentContext> const&, bool) servicemanager.cxx:674
> cppuhelper::ServiceManager::createInstanceWithContext(rtl::OUString const&, com::sun::star::uno::Reference<com::sun::star::uno::XComponentContext> const&) servicemanager.cxx:1005
> non-virtual thunk to cppuhelper::ServiceManager::createInstanceWithContext(rtl::OUString const&, com::sun::star::uno::Reference<com::sun::star::uno::XComponentContext> const&) servicemanager.cxx:0
> i18npool::BreakIteratorImpl::createLocaleSpecificBreakIterator(rtl::OUString const&) breakiteratorImpl.cxx:596
> i18npool::BreakIteratorImpl::getLocaleSpecificBreakIterator(com::sun::star::lang::Locale const&) breakiteratorImpl.cxx:647
> i18npool::BreakIteratorImpl::nextWord(rtl::OUString const&, int, com::sun::star::lang::Locale const&, short) breakiteratorImpl.cxx:147
> non-virtual thunk to i18npool::BreakIteratorImpl::nextWord(rtl::OUString const&, int, com::sun::star::lang::Locale const&, short) breakiteratorImpl.cxx:0
> ImpEditEngine::WordRight(EditPaM const&, short) impedit2.cxx:1504
> ImpEditEngine::DoOnlineSpelling(ContentNode*, bool, bool) impedit4.cxx:2307
> EditEngine::CompleteOnlineSpelling() editeng.cxx:2393
> sc::SpellCheckContext::ensureResults(short, int) spellcheckcontext.cxx:339
> sc::SpellCheckContext::isMisspelled(short, int) const spellcheckcontext.cxx:219
> ScOutputData::LayoutStrings(bool, bool, ScAddress const&) output2.cxx:1633
> ScOutputData::DrawStrings(bool) output2.cxx:1470
> ScGridWindow::DrawContent(OutputDevice&, ScTableInfo const&, ScOutputData&, bool) gridwin4.cxx:920
> ScGridWindow::PaintTile(VirtualDevice&, int, int, int, int, long, long) gridwin4.cxx:1627
> ScModelObj::paintTile(VirtualDevice&, int, int, int, int, long, long) docuno.cxx:559
> non-virtual thunk to ScModelObj::paintTile(VirtualDevice&, int, int, int, int, long, long) docuno.cxx:0
> doc_paintTile(_LibreOfficeKitDocument*, unsigned char*, int, int, int, int, int, int) init.cxx:3478
> ::Java_org_libreoffice_kit_Document_paintTileNative(JNIEnv *, jobject, jobject, jint, jint, jint, jint, jint, jint) lokandroid.cxx:267
> art_quick_generic_jni_trampoline 0x000070fb4d19ffac
> art_quick_invoke_stub 0x000070fb4d194c95
> art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*) 0x000070fb4d21d67b
> art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*) 0x000070fb4d3a2c9d
> bool art::interpreter::DoCall<true, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x000070fb4d39dfc7
> void art::interpreter::ExecuteSwitchImplCpp<false, false>(art::interpreter::SwitchImplContext*) 0x000070fb4d1abfe6
> ExecuteSwitchImplAsm 0x000070fb4d1a2056
> art::interpreter::ExecuteSwitch(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool) 0x000070fb4d39c3ae
> art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool, bool) 0x000070fb4d394421
> art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*, art::JValue*) 0x000070fb4d39be9c
> bool art::interpreter::DoCall<true, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x000070fb4d39dfaf
> void art::interpreter::ExecuteSwitchImplCpp<false, false>(art::interpreter::SwitchImplContext*) 0x000070fb4d1acf96
> ExecuteSwitchImplAsm 0x000070fb4d1a2056
> art::interpreter::ExecuteSwitch(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool) 0x000070fb4d39c3ae
> art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool, bool) 0x000070fb4d394421
> art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*, art::JValue*) 0x000070fb4d39be9c
> bool art::interpreter::DoCall<true, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x000070fb4d39dfaf
> void art::interpreter::ExecuteSwitchImplCpp<false, false>(art::interpreter::SwitchImplContext*) 0x000070fb4d1acf96
> ExecuteSwitchImplAsm 0x000070fb4d1a2056
> art::interpreter::ExecuteSwitch(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool) 0x000070fb4d39c3ae
> art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool, bool) 0x000070fb4d394421
> art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*, art::JValue*) 0x000070fb4d39be9c
> bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x000070fb4d39ca8e
> void art::interpreter::ExecuteSwitchImplCpp<false, false>(art::interpreter::SwitchImplContext*) 0x000070fb4d1ad330
> ExecuteSwitchImplAsm 0x000070fb4d1a2056
> art::interpreter::ExecuteSwitch(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool) 0x000070fb4d39c3ae
> art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool, bool) 0x000070fb4d394421
> art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*, art::JValue*) 0x000070fb4d39be9c
> bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x000070fb4d39ca8e
> void art::interpreter::ExecuteSwitchImplCpp<false, false>(art::interpreter::SwitchImplContext*) 0x000070fb4d1abe50
> ExecuteSwitchImplAsm 0x000070fb4d1a2056
> art::interpreter::ExecuteSwitch(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool) 0x000070fb4d39c3ae
> art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool, bool) 0x000070fb4d394421
> art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*, art::JValue*) 0x000070fb4d39be9c
> bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x000070fb4d39ca8e
> void art::interpreter::ExecuteSwitchImplCpp<false, false>(art::interpreter::SwitchImplContext*) 0x000070fb4d1abe50
> ExecuteSwitchImplAsm 0x000070fb4d1a2056
> art::interpreter::ExecuteSwitch(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool) 0x000070fb4d39c3ae
> art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool, bool) 0x000070fb4d394421
> artQuickToInterpreterBridge 0x000070fb4d758b40
> art_quick_to_interpreter_bridge 0x000070fb4d1a013d
> art_quick_invoke_stub 0x000070fb4d194c95
> art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*) 0x000070fb4d21d67b
> art::JValue art::InvokeVirtualOrInterfaceWithJValues<art::ArtMethod*>(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, art::ArtMethod*, jvalue const*) 0x000070fb4d619e2f
> art::Thread::CreateCallback(void*) 0x000070fb4d679420
> __pthread_start(void*) 0x000070fe0146e58b
> __start_thread 0x000070fe01406d88
>
Comment 2 Michael Weghorn 2022-04-29 13:39:33 UTC
(In reply to Michael Weghorn from comment #0)
> Created attachment 179845 [details]
> Steps to reproduce:
> 
> 1) open attached document "test.xlsx" in Android Viewer
> 2) scroll down the document, then up again
> 3) repeat step 2 over and over again


Note that switching to the first tab in the sheet makes this easier to reproduce, that one has more rows.
Comment 3 Commit Notification 2022-04-29 19:11:36 UTC
Michael Weghorn committed a patch related to this issue.
It has been pushed to "master":

https://git.libreoffice.org/core/commit/d4370761421508522a29c5206aea6e538d71b342

tdf#148851 Unmap + close file again in xdictionary dtor

It will be available in 7.4.0.

The patch should be included in the daily builds available at
https://dev-builds.libreoffice.org/daily/ in the next 24-48 hours. More
information about daily builds can be found at:
https://wiki.documentfoundation.org/Testing_Daily_Builds

Affected users are encouraged to test the fix and report feedback.
Comment 4 Michael Weghorn 2022-04-29 19:13:54 UTC
With the commit from comment 3 in place, I didn't see any more crashes or unexpected memory usage increase when testing more with the sample doc and experimental mode *disabled*.

I can still reproduce a crash due to running out of memory with experimental mode *enabled*, though, which has a different root cause.

I have created a separate ticket to keep track of that: tdf#148854