jputcu / serialport

Cross platform haskell library for using the serial port
Other
43 stars 36 forks source link

Non-blocking interface should be added #13

Closed bgamari closed 10 years ago

bgamari commented 12 years ago

As documented in issue #3, as of 9f1bca693b46be51b3652fb206b341e87d29b9a6 the serial device is opened with O_NONBLOCK to work around a quirk in OS X. This is a quite unsatisfactory result as it is now no longer possible to use the blocking model which is generally the default on a UNIX platform. For this reason, devices should be opened in blocking mode by default, in keeping with the common trend of the last 30 years.

That being said, there are perfectly good uses for O_NONBLOCK. Given that this flag can be set with fcntl after the fd has been opened, it may be that this is an orthogonal concern to serialport (excluding the OS X issue, the current workaround for which apparently requires O_NONBLOCK at time of open). There are a few options for dealing with this,

data Blocking = Block Int           -- ^ Block up to timeout when receiving a char in tenth of seconds
              | NonBlock       -- ^ Don't block
data SerialPortSettings = SerialPortSettings {
                      commSpeed    :: CommSpeed,   -- ^ baudrate
                      bitsPerWord  :: Word8,       -- ^ Number of bits in a word
                      stopb        :: StopBits,    -- ^ Number of stop bits
                      parity       :: Parity,      -- ^ Type of parity
                      flowControl  :: FlowControl, -- ^ Type of flowcontrol
                      blocking     :: Blocking     -- ^ Block or not
                  }
jputcu commented 12 years ago

What about using an OS X specific #define to tweak the behaviour? Then we could leave the interface as it is.

bgamari commented 12 years ago

Sorry for the long hiatus.

@jputcu, I'm not entirely sure what you are proposing, but if you are suggesting that the library open the device with O_NONBLOCK on OS X and without on other platforms, I would respond with a resounding no. Non-blocking and blocking IO are fundamentally different IO models. You cannot simply change this behind the library user's back and expect things not to break.

While I can't recall exactly, I believe the OS X quirk was that cu devices would block in open() until DCD is raised. I think the best way to avoid this sort of difficulty would be to open the device with O_NONBLOCK, and then clear the flag once open. This way we can eliminate the need for a non-blocking interface in serialport altogether (which I regard as pretty non-Haskellish, considering that we have cheap and ubiquitous threads).

acowley commented 11 years ago

I am using a fork of serialport where I open with O_NONBLOCK, then turn it off immediately (https://github.com/acowley/serialport). I haven't been able to find any other way around the issue on OS X. Is this change problematic for Linux users?

bgamari commented 11 years ago

It sounds like this workaround should be pretty harmless. That being said, I'll test next time I'm near a serial device,

bgamari commented 11 years ago

@acowley, your patch has no adverse effects in my Linux environment. It seems like it would be a worthwhile thing to have in the tree.

bgamari commented 10 years ago

Now since the OS X blocking issue is resolved it's not clear that there is a need for a non-blocking interface here. It's far easier to use threads. Closing.