EPICS Home

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: asynInterposeEos/StreamDevice: "read from low-level driver returned 1" and EAGAIN/EWOULDBLOCK
From: Érico Nogueira Rolim via Tech-talk <tech-talk at aps.anl.gov>
To: "tech-talk at aps.anl.gov" <tech-talk at aps.anl.gov>
Date: Wed, 5 Apr 2023 14:12:34 +0000

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.


Replies:
Re: asynInterposeEos/StreamDevice: "read from low-level driver returned 1" and EAGAIN/EWOULDBLOCK Zimoch Dirk via Tech-talk
RE: asynInterposeEos/StreamDevice: "read from low-level driver returned 1" and EAGAIN/EWOULDBLOCK Mark Rivers via Tech-talk

Navigate by Date:
Prev: Re: Probe plug-in for the Probe panel? Kasemir, Kay via Tech-talk
Next: Re: asynInterposeEos/StreamDevice: "read from low-level driver returned 1" and EAGAIN/EWOULDBLOCK Zimoch Dirk 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: EPICS Qt 3.9.2 available [SEC=OFFICIAL] STARRITT, Andrew via Tech-talk
Next: Re: asynInterposeEos/StreamDevice: "read from low-level driver returned 1" and EAGAIN/EWOULDBLOCK Zimoch Dirk 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