microsoft / mimalloc

mimalloc is a compact general purpose allocator with excellent performance.
MIT License
10.57k stars 860 forks source link

Crash in MiMalloc 2.0.4 #518

Closed mm-p4 closed 2 years ago

mm-p4 commented 2 years ago

With these two settings, mimalloc 2.0.4 crashes. Both must be 1, if either are 0, the crash will not occur.

mi_option_reset_decommits from = 1 mi_option_page_reset from = 1

Exception thrown: write access violation. block was 0x5CEAC0D0080.

p4d.exe!mi_page_free_list_extend(mi_page_s const page, const unsigned int64 bsize, const unsigned int64 extend, mi_stats_s const stats) Line 549 C++ p4d.exe!mi_page_extend_free(mi_heap_s heap, mi_page_s page, mi_tld_s tld) Line 610 C++ [Inline Frame] p4d.exe!mi_page_init(mi_heap_s tld, mi_page_s ) Line 662 C++ p4d.exe!mi_page_fresh_alloc(mi_heap_s heap, mi_page_queue_s pq, unsigned __int64 block_size) Line 255 C++ [Inline Frame] p4d.exe!mi_page_fresh(mi_heap_s ) Line 264 C++ p4d.exe!mi_page_queue_find_free_ex(mi_heap_s heap, mi_page_queue_s pq, bool first_try) Line 709 C++ [Inline Frame] p4d.exe!mi_find_free_page(mi_heap_s ) Line 746 C++ p4d.exe!mi_find_page(mi_heap_s heap, unsigned int64 size) Line 835 C++ p4d.exe!_mi_malloc_generic(mi_heap_s heap, unsigned __int64 size) Line 861 C++ [Inline Frame] p4d.exe!mi_heap_malloc_small(mi_heap_s ) Line 83 C++ [Inline Frame] p4d.exe!mi_heap_malloc(mi_heap_s *) Line 101 C++ [Inline Frame] p4d.exe!mi_malloc(unsigned __int64) Line 119 C++ p4d.exe!mi_new(unsigned int64 size) Line 857 C++ p4d.exe!DbOpen::DbOpen(DbTable table, DbJournal jf, StrPtr partition) Line 49 C++ p4d.exe!DbQuery::GetDb(int i, DbLock2 mode) Line 608 C++ p4d.exe!DbPipeDb::DbPipeDb(DbQuery & q, int which, DbLock2 how, int scanCheck) Line 302 C++ [Inline Frame] p4d.exe!Config::ReadConfig(DmAccess ) Line 848 C++ p4d.exe!Config::LoadConfig(Config svrConfig, Rpc rh, DbTable tables, Enviro enviro, Options opts, Error e, DmAccess dma2, const StrPtr sId) Line 287 C++ p4d.exe!Rh::ReloadConfig(Error e) Line 810 C++ p4d.exe!BackgroundRh::Run(Error e) Line 5133 C++ p4d.exe!MultiThreader::NtThreadProc(void param) Line 313 C++ [Inline Frame] p4d.exe!invoke_thread_procedure(unsigned int()(void )) Line 91 C++ p4d.exe!thread_start<unsigned int (__cdecl)(void __ptr64)>(void const parameter) Line 115 C++ kernel32.dll!BaseThreadInitThunk() Unknown ntdll.dll!RtlUserThreadStart() Unknown

