-
Notifications
You must be signed in to change notification settings - Fork 415
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(inotify): watch arbitrary depth #5410
base: main
Are you sure you want to change the base?
fix(inotify): watch arbitrary depth #5410
Conversation
friendly ping @snowleopard |
@rgrinberg There is some logic in dune/src/dune_engine/fs_memo.ml Lines 59 to 89 in 8e155da
Is this not sufficient for you, i.e. are you hitting the |
Thanks for the pointer, we should get rid of that workaround now I suppose.
Yes, this is easy to hit. But also, note that the macos does not have this limitation at all. So this PR just addresses the inconsistency between the two backends. |
@rgrinberg Right, makes sense. Let's drop this workaround then. |
20f8ea0
to
dba7c8f
Compare
The workaround is gone. |
dba7c8f
to
a4879e3
Compare
ping @snowleopard |
Sorry, I'm too out of breath for reviewing subtle stuff like this. Need to find some calm time -- will try to review by end of week! |
@snowleopard this week perhaps? |
in | ||
Mutex.unlock inotify.mutex; | ||
( [ Event.Fs_memo_event (Fs_memo_event.create ~kind ~path) ] | ||
, Option.to_list to_scan ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to_scan
might as well be a list to avoid this to_list
.
match Table.mem inotify.awaiting_creation path with | ||
| false -> None | ||
| true -> | ||
Inotify_lib.add inotify.inotify (Path.to_string path); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The assumption here seems to be that the path
got created. Maybe worth adding an assert
about this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, it doesn't seem great that we're doing all this for every event, not just for events that correspond to path creations. I think we shoud refactor this logic so that inotify.awaiting_creation
and the associated mutex is only touched when necessary. (There should probably be a separate function that processes path creation events and returns a list of paths that need to be scanned.)
let processed, to_scan = | ||
process_inotify_event ~inotify event | ||
in | ||
loop (acc @ processed) (events @ scan_dirs to_scan) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The order of arguments in @
seems weird, almost guaranteeing quadratic complexity if we assume that acc
grows from a large number of small processed
lists. Should this be swapped?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Same for events
.)
let inotify = | ||
create_inotifylib_watcher ~inotify:inotify_decl ~sync_table ~scheduler | ||
in | ||
Fdecl.set inotify_decl |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a brief comment why this Fdecl
is needed?
| Unix.Unix_error (ENOENT, _, _) -> Error `Does_not_exist) | ||
() | ||
| Inotify { inotify; awaiting_creation; mutex } -> | ||
Mutex.lock mutex; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same architectural concern here: messing around with mutex
for every watch, even though most watches don't care about the awaiting_creation
logic, seems wrong.
let (_ : (_, _) result) = Table.add awaiting_creation p () in | ||
match Path.parent p with | ||
| None -> | ||
User_warning.emit |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should print something more informative here. My understanding is that we can only end up here if p
is the workspace root and it doesn't exist? I guess this can only mean that the user deleted the directory while Dune was running. If you agree that that's the only situation where we can reach this code path, let's just say this.
{| | ||
{ path = In_source_tree "e"; kind = "Created" } | ||
{ path = In_source_tree "e/1"; kind = "Created" } | ||
{ path = In_source_tree "e/1/2"; kind = "Created" } |}] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you also add a test where we move a whole tree (say, with 2 levels and 2 subdirectories in each node) into a watched place? I'd like to make sure we can correctly deal with moves and trees (in addition to creating sequences of nested paths as tested above).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, it's a good improvement but I'm a bit unhappy that we are polluting happy/typical code paths with unhappy logic -- can we structure the code in a way that makes it obvious that the mutex and friends are only needed for watching paths that don't exist?
Signed-off-by: Rudi Grinberg <[email protected]> ps-id: 38F4A728-5530-4539-AECD-259E16F44D40 Signed-off-by: Rudi Grinberg <[email protected]>
Signed-off-by: Rudi Grinberg <[email protected]>
and also make sure that we unlock on finalize to avoid dead locks Signed-off-by: Rudi Grinberg <[email protected]>
Signed-off-by: Rudi Grinberg <[email protected]>
Signed-off-by: Rudi Grinberg <[email protected]>
a4879e3
to
8018fab
Compare
This PR fixes the inotify backend to allow watching
x/y/z
even ify
(orx
) do not exist. The fix works by watching the topmost directory that exists and then adding more watches as descendants are created. After adding a watch, we rescan the directory (as per the manual) because some events might have already occurred in that directory.