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

A partial fix for issue #1191. Do not panic mio on sockstate error, i… #1215

Merged
merged 1 commit into from
Mar 1, 2020

Conversation

dtacalau
Copy link
Contributor

@dtacalau dtacalau commented Dec 11, 2019

…nstead keep the err sock states and just retry them later.

This is a partial fix for 0.7 because it just handles the errors, and makes the sockstates available next poll instead of panicking. Pushing the error to user is more complicated as it would require new api added. I'd suggest to leave this part until custom IOCP handlers are implemented and #1195 is merged.

@dtacalau dtacalau marked this pull request as ready for review December 11, 2019 17:32
@@ -122,7 +127,12 @@ impl SockState {
* events that the user is interested in. Therefore, cancel the pending
* poll operation; when we receive it's completion package, a new poll
* operation will be submitted with the correct event mask. */
self.cancel()?;
let result = self.cancel();
Copy link
Collaborator

Choose a reason for hiding this comment

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

I haven't been able to find any documentation on NtCancelIoFileEx (the system call made here), do you have a documentation @dtacalau?

I want to know what kind of errors can be returned here because maybe we can ignore some of them.

Copy link
Contributor Author

@dtacalau dtacalau Dec 12, 2019

Choose a reason for hiding this comment

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

Copy link
Collaborator

Choose a reason for hiding this comment

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

Always great when you're developing against an API for which you don't have docs, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

rhetorical question I guess :)

Copy link
Contributor

@kleimkuhler kleimkuhler left a comment

Choose a reason for hiding this comment

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

Overall looks good. I'd like some of these comments addressed, but should be a 👍 afterwards.

src/sys/windows/selector.rs Outdated Show resolved Hide resolved
src/sys/windows/selector.rs Outdated Show resolved Hide resolved
src/sys/windows/selector.rs Outdated Show resolved Hide resolved
src/sys/windows/selector.rs Show resolved Hide resolved
Copy link
Contributor

@kleimkuhler kleimkuhler left a comment

Choose a reason for hiding this comment

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

Sorry missed something in my first review.

src/sys/windows/selector.rs Outdated Show resolved Hide resolved
src/sys/windows/selector.rs Outdated Show resolved Hide resolved
@dtacalau
Copy link
Contributor Author

I've done a change in the logic of update_sockets_events. The following block should be done no matter if a sock update failed or not, because if we do it only on error then we end up with duplicates in the update_queue:

        update_queue.retain(|sock| {
            sock.lock().unwrap().has_error()
        });

I've also found another issue we need to address: reregister done on a sock which has_error will result in having the same socked added twice in the update queue. Will not result in a bug, just that we'll call update twice, 2nd call being useless. To fix this self.add_socket_to_update_queue(socket); has to be called only if sock.has_error is false.
@Thomasdezeeuw any idea how can I achieve this? I got into mutability issues, cannot move out of a lock, so I cannot check for has_error and add it to the queue at the while sock.lock is being held.

@kleimkuhler
Copy link
Contributor

@dtacalau I still need to familiarize more with the Windows impl, but could set_event do the check and return false if SockState.error is true? We hold the lock right before going into that block of code so it could just return early

@kleimkuhler
Copy link
Contributor

@dtacalau Also I would appreciate it for changes in general if you can not force push commits 🙂. It makes it difficult to review PRs. I like to be able to leave a review, and then when a review is re-requested I can see what changed since the last time.

When a force push happens, the "viewed already" cache resets and I don't have a way to tell what is new and what I've reviewed.

I wouldn't worry about the git log either because commits should be squashed in a PR.

@dtacalau
Copy link
Contributor Author

@dtacalau I still need to familiarize more with the Windows impl, but could set_event do the check and return false if SockState.error is true? We hold the lock right before going into that block of code so it could just return early

@kleimkuhler Yeah that would work, By changing set_event to return has_error we avoid double locking. Another way would be to check has_error under lock, like this sock.lock().unwrap().has_error():

if (sock.lock().unwrap().set_event(event)) {
                self.add_socket_to_update_queue(socket);
}
self.update_sockets_events_if_polling()?;

@dtacalau
Copy link
Contributor Author

@dtacalau Also I would appreciate it for changes in general if you can not force push commits .

Ok, got it, sorry for that.

@kleimkuhler
Copy link
Contributor

kleimkuhler commented Dec 16, 2019

@dtacalau Yea so we still want to call socket.set_sock_state(Some(sock)); after set_event it looks like. In that case, set_event could return false if error.is_some(), and then we only update based on that result. So something like:

let should_update = sock.lock().unwrap().set_event(event);
socket.set_sock_state(Some(sock));
if should_update {
    unsafe {
        self.add_socket_to_update_queue(socket);
        self.update_sockets_events_if_polling()?;
    }
}

Edit: That way, we aren't locking it multiple times

…error, instead keep the err sock states and just retry them later

Signed-off-by: Daniel Tacalau <dst4096@gmail.com>
@dtacalau
Copy link
Contributor Author

rebased on master

@kleimkuhler I'm not quite happy with the solution from #1215 (comment). It works but it feels like a hack conveniently modifying the return of set_event for this fix. What if we need it to return something else for another issue we might find :)?

I'm going to leave it as it is until I figure something cleaner. WDYT?

@Thomasdezeeuw Thomasdezeeuw merged commit 10df3e1 into tokio-rs:master Mar 1, 2020
@Thomasdezeeuw
Copy link
Collaborator

Thanks @dtacalau, sorry for the late review.

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.

3 participants