checkChanges(
os.remove.all(wd / "folder4"),
Set(
os.sub / "folder4",
os.sub / "folder4" / "nestedA",
os.sub / "folder4" / "nestedA" / "a.txt",
os.sub / "folder4" / "nestedB",
os.sub / "folder4" / "nestedB" / "b.txt"
)
)
delete folder4
event arrives before the delete folder4/nestedA
(or B) event. This causes the implementation to cancel the folder/nestedA
watch and that update is lost.
I take it back. Running something like:
declare -i i=0; while ./mill -i os.watch.jvm[2.13.4].test; do i=$((i+1)); echo $i; done
Produced this output:
[103/103] os.watch.jvm[2.13.4].test.test
-------------------------------- Running Tests --------------------------------
+ test.os.watch.WatchTests.singleFolder 5784ms
1
[103/103] os.watch.jvm[2.13.4].test.test
-------------------------------- Running Tests --------------------------------
+ test.os.watch.WatchTests.singleFolder 5786ms
2
[103/103] os.watch.jvm[2.13.4].test.test
-------------------------------- Running Tests --------------------------------
+ test.os.watch.WatchTests.singleFolder 5778ms
3
[103/103] os.watch.jvm[2.13.4].test.test
-------------------------------- Running Tests --------------------------------
+ test.os.watch.WatchTests.singleFolder 5786ms
4
[103/103] os.watch.jvm[2.13.4].test.test
...
+ test.os.watch.WatchTests.singleFolder 5783ms
50
[103/103] os.watch.jvm[2.13.4].test.test
-------------------------------- Running Tests --------------------------------
+ test.os.watch.WatchTests.singleFolder 5794ms
51
[103/103] os.watch.jvm[2.13.4].test.test
-------------------------------- Running Tests --------------------------------
X test.os.watch.WatchTests.singleFolder 3200ms
utest.AssertionError: assert(expectedChangedPaths == changedSubPaths)
expectedChangedPaths: Set[os.SubPath] = HashSet(folder4/nestedB, folder4/nestedA, folder4, folder4/nestedA/a.txt, folder4/nestedB/b.txt)
changedSubPaths: scala.collection.mutable.Set[os.SubPath] = HashSet(folder4/nestedA/a.txt, folder4/nestedB, folder4, folder4/nestedB/b.txt)
utest.asserts.Asserts$.assertImpl(Asserts.scala:30)
test.os.watch.WatchTests$.checkChanges$1(WatchTests.scala:52)
test.os.watch.WatchTests$.$anonfun$tests$3(WatchTests.scala:93)
test.os.TestUtil$.prep(TestUtil.scala:71)
test.os.watch.WatchTests$.$anonfun$tests$2(WatchTests.scala:7)
1 targets failed
os.watch.jvm[2.13.4].test.test test.os.watch.WatchTests test.os.watch.WatchTests.singleFolder
Question 1: consistency between MacOS and Linux. Removing the watched directory (an obvious corner-case) behaves differently on MacOS and Linux. What is the expectation? Maybe it should be documented as undefined behavior?
[Sample program] (https://github.com/utgheith/watch/blob/master/src/main/scala/main.scala)
MacOS
event
data
Linux
event
data/a
data/b
Here is a stress test that leads to failure in 3 native environments: MacOS, Ubuntu/ext4, Ubuntu/ZFS. There seem to be 2 separate issues:
(1) a race condition that causes the watch thread to die with FileNotFoundException.
(2) events get reordered leading to premature watch cancelation on some subdirectories
WatchService
only drops directory DELETE
events (at least in the stress tests I tried)DELETE
eventsDELETE
events for sub directories of moved directories:Once the call to watch returns, onEvent is guaranteed to receive a an event containing the path for:
- Every file or folder that gets created, deleted, updated or moved within the watched folders
- For copied or moved folders, the path of the new folder as well as every file or folder within it.
- For deleted or moved folders, the root folder which was deleted/moved, but without the paths of every file that was within it at the original location
I apologize for all the spam but here is a simple test that shows that the problem is in WatchService
. os.watch
is likely masking some of those issues in its implementation but not all.
https://github.com/utgheith/watch3/blob/master/src/main/scala/main.scala
It seems that readme.md
is using travis-ci badges instead of the github actions ones. Clicking on the build status goes back to a January build (telling me that the switch occurred around this time). Tried to submit a pull request that fixes that but it gets stuck and never runs the tests. This seems to be related to an issue that I don't fully understand but requires special privileges to deal with anyway. Here is a link:
https://github.community/t/expected-waiting-for-status-to-be-reported/16727