EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  <20232024  Index 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  <20232024 
<== Date ==> <== Thread ==>

Subject: Re: asynInterposeEos/StreamDevice: "read from low-level driver returned 1" and EAGAIN/EWOULDBLOCK
From: Zimoch Dirk via Tech-talk <tech-talk at aps.anl.gov>
To: "erico.rolim at lnls.br" <erico.rolim at lnls.br>, "tech-talk at aps.anl.gov" <tech-talk at aps.anl.gov>
Date: Wed, 5 Apr 2023 14:37:38 +0000
Hi Érico,

StreamDevice expects an error when reading to flush the input and does not
complain. But I am not so sure if asynOctet finds it "normal" to get a timeout
error when pasynUser->timeout == 0. Maybe you are right and it should expect
that and not print a warning in that case.

Dirk

On Wed, 2023-04-05 at 14:12 +0000, Érico Nogueira Rolim via Tech-talk wrote:
> Hi!
> 
> I am assisting with development of an IOC for a custom device that speaks SCPI over TCP, using StreamDevice and drvAsynIPPortConfigure. We were investigating how to detect that the device had been disconnected or turned off, for which we found a solution by using an asynRecord, along with the disconnectOnReadTimeout option, as suggested in [1].
> 
> However, while debugging these options, we enabled WARNINGS with asynSetTraceMask for our port, and were faced with the following warning:
> 
> 2023/04/04 17:32:32.122 BPMRFFE read from low-level driver returned 1
> 
> Investigating this warning message, I found it belonged to the asynInterposeEos interface, which I understand is what StreamDevice uses to handle its InTerminator.
> 
> For a better picture of our setup, the protocol file contains:
> 
> OutTerminator
>  = CR LF; InTerminator
>  = CR LF;
> inPIDTdAC
>  { out
>  "GET:PID:Td:AC?"; in
>  "%f"; }
> And the IOC running under strace (with some filtering enabled) looked like:
> 
> [pid
>  1310] poll([{fd=4, events=POLLOUT}], 1, 100) = 1 ([{fd=4, revents=POLLOUT}])  [pid
>  1310] sendto(4, "GET:PID:Td:AC?\r\n", 16, 0, NULL, 0) = 16 [pid
>  1310] poll([{fd=4, events=POLLIN}], 1, 1000) = 1 ([{fd=4, revents=POLLIN}])  [pid
>  1310] recvfrom(4, "0", 2048, 0, NULL, NULL) = 1 [pid
>  1310] poll([{fd=4, events=POLLIN}], 1, 100) = 1 ([{fd=4, revents=POLLIN}])  [pid
>  1310] recvfrom(4, "\r\n", 2048, 0, NULL, NULL) = 2 [pid
>  1310] poll([{fd=4, events=POLLIN}], 1, 1) = 0 (Timeout) [pid
>  1310] recvfrom(4, 0x561122ff95f0, 2048, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
> 2023/04/04
>  17:32:32.122 BPMRFFE read from low-level driver returned 1
> 
> In reading back the strace, we realized a few things:
> - The drvAsynIPPort code called recv() even when poll() returned a timeout, which seems non-ideal. However, looking at the code [2], it would seem to have been done to simplify the case for systems that don't support poll (nor select, seeing as asyn includes an emulation of poll based on select). Is that correct?
> - The conditional in [3] is used to determine if we should disconnect from the device. It seems to rely on EWOULDBLOCK being the same as EAGAIN (since recv/recvfrom can return either of them [4]), which is not a guarantee -- though I don't know if it's actually the case for any platform. I wouldn't be surprised if a lot of code (in general and EPICS code specifically) relies on this assumption, but the Linux manuals recommend against it explicitly as well [5] (under ERRORS).
> - asynInterposeEos's readIt is calling the underlying IPPort's read() function even though it should have matched with the end of string already (rereading [6] made me realize this happens because of StreamDevice's input flushing); this makes it so it returns asynTimeout to StreamDevice, which I assume deals with it just fine. However, since it's flushing the input with pasynUser->timeout=0, does it make sense for the "read from low-level driver returned 1" message to be a warning? It can easily pollute the warning output if one has a lot of SCAN records... Perhaps the message can be disabled or turned into an ASYN_TRACE_FLOW if pasynUser->timeout==0 && status==asynTimeout ?
> 
> [1] https://epics.anl.gov/tech-talk/2019/msg00297.php
> [2] https://github.com/epics-modules/asyn/blob/891c1f17860a82603eeceb84767975e8dd005218/asyn/drvAsynSerial/drvAsynIPPort.c#L758
> [3] https://github.com/epics-modules/asyn/blob/891c1f17860a82603eeceb84767975e8dd005218/asyn/drvAsynSerial/drvAsynIPPort.c#L799
> [4] https://pubs.opengroup.org/onlinepubs/007904875/functions/recvfrom.html
> [5] https://man7.org/linux/man-pages/man2/recv.2.html
> [6] https://epics-modules.github.io/master/asyn/R4-35/RELEASE_NOTES.html
> 
> Thank you,
> Érico
> 
> Aviso Legal: Esta mensagem e seus anexos podem conter informações confidenciais e/ou de uso restrito. Observe atentamente seu conteúdo e considere eventual consulta ao remetente antes de copiá-la, divulgá-la ou distribuí-la. Se você recebeu esta mensagem por engano, por favor avise o remetente e apague-a imediatamente.
> Disclaimer: This email and its attachments may contain confidential and/or privileged information. Observe its content carefully and consider possible querying to the sender before copying, disclosing or distributing it. If you have received this email by mistake, please notify the sender and delete it immediately.

References:
asynInterposeEos/StreamDevice: "read from low-level driver returned 1" and EAGAIN/EWOULDBLOCK Érico Nogueira Rolim via Tech-talk

Navigate by Date:
Prev: asynInterposeEos/StreamDevice: "read from low-level driver returned 1" and EAGAIN/EWOULDBLOCK Érico Nogueira Rolim via Tech-talk
Next: RE: asynInterposeEos/StreamDevice: "read from low-level driver returned 1" and EAGAIN/EWOULDBLOCK Mark Rivers via Tech-talk
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  <20232024 
Navigate by Thread:
Prev: asynInterposeEos/StreamDevice: "read from low-level driver returned 1" and EAGAIN/EWOULDBLOCK Érico Nogueira Rolim via Tech-talk
Next: RE: asynInterposeEos/StreamDevice: "read from low-level driver returned 1" and EAGAIN/EWOULDBLOCK Mark Rivers via Tech-talk
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  <20232024 
ANJ, 05 Apr 2023 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·