[Nut-upsdev] [PATCH] disable nonblocking mode on serial port

Arjen de Korte nut+devel at de-korte.org
Sun Oct 5 20:39:49 UTC 2008


Citeren Jim Paris <jim at jtan.com>:

>> If you know that there should be room to write a single character in the
>> output buffer of the UART, this isn't unreasonable to expect. The delays
>> in ser_send_pace() should allow for plenty of time to empty even the
>> smallest buffer, so this will always be the case.
> That seems like a strange workaround to have to use, when the hardware
> and driver are perfectly capable of knowing when the buffer is
> actually empty, and just blocking (in case of !O_NONBLOCK) or
> providing a signal (through select) when it's actually OK to send.
> The whole serial_send_pace could potentially be discarded entirely --
> how many drivers actually need it because of slow UPS hardware,
> versus drivers that just need it to avoid EAGAIN?

The ser_send_pace() function is intended to work around buggy (read:  
broken) UPS hardware, not slow serial ports and/or operating systems  
that fail to properly provide I/O buffering. You'd be surprised how  
many UPS'es actually need this and choke if you send data too quickly.  
Note that most of this code dates back to when literally every system  
had RS-232 ports and this was basically the only available interface.

>>> One needs to at deal with EAGAIN.
>> No, we don't. This isn't the generic case for a POSIX write() command,
>> we know that we're dealing with a UART that must have at least room for a
>> single character.  If sufficient time has passed since the character was
>> written, EAGAIN is not a proper response from the USB to serial driver
> (even if POSIX allows it).
> Why would you purposely ignore POSIX just because you think you have
> valid assumptions?  If you follow POSIX, things will work regardless
> of whether you've assumed correctly.  Doing things right is not hard.

See above. Most of this code is tried and tested for many years  
already. We deliberately fail and retry, rather than wait for an  
answer that may never come. This is also documented in the developer  
documentation. Changing this, may work for you, but might break  
existing installations where we rely on this behaviour.

> You could be dealing with unusual USB->serial devices, as in my case.

We know (it's not that unusual by the way, problems with USB to serial  
converters not behaving like a 'true' serial port are not limited to  
NUT).

> USB bulk transfers have potentially unbounded latency due to bus
> conditions. Someone else might have a setup that includes forwarding
> the serial port through a TCP/IP link to another machine.  Why assume?

Because the whole purpose of using NUT is that you must have a  
reliable connection to the UPS. There is no point in monitoring a UPS  
if you don't have low (essentially zero) latency. If this means you  
can't use a USB to serial converter, you'd better find that out at the  
time you're trying to configure your setup, rather than when you're  
hit by a power outage. Yes, some people will not be able to use their  
USB to serial converter, but that's a price we must be willing to pay.

[...]

> So I will agree that with a more well-behaved serial port, the
> assumptions made in NUT are OK.  But I still think the behaviour is
> technically wrong and I would really like to see a select() with a
> timeout on the writes.  Would you consider a patch or should
> I just shelve this idea for now and stick with my alternate adapter?

I have considered using a select() here as well in the past. Coding  
this is futile since we only have one write() statement in serial.c. I  
even coded this a while back when I reworked serial.c (but never  
committed the code). The problem is in a different area. How long  
should we wait? Too short and you'd still fail miserably, too long and  
you risk breaking existing installations. Since the demand for fixing  
this is low, I don't consider changing this any time soon.

Now that UPS'es with USB interfaces are (becoming) more common, this  
is just a temporary problem. In a few years time, all UPS'es will come  
with a USB interface and this will be legacy code. Even if this means  
that some people will find that they can't use a specific USB to  
serial converter (like you), I care more about not breaking existing  
installations than religiously trying to follow POSIX.

Best regards, Arjen
-- 
Please keep list traffic on the list



More information about the Nut-upsdev mailing list