Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion pkgs/watcher/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 1.1.4-wip

- Improve handling of subdirectories on Linux: ignore `PathNotFoundException`
due to subdirectory deletion during watch setup, instead of raising it on the
event stream.

## 1.1.3

- Improve handling of
Expand All @@ -6,7 +12,7 @@
events. But, the restart would sometimes silently fail. Now, it is more
reliable.
- Improving handling of directories that are created then immediately deleted on
Windows. Previously, that could cause a `PathNotfoundException` to be thrown.
Windows. Previously, that could cause a `PathNotFoundException` to be thrown.

## 1.1.2

Expand Down
15 changes: 11 additions & 4 deletions pkgs/watcher/lib/src/directory_watcher/linux.dart
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,17 @@ class _LinuxDirectoryWatcher
// top-level clients such as barback as well, and could be implemented with
// a wrapper similar to how listening/canceling works now.

// TODO(nweiz): Catch any errors here that indicate that the directory in
// question doesn't exist and silently stop watching it instead of
// propagating the errors.
var stream = Directory(path).watch();
var stream = Directory(path).watch().transform(
StreamTransformer<FileSystemEvent, FileSystemEvent>.fromHandlers(
handleError: (error, st, sink) {
// Directory might no longer exist at the point where we try to
// start the watcher. Simply ignore this error and let the stream
// close.
if (error is! PathNotFoundException) {
sink.addError(error, st);
}
},
));
_subdirStreams[path] = stream;
_nativeEvents.add(stream);
}
Expand Down
2 changes: 1 addition & 1 deletion pkgs/watcher/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: watcher
version: 1.1.3
version: 1.1.4-wip
description: >-
A file system watcher. It monitors changes to contents of directories and
sends notifications when files have been added, removed, or modified.
Expand Down
29 changes: 29 additions & 0 deletions pkgs/watcher/test/directory_watcher/shared.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:io' as io;
import 'dart:isolate';

import 'package:test/test.dart';
import 'package:test_descriptor/test_descriptor.dart' as d;
import 'package:watcher/src/utils.dart';

import '../utils.dart';
Expand Down Expand Up @@ -340,5 +343,31 @@ void sharedTests() {
events.add(isRemoveEvent('dir/sub'));
await inAnyOrder(events);
});

test('subdirectory watching is robust against races', () async {
// Make sandboxPath accessible to child isolates created by Isolate.run.
final sandboxPath = d.sandbox;
final dirNames = [for (var i = 0; i < 50; i++) 'dir$i'];
await startWatcher();

// Repeatedly create and delete subdirectories in attempt to trigger
// a race.
for (var i = 0; i < 10; i++) {
for (var dir in dirNames) {
createDir(dir);
}
await Isolate.run(() async {
await Future.wait([
for (var dir in dirNames)
io.Directory('$sandboxPath/$dir').delete(),
]);
});
}

writeFile('a/b/c/d/file.txt');
await inAnyOrder([
isAddEvent('a/b/c/d/file.txt'),
]);
});
});
}