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  <20212022  2023  2024  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  <20212022  2023  2024 
<== Date ==> <== Thread ==>

Subject: Re: Weird channel access problem within Python softioc process
From: Michael Davidsaver via Tech-talk <tech-talk at aps.anl.gov>
To: Paul Richards <prichards at keck.hawaii.edu>
Cc: "tech-talk at aps.anl.gov" <tech-talk at aps.anl.gov>
Date: Tue, 10 Aug 2021 20:37:44 -0700
On 8/10/21 5:05 PM, Paul Richards via Tech-talk wrote:
> All,
> 
>  
> 
> At Keck, we have been using the EPICS Python softioc with great success.  The recent 3.1 release has made it even more popular and easier to use.
> 
>  
> 
> That said, I have found a very odd behavior that I can replicate, relating to the consumption of keywords inside the same process that runs the softioc.  Sometimes it makes sense to do it this way, instead of finding a reference to the channel in the IOC and manipulating that.
> 
>  
> 
> A simplified example of the problem:
> 
>  1. Import the pyepics and softioc libraries.
>  2. Start a softioc with a channel (call it ‘prefix:long’ in my example).
>  3. Start a thread that periodically updates the channel with a new value.
>  4. Start another thread that tries to access this channel, either with epics.PV() or epics.caget().
>  5. Channel access in thread 2 always times out, forever.
> 
>  
> 
> Today I found a “solution” to this that does not make sense: if I start the softioc (the call to softioc.iotInit()) in the first thread, and not in the main process, everything works as expected.
> 
>  
> 
> Our engineers are unable to explain this behavior.  I hope there’s someone here on the list that might know why!

You might try moving the 'import epics' line after softioc.iocInit().

fyi. libca has some special behavior when run within an IOC process
to facilitate access to local records.  As I recall, this imposes
a required initialization order.

Also, libca uses a thread local variable to hold the client context
pointer.  It is possible that pyepics is leaving its context pointer
in place, which will likely cause problems during iocInit().


