private void AddDirectoryWatch(WatchedDirectory parent, string directoryName)
{
lock (SyncObj)
{
// The read syscall on the file descriptor will block until either close is called or until
// all previously added watches are removed. We don't want to rely on close, as a) that could
// lead to race conditions where we inadvertently read from a recycled file descriptor, and b)
// the SafeFileHandle that wraps the file descriptor can't be disposed (thus closing
// the underlying file descriptor and allowing read to wake up) while there's an active ref count
// against the handle, so we'd deadlock if we relied on that approach. Instead, we want to follow
// the approach of removing all watches when we're done, which means we also don't want to
// add any new watches once the count hits zero.
if (parent == null || _wdToPathMap.Count > 0)
{
Debug.Assert(parent != null || _wdToPathMap.Count == 0);
AddDirectoryWatchUnlocked(parent, directoryName);
}
}
}