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)