ibraheemdev / too-many-web-servers

https://ibraheem.ca/posts/too-many-web-servers/
101 stars 7 forks source link

What does "fd == listener.as_raw_fd()" do exactly? #8

Closed jmevel closed 1 year ago

jmevel commented 1 year ago

Hi,

Still (slowly) following your blog post but there's a piece I don't understand in the multiplexed server section.

You are doing

// is the listener ready?
if fd == listener.as_raw_fd() {
   [...]
   // register the connection with epoll
   let event = Event::new(Events::EPOLLIN | Events::EPOLLOUT, fd as u64);
   epoll::ctl(epoll, EPOLL_CTL_ADD, fd, event).unwrap();
}

What does if fd == listener.as_raw_fd() do exactly? Obviously if fd and listener.as_raw_fd() were identical then this would work the same:

// register the connection with epoll
let event = Event::new(Events::EPOLLIN | Events::EPOLLOUT, listener.as_raw_fd() as u64);
epoll::ctl(epoll, EPOLL_CTL_ADD, listener.as_raw_fd(), event).unwrap();

But actually it doesn't. We get a crash with the following error message:

thread 'main' panicked at 'called Result::unwrap() on an Err value: Os { code: 17, kind: AlreadyExists, message: "File exists" }', src/main.rs:54:78

Which makes sense because we already added this file descriptor above the main loop

// add listener to epoll
let event = Event::new(Events::EPOLLIN, listener.as_raw_fd() as u64);
epoll::ctl(epoll, EPOLL_CTL_ADD, listener.as_raw_fd(), event).unwrap();

So how is this if fd == listener.as_raw_fd() working? I'm confused.

Thanks for your answer 🙏

ibraheemdev commented 1 year ago

You missed the line above registering the connection with epoll:

let fd = connection.as_raw_fd();
let event = Event::new(Events::EPOLLIN | Events::EPOLLOUT, fd as u64);
// ...

The fd == listener.as_raw_fd() check simply tells us if the event was for TCP listener readiness, i.e. an incoming connection, as opposed to a TCP connection becoming ready in the map.

jmevel commented 1 year ago

Ahhhh I missed the variable shadowing !!! Makes perfect sense now.

Thanks again !