Search code examples
exceptionscopedmmap

MmFile Empty Files throws Exception in Destructor


I'm having trouble getting MmFile to work in a directory scanning algorithm.

When I'm stress-testing it as follows

foreach (dent; dirEntries(..)) {
    const size_t K = ...;
    const ulong size = ...;
    scope auto mf = new MmFile(dent.name, MmFile.Mode.read, size, null, win)  
}

I can't find a combination of size and win that works for all cases when reading data.

When I set

const size = 0;
const win = 64*1024; 

the length gets calculated correctly.

But when dent.name is an existing empty file it crashes in the destruction of the MMFile throwing a

 core.exception.FinalizeError...std.exception.ErrnoException@std.mmfile.d(490): munmap failed (Invalid argument).

And I can't recover this error by catching core.exception.FinalizeError because its thrown in the destructor. I haven't tried

try { delete mm; } catch (core.exception.FinalizeError) { ; /* pass */}

Maybe that works.

Is this the default behavior when calling mmap in C on existing empty files?

If so I think that MmFile should check for this error during construction.

The except gets thrown also when I replace scope with an explicit delete.

For now I simply skip calling MmFile on empty files.


Solution

  • It sounds like a bug to me for MmFile to barf on empty files regardless of what mmap itself does. Please report it.

    On a side note, I'd advise against using either scope or delete, as they're going to be removed from the language, because they're both unsafe. std.typecons.scoped replaces scope in this context if you want to do that (though it's still unsafe). And as for delete, destroy will destroy the object without freeing its memory, and core.memory can be used to free memory if you really want to, but in general, if you want to be worrying about freeing memory, then you should be manually managing your memory (with malloc and free and possibly emplace) and not using the GC at all.