static mi_decl_noinline void mi_page_free_list_extend( mi_page_t const page, const size_t bsize, const size_t extend, mi_stats_t const stats) { MI_UNUSED(stats);

if (MI_SECURE <= 2)

mi_assert_internal(page->free == NULL); mi_assert_internal(page->local_free == NULL);

endif

mi_assert_internal(page->capacity + extend <= page->reserved); mi_assert_internal(bsize == mi_page_block_size(page)); void* const page_area = _mi_page_start(_mi_page_segment(page), page, NULL );

mi_block_t* const start = mi_page_block_at(page, page_area, bsize, page->capacity);

// initialize a sequential free list mi_block_t const last = mi_page_block_at(page, page_area, bsize, page->capacity + extend - 1); mi_block_t block = start; while(block <= last) { mi_block_t next = (mi_block_t)((uint8_t*)block + bsize); mi_block_set_next(page,block,next); <<<<< EXCEPTION block = next; } // prepend to free list (usually NULL) mi_block_set_next(page, last, page->free); page->free = start; }

page = 0x000005ceac000580 page->next 0x0 block = 0x000005ceac0d0080 block->next next = 0x000005ceac0d00c0 next->next

mi_option_show_errors from 0 to 0 mi_option_show_stats from 0 to 0 mi_option_verbose from 0 to 0 mi_option_eager_commit from 1 to 1 mi_option_eager_region_commit from 0 to 0 mi_option_reset_decommits from 0 to 1 <<< set to 1 mi_option_large_os_pages from 0 to 0 mi_option_reserve_huge_os_pages from 0 to 0 mi_option_reserve_huge_os_pages_at from -1 to -1 mi_option_reserve_os_memory from 0 to 0 mi_option_segment_cache from 0 to 0 mi_option_page_reset from 0 to 1 <<< set to 1 mioption.abandoned_page_reset from 0 to 0 mi_option_segment_reset from 0 to 0 mi_option_eager_commit_delay from 4 to 4 mi_option_allow_decommit from 1 to 1 mi_option_reset_delay from 25 to 25 mi_option_segment_decommit_delay from 500 to 500 mi_option_use_numa_nodes from 0 to 0 mi_option_limit_os_alloc from 0 to 0 mi_option_os_tag from 100 to 100 mi_option_max_errors from 16 to 16 mi_option_max_warnings from 16 to 16

daanx commented 2 years ago

Thank you for the report! However, in the v2.x versions the mi_option_reset_decommits should never be 1 -- it is a left-over from the 1.x versions and the new segment management is now always explicit.

I will remove the relevant code and option from the v2.x code base as we should never crash just because an option was set! Fix coming soon.

mm-p4 commented 2 years ago

Thanks for the reply. Unsetting reset decommits does prevent the crash.

Closing this case.

malkia commented 5 months ago

Hi! We have a similar crash, although in our case mi_option_page_reset is 0, but the other one is 1, from src/options.c

  { 1, UNINIT, MI_OPTION_LEGACY(purge_decommits,reset_decommits) },

Here is the crash


    ntdll.dll!NtDelayExecution()    Unknown Symbols loaded.
    KERNELBASE.dll!SleepEx()    Unknown Symbols loaded.
redacted
    mscoreei.dll!InternalUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *) Unknown Symbols loaded.
    KERNELBASE.dll!UnhandledExceptionFilter()   Unknown Symbols loaded.
    ntdll.dll!RtlUserThreadStart$filt$0()   Unknown Symbols loaded.
    ntdll.dll!__C_specific_handler()    Unknown Symbols loaded.
    ntdll.dll!RtlpExecuteHandlerForException()  Unknown Symbols loaded.
    ntdll.dll!RtlDispatchException()    Unknown Symbols loaded.
    ntdll.dll!KiUserExceptionDispatch() Unknown Symbols loaded.
