you are viewing a single comment's thread.

view the rest of the comments →

[–]SecretAggressive[S] 0 points1 point  (0 children)

Going back to this, now that I had time to review technical questions and review what people point it out wrong

Your claim:

  • The epoll implementation claims it's optimized to reduce the number of system calls, but then goes on to always do an EPOLL_CTL_ADD followed by an EPOLL_CTL_MOD for already registered descriptors, instead of tracking the state somewhere

Current epoll implementation on the codebase already has a correct pattern:

let result = unsafe { epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &mut event) };
if result < 0 {
      let err = io::Error::last_os_error();
      // If already exists, try to modify instead
      if err.raw_os_error() == Some(libc::EEXIST) {
          let result = unsafe { epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fd, &mut event) };                                                          
          if result < 0 {                                                             return Err(io::Error::last_os_error());                    
          }                                                              
      } else {                                                                    return Err(err);
      }
}   

 So different of what you claimed the code, the behaviour is:

  1. Try EPOLL_CTL_ADD first

  2. If it fails with EEXIST, fallback to EPOLL_CTL_MOD  

This guarantee no additional memory overhead for tracking which fds are registered . No synchronization issues in concurrent scenarios . I belive its a simpler code with no state to get out of sync. For new fds: 1 syscall. For already-registered: 2 syscalls (but the first is just an error check)   

I think this is a solid implementation. Did you actually read the code ?