From 973579e662da41344880a4ff4a558cd89c94e845 Mon Sep 17 00:00:00 2001 From: Seebs Date: Fri, 31 May 2019 16:17:06 -0500 Subject: [PATCH] on freeze, unmap mapped containers It turns out that calling syscall.Munmap() is a thing which can change any container holding a pointer into the mapped space, but which wouldn't detect frozen containers. So we need to copy storage for such things. This negates some of the memory wins of the rowcache code, but makes it not crashy. --- roaring/container_stash.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/roaring/container_stash.go b/roaring/container_stash.go index 46725238f..fe03f9d2e 100644 --- a/roaring/container_stash.go +++ b/roaring/container_stash.go @@ -256,11 +256,20 @@ func (c *Container) setMapped(mapped bool) { } // Freeze returns an unmodifiable container identical to c. This might -// be c, now marked unmodifiable, or might be a new container. +// be c, now marked unmodifiable, or might be a new container. If c +// is currently marked as "mapped", referring to a backing store that's +// not a conventional Go pointer, the storage may be copied. func (c *Container) Freeze() *Container { if c == nil { return nil } + // don't need to freeze + if c.flags&flagFrozen != 0 { + return c + } + // unmapOrClone should unmap-in-place because the existing + // container isn't frozen (or we'd already have returned it). + c = c.unmapOrClone() c.flags |= flagFrozen return c }