>   mimalloc-flavor-fast.dll!mi_page_free_list_extend(mi_page_s * const page=0x0000004682000158, const unsigned __int64 bsize, const unsigned __int64 extend=0x0000000000000001, mi_stats_s * const stats=0x0000000000000000) Line 586  C   Symbols loaded.
    mimalloc-flavor-fast.dll!mi_page_extend_free(mi_heap_s * heap=0x0000000005c00000, mi_page_s * page=0x0000004682000158, mi_tld_s * tld) Line 650 C   Symbols loaded.
    [Inline Frame] mimalloc-flavor-fast.dll!mi_page_init(mi_heap_s * tld, mi_page_s *) Line 701 C   Symbols loaded.
    mimalloc-flavor-fast.dll!mi_page_fresh_alloc(mi_heap_s * heap=0x0000000065580000, mi_page_queue_s * pq=0x0000000065580ae8, unsigned __int64 block_size, unsigned __int64 page_alignment) Line 293   C   Symbols loaded.
    mimalloc-flavor-fast.dll!_mi_malloc_generic(mi_heap_s * heap=0x0000000065580000, unsigned __int64 size=0x0000000005ac0027, bool zero, unsigned __int64 huge_alignment=0x0000000000000000) Line 913  C   Symbols loaded.
    mimalloc-flavor-fast.dll!_mi_heap_malloc_zero_ex(mi_heap_s * heap, unsigned __int64 size=0x0000000005ac0027, bool zero, unsigned __int64 huge_alignment) Line 150   C   Symbols loaded.```

(Our mimalloc.dll version supports multiple build configuration ("flavors"), and this is `mimalloc-flavor-fast` would be the default "release" one)
malkia commented 5 months ago

We also have another thread crash the same way:

    ntdll.dll!NtDelayExecution()    Unknown Symbols loaded.
    KERNELBASE.dll!SleepEx()    Unknown Symbols loaded.
redacted
    mscoreei.dll!InternalUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *) Unknown Symbols loaded.
    KERNELBASE.dll!UnhandledExceptionFilter()   Unknown Symbols loaded.
    ntdll.dll!RtlUserThreadStart$filt$0()   Unknown Symbols loaded.
    ntdll.dll!__C_specific_handler()    Unknown Symbols loaded.
    ntdll.dll!RtlpExecuteHandlerForException()  Unknown Symbols loaded.
    ntdll.dll!RtlDispatchException()    Unknown Symbols loaded.
    ntdll.dll!KiUserExceptionDispatch() Unknown Symbols loaded.
>   mimalloc-flavor-fast.dll!mi_page_free_list_extend(mi_page_s * const page=0x0000004680000158, const unsigned __int64 bsize, const unsigned __int64 extend=0x0000000000000001, mi_stats_s * const stats=0x000000014173a054) Line 586  C   Symbols loaded.
    mimalloc-flavor-fast.dll!mi_page_extend_free(mi_heap_s * heap=0x0000000001100000, mi_page_s * page=0x0000004680000158, mi_tld_s * tld) Line 650 C   Symbols loaded.
    [Inline Frame] mimalloc-flavor-fast.dll!mi_page_init(mi_heap_s * tld, mi_page_s *) Line 701 C   Symbols loaded.
    mimalloc-flavor-fast.dll!mi_page_fresh_alloc(mi_heap_s * heap=0x000000013fb30000, mi_page_queue_s * pq=0x000000013fb30ae8, unsigned __int64 block_size, unsigned __int64 page_alignment) Line 293   C   Symbols loaded.
    mimalloc-flavor-fast.dll!_mi_malloc_generic(mi_heap_s * heap=0x000000013fb30000, unsigned __int64 size=0x0000000001002001, bool zero, unsigned __int64 huge_alignment=0x0000000000000000) Line 913  C   Symbols loaded.
    mimalloc-flavor-fast.dll!_mi_heap_malloc_zero_ex(mi_heap_s * heap, unsigned __int64 size=0x0000000001002001, bool zero, unsigned __int64 huge_alignment) Line 150   C   Symbols loaded.
malkia commented 5 months ago

And third one was still working:

>   mimalloc-flavor-fast.dll!mi_page_free_list_extend(mi_page_s * const page=0x000000467e000158, const unsigned __int64 bsize=0x0000000001100000, const unsigned __int64 extend=0x0000000000000001, mi_stats_s * const stats=0x000000014173a054) Line 586   C   Symbols loaded.
    mimalloc-flavor-fast.dll!mi_page_extend_free(mi_heap_s * heap=0x0000000001100000, mi_page_s * page=0x000000467e000158, mi_tld_s * tld) Line 650 C   Symbols loaded.
    [Inline Frame] mimalloc-flavor-fast.dll!mi_page_init(mi_heap_s * tld, mi_page_s *) Line 701 C   Symbols loaded.
    mimalloc-flavor-fast.dll!mi_page_fresh_alloc(mi_heap_s * heap=0x0000001731e20000, mi_page_queue_s * pq=0x0000001731e20ae8, unsigned __int64 block_size, unsigned __int64 page_alignment) Line 293   C   Symbols loaded.
    mimalloc-flavor-fast.dll!_mi_malloc_generic(mi_heap_s * heap=0x0000001731e20000, unsigned __int64 size=0x0000000001002001, bool zero, unsigned __int64 huge_alignment=0x0000000000000000) Line 913  C   Symbols loaded.
    mimalloc-flavor-fast.dll!_mi_heap_malloc_zero_ex(mi_heap_s * heap, unsigned __int64 size=0x0000000001002001, bool zero, unsigned __int64 huge_alignment) Line 150   C   Symbols loaded.
malkia commented 1 month ago

ping - we had another one recently - where instead of returning 0 from malloc/new - e.g. can't allocate - it crashes.

malkia commented 1 month ago

Actually just realized I haven't tried MIMALLOC_PURGE_DECOMMITS=0 (which is the same as MIMALLOC_RESET_DECOMMITS=0) in my branch - I'll try this and report back after some time to see if it fixes for me. I missed @mm-p4's message above.