Opened 8 years ago

Closed 8 years ago

#9959 closed Patch - Bug Fix (fixed)

[PATCH] ringbuffer: Fix a deadlock in readahead

Reported by: Lawrence Rust <lvr@…> Owned by: danielk
Priority: minor Milestone: 0.25
Component: MythTV - General Version: Master Head
Severity: medium Keywords: ringbuffer deadlock
Cc: Ticket locked: no

Description

There is a potential deadlock in ringbuffer::run() due to violation of the lock acquisition hierarchy when it calls safe_read().

If an error is encountered in fileringbuffer::safe_read() then poslock is read locked prior to calling Seek() but run() has already read locked rbwlock which leads to a violation of the lock hierarchy rwlock->poslock->rbrlock->rbwlock.

This fix releases rbwlock prior to calling safe_read.

NB this bug also affects fixes/0.24

Attachments (2)

0001-ringbuffer-Fix-a-deadlock-in-readahead.patch (2.3 KB) - added by Lawrence Rust <lvr@…> 8 years ago.
9959-v2.patch (2.6 KB) - added by danielk 8 years ago.

Download all attachments as: .zip

Change History (6)

Changed 8 years ago by Lawrence Rust <lvr@…>

comment:1 Changed 8 years ago by danielk

Owner: set to danielk
Status: newaccepted

Changed 8 years ago by danielk

Attachment: 9959-v2.patch added

comment:2 Changed 8 years ago by danielk

Lawrence can you take a look at 9959-2.patch ? My concern is that with the lock undone during read_safe() the rbwpos could be changed during the read.. This was really already a problem because we unlocked rbwlock before we did the update, but I believe 9959-v2.patch might fix both problems by comparing rbwpos with rbwposcopy once we acquire the write lock.

comment:3 Changed 8 years ago by Lawrence Rust <lvr@…>

OK, I see what you're trying to do - it adds a level of security in case something changes rbwpos while rbwlock is released. However, I think that you're worrying unnecessarily. The only code that changes rbwpos is ResetReadAhead? (protected) and this is only called from Seek() (public) which obtains a rwlock write lock at entry, or the caller of Seek has done so. Any attempt to write lock rwlock will block until readahead is idle.

What you propose is absolutely safe and protects against future changes. I think the change is for the best.

comment:4 Changed 8 years ago by Github

Milestone: unknown0.25
Resolution: fixed
Status: acceptedclosed

Fixes #9959. This fixes a race deadlock in FileRingBuffer::safe_read(RemoteFile? *rf... and also makes sure we don't update rbwpos with read_return if rbspos has changed since we read in the data.

The first problem was discovered & fixed by Lawrence Rust. I discovered & fixed the other related problem when reviewing his patch.

Branch: master Changeset: 3733544bafeeb7f20bed1334e7f76b4581790429

Note: See TracTickets for help on using tickets.