)]}'
{
  "commit": "c3f354edc72f37cee1d8439c9e060d7f04eede6d",
  "tree": "febca7691a22b51619e46d0945dd97e9043d1efc",
  "parents": [
    "8d524e74d6c14d551b543e6e9d3ef62e9d676d68"
  ],
  "author": {
    "name": "Antonio Barone",
    "email": "syntonyze@gmail.com",
    "time": "Tue Jul 01 12:22:46 2025 +0200"
  },
  "committer": {
    "name": "Antonio Barone",
    "email": "syntonyze@gmail.com",
    "time": "Wed Jul 02 15:24:03 2025 +0200"
  },
  "message": "Lock reftable auto-refresh to ensure consistency\n\nEnsure that reftable auto-refresh operations, clearing the database\ncache and reloading the reftable stack are executed in an exclusive\ncritical section under lock. Previously, these steps were performed\nwithout an exclusive critical section, creating a window where\nconcurrent threads could interfere with each other.\n\nIn a race condition, one thread might clear the cache and before it had\na chance of reloading the stack, another thread could repopulate the\ncache with stale data, keeping a reference to the open BlockSource\nchannel to the underlying tables that are subsequently removed when the\nfirst thread reloads the stack.\n\nThe above race condition resulted in attempts to access closed resources\nand lead to ClosedChannelException errors.\n\nAs an example, consider the following scenario:\n\n* T0 - Thread-1 is executing auto-refresh and it clears the database\n       cache\n\n* T1 - The master branch moves forward (for any reason):\n         - A new refTable (`R_new`) file is created\n         - An existing refTable (`R_old`) file is deleted due to\n           auto-compaction.\n\n* T3 - Thread-2 repopulates the database cache before Thread-1 has had a\n       chance to reload the refTable stack.\n\n* T4 - Thread-1 finally reloads the refTable stack, causing the closing\n       of the BlockSource wrapping the removed `R_old` refTable file.\n\n* T5 - Thread-2 attempts to read from the already-closed `R_old`\n       BlockSource and the `j.n.c.ClosedChannelException` is thrown\n\nTo reproduce this problem, you can run a script created to craft this\nracing condition: I1e78e175cff.\n\nWhile such errors during concurrent execution might be expected and\ntolerable in isolation, the situation becomes more severe when the\n`RepositoryCache` is involved, as is the case with Gerrit.\n\nThe `FileReftableDatabase` instance is cached within the `Repository`\nobject. When a `BlockSource` is closed prematurely due to this race\ncondition, the dangling reference remains in memory until the cached\nRepository expires, which is one hour by default.\n\nThis means that, once the race occurs, the repository may be unable to\nperform any ref lookups for up to an hour, effectively causing a\nrepository outage.\n\nBy introducing a ReentrantLock around both operations, the refresh logic\nnow guarantees that concurrent readers and writers maintain a consistent\nview of the reftable state, eliminating the race condition.\n\nVerified by executing the script provided at I1e78e175cff and no\nexceptions are raised anymore.\n\nBug: jgit-130\nChange-Id: I6153528a7b2695115b670bda04d4d4228c1731e1\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "e9782e2e188fc29de446ac15bcc6e5c64c6af429",
      "old_mode": 33188,
      "old_path": "org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableDatabase.java",
      "new_id": "d5a060f06c52a69b9caa518dea233d97b367c96e",
      "new_mode": 33188,
      "new_path": "org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableDatabase.java"
    }
  ]
}
