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  <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: Weird channel access problem within Python softioc process
From: Paul Richards via Tech-talk <tech-talk at aps.anl.gov>
To: "tech-talk at aps.anl.gov" <tech-talk at aps.anl.gov>
Date: Wed, 11 Aug 2021 00:05:59 +0000

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!

 

 

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:image001.jpg@01CB39FD.C1593830

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 Michael Davidsaver via Tech-talk
Re: Weird channel access problem within Python softioc process Cobb, Tom (DLSLtd,RAL,LSCI) via Tech-talk

Navigate by Date:
Prev: RE: Getting started talking to a device Mark Rivers via Tech-talk
Next: Career Opportunities [NEW] for Accelerator Scientists Nicholas James Meyler 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: Re: HiPace control via EDU TC 400 Marco A. Barra Montevechi Filho via Tech-talk
Next: Re: Weird channel access problem within Python softioc process Michael Davidsaver 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