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

Support non-blocking operation #64

Open
detly opened this issue Jul 21, 2021 · 0 comments
Open

Support non-blocking operation #64

detly opened this issue Jul 21, 2021 · 0 comments

Comments

@detly
Copy link

detly commented Jul 21, 2021

I am using serial-rs on Linux (both Ubuntu and OpenWRT), so this mostly only applies to serial-unix.

I use the Calloop event loop for event-driven systems. Under the hood (on Linux), Calloop basically uses epoll() with whatever file descriptors it extracts from things that implement AsRawFd. The general contract of epoll() in edge-triggered mode (which is what I tend to use) is:

  • wait until epoll_await() tells you to write
  • try to write N bytes from a buffer
  • keep trying this until write() returns -1 and errno is EAGAIN
  • go back to epoll_await()

This relies on the fd being opened in non-blocking mode. In blocking mode, you will never get EAGAIN, write() will simply block until all bytes are written.

In tty.rs you do indeed open the fd as non-blocking. But very shortly after, you clear this flag. This makes it impossible to use serial and enjoy non-blocking writes.

So for example, if I try to write N bytes from a buffer, this call eventually comes down to your implementation of io::Write. You call ppoll() with the timeout and then attempt the write. But even if the timeout is zero, the write will potentially block until all bytes are written.

The workaround we have for this at the moment is to write one byte at a time. That way any time spent blocking on write() is quite short and potentially, but not always, detected beforehand by ppoll().

Versions: Rust 1.53, serial 0.4.0,
Tried on: Ubuntu 20.10 and 21.04, OpenWRT (ramips + musl).

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

No branches or pull requests

1 participant