Opened 8 years ago

Closed 7 years ago

#8123 closed bug (fixed)

PANIC: object_cache: tried to free invalid object pointer

Reported by: beos_zealot Owned by: axeld
Priority: normal Milestone: R1
Component: System/Kernel Version: R1/Development
Keywords: slab deadbeef Cc:
Blocked By: Blocking:
Has a Patch: yes Platform: x86

Description

Updated local Haiku SVN repository and started building anyboot image:
jam -j2 -q @anyboot

after several minutes of building I got PANIC (attached pic: PANIC - object_cache - tried to free invalid object pointer.jpg)

Haiku gcc4 hrev43224
Intel Core 2
2 GB RAM (swap on)

Attachments (4)

PANIC - object_cache - tried to free invalid object pointer.jpg (737.5 KB) - added by beos_zealot 8 years ago.
deadbeef.jpg (397.7 KB) - added by beos_zealot 7 years ago.
reproduce.patch (860 bytes) - added by ahenriksson 7 years ago.
check_unused.patch (1.4 KB) - added by ahenriksson 7 years ago.

Download all attachments as: .zip

Change History (11)

comment:1 Changed 8 years ago by bonefish

Keywords: slab deadbeef added; PANIC object_cache tried to free invalid object pointer removed
Owner: changed from axeld to mmlr
Status: newassigned

Maybe mmlr is interested in looking into that. The stack trace suggests that the magazine that is being emptied was already freed.

Changed 7 years ago by beos_zealot

Attachment: deadbeef.jpg added

comment:2 Changed 7 years ago by beos_zealot

Second time encountered same PANIC (attached image: deadbeef.jpg) while building Haiku anyboot image.

Haiku gcc4 hrev43751

Changed 7 years ago by ahenriksson

Attachment: reproduce.patch added

Changed 7 years ago by ahenriksson

Attachment: check_unused.patch added

comment:3 Changed 7 years ago by ahenriksson

Has a Patch: set

comment:4 Changed 7 years ago by ahenriksson

I've encountered this as well, or at least something very similar. The problem is in the block cache, when a cached_block with is_dirty = true, discard = false, transaction = NULL and ref_count = 0 is added to the unused_blocks list. This can happen when a transaction is aborted, or when the block cache is used without a transaction.

When RemoveUnusedBlocks() free's a block with these properties, it will call BlockWriter::WriteBlock(), which eventually leads to the block being re-added to the list in _BlockDone(). When execution returns to RemoveUnusedBlocks(), the block is free'd. So at this point we have a free'd block in the unused_blocks list, waiting to cause a crash.

reproduce.patch contains code to reproduce the crash, and check_unused.patch is my attempt at fixing the problem. As far as I can tell, cached_block::unused basically means "is this block in unused_list", so checking for that tells _BlockDone() that it was called from RemoveUnusedBlocks() and should not re-add the block.

comment:5 Changed 7 years ago by anevilyak

Owner: changed from mmlr to axeld

comment:6 Changed 7 years ago by axeld

Great findings! Actually, your patch is not entirely correct, even though it helps ignoring the problem: when a block is without a transaction, it mustn't be dirty anymore.

It looks both cache_abort_transaction(), and cache_abort_sub_transaction() don't deal with this correctly. The latter even has some more problems, as it does not reset the transaction field when it should.

I'm currently working on a revised patch. Thanks a lot in any case!

comment:7 Changed 7 years ago by axeld

Resolution: fixed
Status: assignedclosed

Applied your patch in hrev44355 - please use git format-patch next time, as this makes it easier to attribute the change to you. I've made the additional changes in hrev44357 which hopefully solves the underlying issue.

Note: See TracTickets for help on using tickets.