> Example code that demonstrates the failure:
> 
> --------------------
> 
>  
> 
> import os
> 
> import time
> 
> import threading
> 
>  
> 
> os.environ['EPICS_CA_SERVER_PORT'] = '5100'
> 
> os.environ['EPICS_CA_ADDR_LIST'] = 'localhost:5100'
> 
> os.environ['EPICS_CA_AUTO_ADDR_LIST'] = 'NO'
> 
>  
> 
> try:
> 
>     import epicscorelibs.path.pyepics
> 
> except ImportError:
> 
>     pass
> 
> import epics
> 
>  
> 
> from softioc import softioc, builder
> 
>  
> 
> # Create a long record for this demo
> 
> long = builder.longOut('prefix:long', initial_value=1)
> 
> builder.LoadDatabase()
> 
> softioc.iocInit()
> 
>  
> 
> def thread1():
> 
>     while True:
> 
>         val = long.get()
> 
>         long.set(val + 1)
> 
>         print(f'thread1: {val}')
> 
>         time.sleep(1)
> 
>  
> 
> def thread2():
> 
>     pv = epics.PV('prefix:long')
> 
>  
> 
>     while True:
> 
>         val = pv.get()
> 
>         print(f'thread2: {val}')
> 
>         time.sleep(1)
> 
>  
> 
> t1 = threading.Thread(target=thread1, daemon=True)
> 
> t2 = threading.Thread(target=thread2, daemon=True)
> 
>  
> 
> t1.start()
> 
> t2.start()
> 
>  
> 
> time.sleep(10)
> 
>  
> 
>  
> 
>  
> 
> Example that works; note the only change is the movement of the .iocInit() line down into thread1:
> 
> --------------------
> 
>  
> 
> import os
> 
> import time
> 
> import threading
> 
>  
> 
> os.environ['EPICS_CA_SERVER_PORT'] = '5100'
> 
> os.environ['EPICS_CA_ADDR_LIST'] = 'localhost:5100'
> 
> os.environ['EPICS_CA_AUTO_ADDR_LIST'] = 'NO'
> 
>  
> 
> try:
> 
>     import epicscorelibs.path.pyepics
> 
> except ImportError:
> 
>     pass
> 
> import epics
> 
>  
> 
> from softioc import softioc, builder
> 
>  
> 
> # Create a long record for this demo
> 
> long = builder.longOut('prefix:long', initial_value=1)
> 
> builder.LoadDatabase()
> 
>  
> 
> def thread1():
> 
>     softioc.iocInit()
> 
>  
> 
>     while True:
> 
>         val = long.get()
> 
>         long.set(val + 1)
> 
>         print(f'thread1: {val}')
> 
>         time.sleep(1)
> 
>  
> 
> def thread2():
> 
>    pv = epics.PV('prefix:long')
> 
>  
> 
>     while True:
> 
>         val = pv.get()
> 
>         print(f'thread2: {val}')
> 
>         time.sleep(1)
> 
>  
> 
> t1 = threading.Thread(target=thread1, daemon=True)
> 
> t2 = threading.Thread(target=thread2, daemon=True)
> 
>  
> 
> t1.start()
> 
> t2.start()
> 
>  
> 
> time.sleep(10)
> 
>  
> 
>  
> 
> The output when it fails:
> 
>  
> 
> $ python3 ./demoFailingDaemon.py
> 
> Starting iocInit
> 
> ############################################################################
> 
> ## EPICS 7.0.6.0
> 
> ## Rev. 7.0.6.99.1.0
> 
> ############################################################################
> 
> iocRun: All initialization complete
> 
> thread1: 1
> 
> thread1: 2
> 
> thread1: 3
> 
> thread2: None
> 
> thread1: 4
> 
> thread1: 5
> 
> thread2: None
> 
> thread1: 6
> 
> thread1: 7
> 
> thread1: 8
> 
> thread2: None
> 
> thread1: 9
> 
> thread1: 10
> 
> thread1: 11
> 
>  
> 
>  
> 
> The output when it works:
> 
>  
> 
> $ python3 ./demoWorkingDaemon.py
> 
> Starting iocInit
> 
> ############################################################################
> 
> ## EPICS 7.0.6.0
> 
> ## Rev. 7.0.6.99.1.0
> 
> ############################################################################
> 
> iocRun: All initialization complete
> 
> thread1: 1
> 
> thread2: 2
> 
> thread1: 2
> 
> thread2: 3
> 
> thread1: 3
> 
> thread2: 4
> 
> thread1: 4
> 
> thread2: 5
> 
> thread1: 5
> 
> thread2: 6
> 
> thread1: 6
> 
> thread2: 7
> 
> thread1: 7
> 
> thread2: 8
> 
> thread1: 8
> 
> thread2: 9
> 
> thread1: 9
> 
> thread2: 10
> 
> thread1: 10
> 
> thread2: 11
> 
>  
> 
>  
> 
>  
> 
>  
> 
>  
> 
> Paul
> 
>  
> 
>  
> 
>  
> 
> Description: Description: cid:[email protected]
> 
> 	
> 
> *Paul Richards*
> 
> *Software Engineer*
> 
> W. M. Keck Observatory
> 
> 65-1120 Mamalahoa Hwy.
> 
> Kamuela, Hawai'i 96743
> 
> 	
> 
> Main: (808) 885-7887
> 
> Direct: (808) 881-3537
> 
> Fax: (808) 885-3535
> 
>  
> 
>  
> 


Replies:
Re: Weird channel access problem within Python softioc process Zhang, Tong via Tech-talk
References:
Weird channel access problem within Python softioc process Paul Richards via Tech-talk

Navigate by Date:
Prev: Career Opportunities [NEW] for Accelerator Scientists Nicholas James Meyler via Tech-talk
Next: Re: HiPace control via EDU TC 400 Florian Feldbauer 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  <20212022  2023  2024 
Navigate by Thread:
Prev: Weird channel access problem within Python softioc process Paul Richards via Tech-talk
Next: Re: Weird channel access problem within Python softioc process Zhang, Tong 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  <20212022  2023  2024 
ANJ, 11 Aug 2021 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·