mwindow: close LRU window properly Remove a wrong call to git_mwindow_close which caused a segfault if it ever did run. In that same piece of code, if the LRU was from the first wiindow in the list in a different file, we didn't update that list, so the first element had been freed. Fix these two issues. Signed-off-by: Carlos Martín Nieto <carlos@cmartin.tk>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
diff --git a/src/mwindow.c b/src/mwindow.c
index c126fa2..e53477e 100644
--- a/src/mwindow.c
+++ b/src/mwindow.c
@@ -116,25 +116,28 @@ void git_mwindow_scan_lru(
static int git_mwindow_close_lru(git_mwindow_file *mwf)
{
unsigned int i;
- git_mwindow *lru_w = NULL, *lru_l = NULL;
+ git_mwindow *lru_w = NULL, *lru_l = NULL, **list = &mwf->windows;
/* FIMXE: Does this give us any advantage? */
if(mwf->windows)
git_mwindow_scan_lru(mwf, &lru_w, &lru_l);
for (i = 0; i < ctl.windowfiles.length; ++i) {
- git_mwindow_scan_lru(git_vector_get(&ctl.windowfiles, i), &lru_w, &lru_l);
+ git_mwindow *last = lru_w;
+ git_mwindow_file *cur = git_vector_get(&ctl.windowfiles, i);
+ git_mwindow_scan_lru(cur, &lru_w, &lru_l);
+ if (lru_w != last)
+ list = &cur->windows;
}
if (lru_w) {
- git_mwindow_close(&lru_w);
ctl.mapped -= lru_w->window_map.len;
git_futils_mmap_free(&lru_w->window_map);
if (lru_l)
lru_l->next = lru_w->next;
else
- mwf->windows = lru_w->next;
+ *list = lru_w->next;
free(lru_w);
ctl.open_windows--;
@@ -167,7 +170,11 @@ static git_mwindow *new_window(git_mwindow_file *mwf, git_file fd, git_off_t siz
while(ctl.mapped_limit < ctl.mapped &&
git_mwindow_close_lru(mwf) == GIT_SUCCESS) {}
- /* FIXME: Shouldn't we error out if there's an error in closing lru? */
+ /*
+ * We treat ctl.mapped_limit as a soft limit. If we can't find a
+ * window to close and are above the limit, we still mmap the new
+ * window.
+ */
if (git_futils_mmap_ro(&w->window_map, fd, w->offset, (size_t)len) < GIT_SUCCESS)
goto cleanup;