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
broke io::read/write out into non-buffering and buffering solutions #51
Conversation
more tweaks to make the tests pass, also made the return type uint instead of () so the customer doesn't have to go looking through the buffer for answers addressing issues 45, 46, and 47. Added re-registration via an IoEventContext into the event_loop. Supports both edge triggered and level triggered setups. Changed net::read and write to not use a loop.. added read_all and write_all to use them and perform the old behavior more updates, mostly to tests got all tests passing
I also added a close() function for TcpSocket, because sometime you want to close a socket without it going out of scope first :) |
} | ||
|
||
pub fn close(&self) -> MioResult<()> { | ||
os::close(&self.desc) |
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 that the self.desc
should be set to something equivalent to -1
.
A file descriptor number is reused by the kernel after closing it, so it is possible that a future read
on a closed TcpSocket get data from another connection.
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.
That's a good point. I'm not sure where this should happen, though because
net:: doesn't really know about file descriptors. Maybe it should go into
posix::
On Nov 15, 2014 9:20 AM, "Ayose Cazorla" notifications@github.com wrote:
In src/net.rs:
pub fn connect(&self, addr: &SockAddr) -> MioResult<()> {
debug!("socket connect; addr={}", addr);
// Attempt establishing the context. This may not complete immediately.
if try!(os::connect(&self.desc, addr)) {
// On some OSs, connecting to localhost succeeds immediately. In
// this case, queue the writable callback for execution during the
// next event loop tick.
debug!("socket connected immediately; addr={}", addr);
}
Ok(())
}
pub fn close(&self) -> MioResult<()> {
os::close(&self.desc)
I think that the self.desc should be set to something equivalent to -1.
A file descriptor number is reused by the kernel after closing it, so it
is possible that a future read on a closed TcpSocket get data from
another connection.—
Reply to this email directly or view it on GitHub
https://github.com/carllerche/mio/pull/51/files#r20402565.
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.
Maybe, the safest option is to not provide a tcp_socket.close()
.
If TcpSocket is stored in another struct, the user can use something like Option<TcpSocket>
, instead of just TcpSocket
. Thus, the socket can be closed with self.foo = None
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.
That seems like a lot of overhead and hassle for the purposes of avoiding accidentally re-using a socket that one has explicitly closed (e.g. probability near 0). I am for changing the fd to -2 in os::close() (such as posix)
I'll review the PR in more detail today, but quick question. What is a case where you would want to call (I used to think the same re: having a close fn, but I changed my mind as of now, so if you have a more specific example, I would love to see it). |
I've been thinking about this a lot today. I guess my problem with Rust doesn't suffer from this problem since drop() is called synchronously, All of the examples I can think of where I'd want to force-close a bunch of So consider me convinced. I can ditch the close functions.
|
Alright, I'm not dead! I will go over this in detail today. Promise |
@@ -8,6 +8,10 @@ authors = ["Carl Lerche <me@carllerche.com>"] | |||
|
|||
git = "https://github.com/carllerche/nix-rust" | |||
|
|||
[dependencies.time] | |||
|
|||
git = "https://github.com/rust-lang/time" |
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 pulled this in on master already.
As we discussed in IRC. IoEventCtx would not be part of the public API in favor of passing the components directly: pub fn register<H: IoHandle>(&mut self, io: &H, token: Token) -> MioResult<()>;
pub fn register_opt<H: IoHandle>(&mut self, io: &H, token: Token, interests: IoInterests, opts: PollOpt) -> MioResult<()>;
pub fn reregister<H: IoHandle>(&mut self, io: &H, token: Token, interests: IoInterests, opts: PollOpt) -> MioResult<()>; (not 100% sure if reregister takes PollOpt) |
I can't think of a case where I would want to register a function with the poller and not indicate at least Interest. |
Would a good default for interests not just be all possible interests? |
Not it's level triggered by default. It would spam the readable and
|
I would be OK w/ having the EventLoop::register require the interests. There should be some helpers though like |
SGTM.
|
superceded by #57 |
OK. Here is the pull request which addresses issues #45, #46, and #47. It is pretty large, the IoEventCtx plays a more important role in things, since re-registration is so common. I renamed to IoEventCtx and added the Token to it, to simplify the interface into the the register functions.
For an advanced example of how the event re-registration can actually help simplify a state machine, check out the revised test_echo_server.