Coder Social home page Coder Social logo

Comments (12)

LubosD avatar LubosD commented on September 4, 2024

Your suggestion unfortunately leads to the "resource temporarily unavailable" error when using bufio.ReadString('\n'), but in general, the fact that Read() cannot be interrupted is very bad.

from go-serial.

nkovacs avatar nkovacs commented on September 4, 2024

That's the EAGAIN error which should be caught by poll, and it shouldn't matter if you're using bufio.ReadString or just plain Read: https://github.com/golang/go/blob/release-branch.go1.12/src/internal/poll/fd_unix.go#L168
What operating system are you using? Maybe the runtime failed to initialize polling on the file (https://github.com/golang/go/blob/release-branch.go1.12/src/os/file_unix.go#L156), but there's no easy way to detect that.

from go-serial.

LubosD avatar LubosD commented on September 4, 2024

@nkovacs The app I'm writing is for Linux/arm (Raspberry Pi).

I wasn't aware that Raspbian contains Go 1.7.4 (almost 3 years old), so I updated to Go 1.12.4 and there I get the expected behavior when I add syscall.SetNonblock(int(file.Fd()), true) into my own code. Thanks!

from go-serial.

nkovacs avatar nkovacs commented on September 4, 2024

The poller was implemented for files in Go 1.9. One option is to use build tags and then use blocking mode in Go <1.9, but then Close won't work and will probably lead to a race condition as well. To make it work properly, you would have to wrap Read and Close, put a mutex in them, use non-blocking mode, vmin=0 and vtime>0, and if you get an EAGAIN, repeat the read (while letting Close interrupt it). This would waste cpu time of course, and Close would hang for up to vtime.

There's also the issue that we're assuming polling will always be available. If the poller fails to initialize, the file is not put into non-blocking mode (https://github.com/golang/go/blob/release-branch.go1.12/src/os/file_unix.go#L156), but since this package calls os.OpenFile with O_NONBLOCK, the file will be in non-blocking mode anyway, so there's no way to detect whether the poller init succeeded.

from go-serial.

chenwaichung avatar chenwaichung commented on September 4, 2024

@nkovacs Thank you for sharing the solution

from go-serial.

chmorgan avatar chmorgan commented on September 4, 2024

I've forked at GitHub.com/chmorgan/go-serial2 btw

I'm seeing this issue on my test target. Should there be an option to be blocking vs. non-blocking? I'm not super familiar with the poller support. It seems super helpful to support non-blocking reads as well, we can't expect data to be returned all of the time.

from go-serial.

nkovacs avatar nkovacs commented on September 4, 2024

From the perspective of your program, the read will still be blocking (with Go 1.9+), because the poller will handle all that (while the file is actually in non-blocking mode). That's the ideal situation, and there should be no reason to use blocking mode.

The main issue is that this package calls os.OpenFile with syscall.O_NONBLOCK, which unfortunately does two, separate things: it prevents the open from blocking for a long time and it sets the non-blocking flag. And because the non-blocking flag is set, this package cannot detect if Go's poller was successfully enabled for the file by checking if OpenFile itself set the flag.

You could call OpenFile without syscall.O_NONBLOCK, and let stdlib handle it, then check whether the non-blocking flag is set on the file (indicating the poller successfully initialized on the file), and restore it if needed after calling Fd (because Fd sets it to blocking mode). If the poller failed, then there's not much that can be done. You could implement a workaround like I described in my previous comment, or you could just deal with Read not being interruptible with Close (if you don't need to Close during the lifetime of your program, you won't get goroutine leaks, for example).

Unfortunately, calling OpenFile without syscall.O_NONBLOCK might lead to the open blocking for a long time, and I don't know under which circumstances it would happen. So another option is to always put the file into non-blocking mode (like my fork), and wrap Read/Write and handle EAGAIN yourself, in case the poller failed (Go <1.9 or unsupported architecture or whatever other reason).

from go-serial.

chmorgan avatar chmorgan commented on September 4, 2024

@nkovacs you'd recommend I pull in nkovacs@a726144 and nkovacs@73fc76f then?

In terms of usage should we update the example to make use of the poller? I'm not familiar with that module but it looks like great functionality to have when working with fds.

from go-serial.

chmorgan avatar chmorgan commented on September 4, 2024

@nkovacs and I think its ok to assume Go >1.9 at this point, at least I'm not excited about adding support for such old versions at the moment. Someone else is welcome to though :-)

from go-serial.

nkovacs avatar nkovacs commented on September 4, 2024

Yes, I think using non-blocking mode with the poller is the way to go.
You can assume Go > 1.9, the issue is that the poller might not initialize in certain cases, but I don't know how common that is. I haven't had any problems on a Raspberry Pi.

from go-serial.

chmorgan avatar chmorgan commented on September 4, 2024

Ahh very good!

I’ll merge those changes this afternoon. I’m collecting all of the good fixes to the library so they are in one maintained repo. If you have any other suggestions I’d love to hear them.

from go-serial.

chmorgan avatar chmorgan commented on September 4, 2024

Thanks @nkovacs, changes merged into the go-serial2 fork, https://github.com/chmorgan/go-serial2

from go-serial.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.