Fix segfault in DirectoryWatcher.
This commit is contained in:
parent
d0a55ef374
commit
e88d2d1b4b
|
@ -563,21 +563,34 @@ struct DirectoryWatcher { // TODO: avoid all those heap allocations!
|
||||||
|
|
||||||
@safe:
|
@safe:
|
||||||
|
|
||||||
private struct Context {
|
private static struct Context {
|
||||||
Path path;
|
Path path;
|
||||||
bool recursive;
|
bool recursive;
|
||||||
Appender!(DirectoryChange[]) changes;
|
Appender!(DirectoryChange[]) changes;
|
||||||
LocalManualEvent changeEvent;
|
LocalManualEvent changeEvent;
|
||||||
|
|
||||||
|
void onChange(WatcherID, in ref FileChange change)
|
||||||
|
nothrow {
|
||||||
|
DirectoryChangeType ct;
|
||||||
|
final switch (change.kind) {
|
||||||
|
case FileChangeKind.added: ct = DirectoryChangeType.added; break;
|
||||||
|
case FileChangeKind.removed: ct = DirectoryChangeType.removed; break;
|
||||||
|
case FileChangeKind.modified: ct = DirectoryChangeType.modified; break;
|
||||||
|
}
|
||||||
|
this.changes ~= DirectoryChange(ct, Path(change.directory) ~ change.name.idup);
|
||||||
|
this.changeEvent.emit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private {
|
private {
|
||||||
WatcherID m_watcher;
|
WatcherID m_watcher;
|
||||||
Context m_context;
|
Context* m_context;
|
||||||
}
|
}
|
||||||
|
|
||||||
private this(Path path, bool recursive)
|
private this(Path path, bool recursive)
|
||||||
{
|
{
|
||||||
m_watcher = eventDriver.watchers.watchDirectory(path.toNativeString, recursive, &onChange);
|
m_context = new Context; // FIME: avoid GC allocation (use FD user data slot)
|
||||||
|
m_watcher = eventDriver.watchers.watchDirectory(path.toNativeString, recursive, &m_context.onChange);
|
||||||
m_context.path = path;
|
m_context.path = path;
|
||||||
m_context.recursive = recursive;
|
m_context.recursive = recursive;
|
||||||
m_context.changes = appender!(DirectoryChange[]);
|
m_context.changes = appender!(DirectoryChange[]);
|
||||||
|
@ -608,31 +621,24 @@ struct DirectoryWatcher { // TODO: avoid all those heap allocations!
|
||||||
*/
|
*/
|
||||||
bool readChanges(ref DirectoryChange[] dst, Duration timeout = Duration.max)
|
bool readChanges(ref DirectoryChange[] dst, Duration timeout = Duration.max)
|
||||||
{
|
{
|
||||||
|
if (timeout == Duration.max) {
|
||||||
|
while (!m_context.changes.data.length)
|
||||||
|
m_context.changeEvent.wait(Duration.max, m_context.changeEvent.emitCount);
|
||||||
|
} else {
|
||||||
SysTime now = Clock.currTime(UTC());
|
SysTime now = Clock.currTime(UTC());
|
||||||
SysTime final_time = now + timeout;
|
SysTime final_time = now + timeout;
|
||||||
while (!m_context.changes.data.length) {
|
while (!m_context.changes.data.length) {
|
||||||
m_context.changeEvent.wait(final_time - now, m_context.changeEvent.emitCount);
|
m_context.changeEvent.wait(final_time - now, m_context.changeEvent.emitCount);
|
||||||
if (m_context.changes.data.length) break;
|
now = Clock.currTime(UTC());
|
||||||
else now = Clock.currTime(UTC());
|
if (now >= final_time) break;
|
||||||
|
}
|
||||||
|
if (!m_context.changes.data.length) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_context.changes.data.length) return false;
|
|
||||||
dst = m_context.changes.data;
|
dst = m_context.changes.data;
|
||||||
m_context.changes = appender!(DirectoryChange[]);
|
m_context.changes = appender!(DirectoryChange[]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onChange(WatcherID, in ref FileChange change)
|
|
||||||
nothrow {
|
|
||||||
DirectoryChangeType ct;
|
|
||||||
final switch (change.kind) {
|
|
||||||
case FileChangeKind.added: ct = DirectoryChangeType.added; break;
|
|
||||||
case FileChangeKind.removed: ct = DirectoryChangeType.removed; break;
|
|
||||||
case FileChangeKind.modified: ct = DirectoryChangeType.modified; break;
|
|
||||||
}
|
|
||||||
m_context.changes ~= DirectoryChange(ct, Path(change.directory) ~ change.name.idup);
|
|
||||||
m_context.changeEvent.emit();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue