Skip to content
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

Add windows ReadDirectoryChanges support #39

Merged
merged 26 commits into from
Nov 29, 2015
Merged

Conversation

jmquigs
Copy link
Contributor

@jmquigs jmquigs commented Nov 18, 2015

Original code by @maurizi , with some fixes by me.

Fix #4

maurizi and others added 14 commits June 13, 2015 14:39
…nsmute on request pointer.

- This switches the main loop to alternate between waiting for action events and blocking on SleepEx.
The SleepEx block allows completion events to fire.
-  This also fixes a failed transmute in the completion callback.  Basically instead of using the request_p
casted to &mut c_void, we need to transmute it and pass that into ReadDirectoryChangesW.  Otherwise,
when the completion routine attempts to transmute it back, it will be crap.
- Still need to fix some todos, so this is still WIP.
…s closed

- Most of the other watchers don't panic on send failure
- Transmute converts them back into a droppable resource
- If these occur they are internal errors, so Generic seems sufficient
- Otherwise files can't be renamed/deleted!
- The file or directory must exist when watch is called, since we use its type to determine how to watch it.
- File watches are essentially emulated by watching the parent directory and excluding changes to anything but the target file.  This allows reuse of the ReadDirectoryChangesW API.
- Windows needs a special variant of this test to deal with its limitations.
- This also modifies validate_recv to return the event list, so that the calling test can check more properties
@maurizi
Copy link
Contributor

maurizi commented Nov 18, 2015

Great to see someone finish the work I started! 👏

@@ -0,0 +1,306 @@
extern crate libc;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems entirely unused.

@@ -6,7 +6,7 @@ authors = [
"Antti Keränen <detegr@gmail.com>",
"Gilbert Röhrbein <gilbert@ifsr.de>",
"Jorge Israel Peña <jorge.israel.p@gmail.com>",
"Michael Maurizi <mmaurizi@azavea.com>",
"Michael Maurizi <michael.maurizi@gmail.com>",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add yourself in there, too :)

- Allows final read callback to fire, so that we can destroy outstanding request memory
@passcod
Copy link
Member

passcod commented Nov 19, 2015

@maurizi @retep998 waiting on your approval/testing before merge :)

@jmquigs
Copy link
Contributor Author

jmquigs commented Nov 19, 2015

@passcod, I'm going to investigate an alternate fix for the shutdown memory leak that @retep998 found. The sleep I have there works for the common case, but if the completion routine isn't fired before sleep exits, it still leaks memory. So if you created lots of watchers on a busy system and then shut them down, you'd probably leak some memory.

It will probably be a couple days before I can get that fix in.

- This required adding a new channel to the watcher that allows the test to observe internal changes ("Meta Events")
- Each watcher now has a a semaphore that is used to indicate when the final completion routine is called (or a read failed)
- Also added some general error handling to make the code more robust in the face of deleted watch directories, etc
@jmquigs
Copy link
Contributor Author

jmquigs commented Nov 19, 2015

I made some good progress on that leak here: jmquigs@02bca44. I'm using semaphores to make sure that I wait for the final completion callback on each watcher. Its not part of this PR; might be better to have a separate PR since there are so many changes here already.

unsafe extern "system" fn handle_event(error_code: u32, _bytes_written: u32, overlapped: LPOVERLAPPED) {
// TODO: Use Box::from_raw when it is no longer unstable
let overlapped: Box<OVERLAPPED> = mem::transmute(overlapped);
let request: Box<ReadDirectoryRequest> = mem::transmute(overlapped.hEvent);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what the minimum Rust version is for this project, but Box::from_raw has been stabilized as of 1.4

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Latest stable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed it to Box::from_raw

// for our own purposes

let req_buf = request.buffer.as_mut_ptr() as *mut c_void;
let request_p: *mut c_void = mem::transmute(request);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be Box::into_raw

- Allows errors to be returned immediately, rather than on the event channel
- Use a semaphore to wake up the server so that watch doesn't have to block for up to 500ms
- Add a new metaevent to let unit test check this
@jmquigs
Copy link
Contributor Author

jmquigs commented Nov 21, 2015

I don't have any more pending changes for this PR. It would be nice to add a dedup to the windows watcher are some point (its kinda spammy with writes to same file, for instance), but that should wait for another PR.

@passcod
Copy link
Member

passcod commented Nov 23, 2015

@retep998 @maurizi Can either of you give the go-ahead for merging this?

@jmquigs
Copy link
Contributor Author

jmquigs commented Nov 25, 2015

@passcod, its fine if you aren't comfortable merging this. I'll keep the branch around in my fork anyway, since I need it for my project.

@passcod
Copy link
Member

passcod commented Nov 25, 2015

Oh, I am totally comfortable merging this, but I don't have either the expertise to assess whether it's good code nor the setup to test it (appveyor takes care of some of that, but still). I'll probably end up merging it if nobody chimes in to tell me not to in a little bit, but I still want to give time for @retep998 and/or @maurizi to give it a look over and give me a LGTM.

passcod added a commit that referenced this pull request Nov 29, 2015
@passcod passcod merged commit 7e87315 into notify-rs:master Nov 29, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants