Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: purgeStale sometimes gets stuck in an infinite loop #209

Closed
javiergonzalezGenially opened this issue Mar 10, 2022 · 6 comments
Closed

Comments

@javiergonzalezGenially
Copy link

We found out that since we updated to v7 sometimes lru-cache would get stuck inside the purgeStale function

(lame) test

const LRU = require("lru-cache");

const sleep = (m) => new Promise((r) => setTimeout(r, m));
jest.setTimeout(50000);

it("works", async () => {
  const expirationTime = 1;
  const accessCache = new LRU({
    max: 66000,
    ttl: expirationTime,
    ttlResolution: 100,
    updateAgeOnGet: true,
  });
  console.log("start");

  for (let i = 0; i < 600; i++) {
    // console.log(i);
    await sleep(10);
    const rnd = Math.random() * 3;
    const v = i % 10;

    if (rnd < 1) {
      accessCache.set(v, v);
    } else if (rnd < 2) {
      accessCache.get(v);
    } else {
      console.log("purge start");
      accessCache.purgeStale();
      console.log("purge end");
    }
  }

  console.log("end");
});

you will see it gets stuck in purge start

The solution seems to be to make the purgeStale function "cache" the items to delete and delete it after the rindexes iteration, or else it may get stuck in an infinite iteration

purgeStale () {
  const toDelete = [];
  for (const i of this.rindexes({ allowStale: true })) {
    if (this.isStale(i)) {
      toDelete.push(this.keyList[i]);
    }
  }

  toDelete.forEach(k => this.delete(k));

  return toDelete.length > 0
}
@sheepa
Copy link

sheepa commented Mar 10, 2022

I can confirm this bug.

@isaacs
Copy link
Owner

isaacs commented Mar 10, 2022

Ahh, yes, because delete changes the linked list order. Good catch and root cause. Will fix shortly.

isaacs added a commit that referenced this issue Mar 10, 2022
isaacs added a commit that referenced this issue Mar 10, 2022
@isaacs
Copy link
Owner

isaacs commented Mar 10, 2022

fixed on 7.4.3 by accident, on 7.4.4 on purpose 😬

@isaacs isaacs closed this as completed Mar 10, 2022
isaacs added a commit that referenced this issue Mar 10, 2022
isaacs added a commit that referenced this issue Mar 10, 2022
isaacs added a commit that referenced this issue Mar 10, 2022
isaacs added a commit that referenced this issue Mar 10, 2022
@isaacs
Copy link
Owner

isaacs commented Mar 10, 2022

backported to other 7.x versions

@palashkulsh
Copy link

im not able to get my head around why infinite loop leads to infinite getpid syscalls as shown nodejs/node#42277 . any ideas?

@isaacs
Copy link
Owner

isaacs commented Mar 17, 2023

@palashkulsh Idk, you'd have to ask them. LRUCache doesn't do any getpid() calls.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants