Repository navigation
Updater: fall back to a 256 byte buffer when the sector buffer cannot be allocated - #9344
sanerdemirel wants to merge 6 commits into
Conversation
| void* operator new[](std::size_t size, const std::nothrow_t&) noexcept | ||
| { | ||
| if (logging && allocCount < maxLog) | ||
| { | ||
| allocLog[allocCount++] = size; | ||
| } | ||
| if (size == refuseA || size == refuseB) | ||
| { | ||
| return nullptr; | ||
| } | ||
| return malloc(size); | ||
| } |
There was a problem hiding this comment.
i believe this has to go to malloc, since we don't particularly care that this specific call is overloaded but only that some sized allocation get rejected.
also note it missed the linkage part, this gets pulled everywhere in the test runtime
thanks otherwise! i don't mind this here, but only in a way that valgrind actually works.
could just drop it too, in that case i'll create a separate pr for similar cases. it would have to create a separate 'mocking' allocator with stubs that we then could override through -Wl,--wrap=foobar
Replacing operator new[] leaks into the whole test runtime and does not work under valgrind. The allocation tests and the mockFreeHeap seam go; only the change in Updater.cpp stays.
|
Thanks for the review. You are right: replacing I have dropped the allocation-hook tests from this PR. What is left is the change in When your mocking allocator with |
Fixes #9342.
UpdaterClass::begin()picks a 4 KB write buffer when total free heap is above 8 KB, and a 256 byte buffer otherwise. It then makes one allocation. If the heap is fragmented, there can be more than 8 KB free but no free block of 4 KB. The allocation fails andbegin()returnsUPDATE_ERROR_OOM, although the update would work with 256 bytes.As suggested in the issue,
begin()now walks through{FLASH_SECTOR_SIZE, 256}and usesnew (std::nothrow)for each size. The first size that works is used. If both fail, it still reportsUPDATE_ERROR_OOM.The low-heap rule is unchanged: with 8 KB or less free, only 256 is tried, so the buffer does not take the last of the heap.
The diff is
cores/esp8266/Updater.cpponly, +7/-5. The 256 byte path was already used when the heap was low, so no code needs to learn about a new buffer size.Tests
This PR adds no new tests. An earlier version had host tests that replaced the nothrow
operator new[]for the whole test binary, to refuse chosen sizes. As discussed in the review, that is the wrong level, and under valgrind the hook is never called, so I dropped them. The fallback tests can follow on top of a mocking allocator that works under valgrind:begin()still succeeds with 256.begin()reportsUPDATE_ERROR_OOM, and the updater can be used again afterwards.Results on the current head, on Ubuntu 24.04 with g++ 13 and clang-format-18:
make FORCE32=0 D=1 testpasses: 89 test cases, 33214 assertions. The existing Updater host tests run against the changedbegin().make CI(-Werror, valgrind, coverage) passes: 0 errors, no leaks reported.tests/restyle.shwith clang-format-18 changes nothing.Not tested
begin().