Make handling of corrupt Windows file system watcher events more robust.

The reason for the intermittent corruptions still needs to be found.
This commit is contained in:
Sönke Ludwig 2019-02-22 21:29:18 +01:00
parent 157de1d3f5
commit a59e4b6455

View file

@ -135,10 +135,11 @@ final class WinAPIEventDriverWatchers : EventDriverWatchers {
while (result.length) { while (result.length) {
assert(result.length >= FILE_NOTIFY_INFORMATION._FileName.offsetof); assert(result.length >= FILE_NOTIFY_INFORMATION._FileName.offsetof);
auto fni = () @trusted { return cast(FILE_NOTIFY_INFORMATION*)result.ptr; } (); auto fni = () @trusted { return cast(FILE_NOTIFY_INFORMATION*)result.ptr; } ();
if (fni.NextEntryOffset > result.length) { auto fulllen = () @trusted { try return cast(ubyte*)&fni.FileName[fni.FileNameLength/2] - result.ptr; catch (Exception e) return size_t.max; } ();
if (fni.NextEntryOffset > result.length || fulllen > (fni.NextEntryOffset ? fni.NextEntryOffset : result.length)) {
import std.stdio : stderr; import std.stdio : stderr;
() @trusted { () @trusted {
try stderr.writeln("ERROR: Invalid directory watcher event received."); try stderr.writefln("ERROR: Invalid directory watcher event received: %s", *fni);
catch (Exception e) {} catch (Exception e) {}
} (); } ();
break; break;
@ -156,7 +157,23 @@ final class WinAPIEventDriverWatchers : EventDriverWatchers {
} }
ch.baseDirectory = slot.directory; ch.baseDirectory = slot.directory;
auto path = () @trusted { try return fni.FileName[0 .. fni.FileNameLength/2].map!(ch => dchar(ch)).to!string; catch (Exception e) assert(false, e.msg); } (); string path;
try {
() @trusted {
path = fni.FileName[0 .. fni.FileNameLength/2].map!(ch => dchar(ch)).to!string;
} ();
} catch (Exception e) {
import std.stdio : stderr;
// NOTE: sometimes corrupted strings and invalid UTF-16
// surrogate pairs occur here, until the cause of this is
// found, the best alternative is to ignore those changes
() @trusted {
try stderr.writefln("Invalid path in directory change: %(%02X %)", cast(ushort[])fni.FileName[0 .. fni.FileNameLength/2]);
catch (Exception e) assert(false, e.msg);
} ();
if (fni.NextEntryOffset > 0) continue;
else break;
}
auto fullpath = buildPath(slot.directory, path); auto fullpath = buildPath(slot.directory, path);
ch.directory = dirName(path); ch.directory = dirName(path);
if (ch.directory == ".") ch.directory = ""; if (ch.directory == ".") ch.directory = "";