You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@asterixdb.apache.org by "Wail Y. Alkowaileet (Jira)" <ji...@apache.org> on 2024/06/03 17:22:00 UTC
[jira] [Updated] (ASTERIXDB-3416) Buffer Cache could leak locks on read failures
[ https://issues.apache.org/jira/browse/ASTERIXDB-3416?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Wail Y. Alkowaileet updated ASTERIXDB-3416:
-------------------------------------------
Description:
{noformat}
public ICachedPage pin(long dpid, IBufferCacheReadContext context) throws HyracksDataException {
...
// Notify context page is going to be pinned
context.onPin(cPage); <---- COULD ACQUIRE A READ LOCK
// Resolve race of multiple threads trying to read the page from
// disk.
synchronized (cPage) {
if (!cPage.valid) {
try {
tryRead(cPage, context); <--- THIS COULD FAIL
cPage.valid = true;
} catch (Exception e) {
LOGGER.log(ExceptionUtils.causedByInterrupt(e) ? Level.DEBUG : Level.WARN,
"Failure while trying to read a page from disk", e);
throw e;
} finally {
if (!cPage.valid) {
unpin(cPage); <--- THE ISSUE IS HERE
}
}
}
}
} else {
cPage.valid = true;
}
....
return cPage;
} {noformat}
*context.onPin(page)* could acquire a read lock However, when *tryRead()* fails, the *finally* part unpins the page without using the proper context. Thus, the lock acquired by the calling *context.onPin(page)* will not be released by calling unpin(page) as the context isn't passed and a default context will be used.
was:
{noformat}
public ICachedPage pin(long dpid, IBufferCacheReadContext context) throws HyracksDataException {
...
// Notify context page is going to be pinned
context.onPin(cPage); <---- COULD ACQUIRE A READ LOCK
// Resolve race of multiple threads trying to read the page from
// disk.
synchronized (cPage) {
if (!cPage.valid) {
try {
tryRead(cPage, context); <--- THIS COULD FAIL cPage.valid = true;
} catch (Exception e) {
LOGGER.log(ExceptionUtils.causedByInterrupt(e) ? Level.DEBUG : Level.WARN,
"Failure while trying to read a page from disk", e);
throw e;
} finally {
if (!cPage.valid) {
unpin(cPage); <--- THE ISSUE IS HERE
}
}
}
}
} else {
cPage.valid = true;
}
....
return cPage;
} {noformat}
*context.onPin(page)* could acquire a read lock However, when *tryRead()* fails, the *finally* part unpins the page without using the proper context. Thus, the lock acquired by the calling *context.onPin(page)* will not be released by calling unpin(page) as the context isn't passed and a default context will be used.
> Buffer Cache could leak locks on read failures
> ----------------------------------------------
>
> Key: ASTERIXDB-3416
> URL: https://issues.apache.org/jira/browse/ASTERIXDB-3416
> Project: Apache AsterixDB
> Issue Type: Bug
> Components: STO - Storage
> Affects Versions: 0.9.10
> Reporter: Wail Y. Alkowaileet
> Assignee: Wail Y. Alkowaileet
> Priority: Blocker
> Fix For: 0.9.10
>
>
> {noformat}
> public ICachedPage pin(long dpid, IBufferCacheReadContext context) throws HyracksDataException {
> ...
> // Notify context page is going to be pinned
> context.onPin(cPage); <---- COULD ACQUIRE A READ LOCK
> // Resolve race of multiple threads trying to read the page from
> // disk.
> synchronized (cPage) {
> if (!cPage.valid) {
> try {
> tryRead(cPage, context); <--- THIS COULD FAIL
> cPage.valid = true;
> } catch (Exception e) {
> LOGGER.log(ExceptionUtils.causedByInterrupt(e) ? Level.DEBUG : Level.WARN,
> "Failure while trying to read a page from disk", e);
> throw e;
> } finally {
> if (!cPage.valid) {
> unpin(cPage); <--- THE ISSUE IS HERE
> }
> }
> }
> }
> } else {
> cPage.valid = true;
> }
> ....
> return cPage;
> } {noformat}
> *context.onPin(page)* could acquire a read lock However, when *tryRead()* fails, the *finally* part unpins the page without using the proper context. Thus, the lock acquired by the calling *context.onPin(page)* will not be released by calling unpin(page) as the context isn't passed and a default context will be used.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)