Skip to content

Commit

Permalink
Prevented unsubscribing events from a cleared channel
Browse files Browse the repository at this point in the history
  • Loading branch information
hanak committed Oct 17, 2023
1 parent 561c5ef commit 634fe76
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 8 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ dist
NonGit
venv
.vscode
.coverage
pyepics.egg-info
epics.egg-info
14 changes: 10 additions & 4 deletions epics/ca.py
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,16 @@ def clear_cache():
multiprocessing (and is done internally by CAProcess),
but can be useful to fully reset a Channel Access session.
"""
# Clear the cache of PVs used by epics.caget()-like functions
# by disconnecting PVs so that all subscriptions are released
# prior clearing channels.
from . import pv
pv_cache = pv._PVcache_
pv._PVcache_ = {}
for pv in pv_cache.values():
pv.disconnect()
pv_cache.clear()

# Unregister callbacks (if any)
for chid, entry in list(_chid_cache.items()):
try:
Expand All @@ -505,10 +515,6 @@ def clear_cache():
_cache.clear()
_chid_cache.clear()

# Clear the cache of PVs used by epics.caget()-like functions
from . import pv
pv._PVcache_ = {}

# The old context is copied directly from the old process
# in systems with proper fork() implementations
detach_context()
Expand Down
5 changes: 5 additions & 0 deletions epics/pv.py
Original file line number Diff line number Diff line change
Expand Up @@ -1120,6 +1120,11 @@ def disconnect(self, deepclean=True):
it from _PVcache_, so that subsequent connection to this PV will almost
always make a completely new connection.
However, this method keeps the EPICS channel ID alive
so that it can be re-used later. This may block some resources.
Use `ca.clear_channel()` to clear the channel ID if needed
only after disconnecting the PV.
Arguments
-----------
deepclean, bool removal all cache connection and access-rights callbacks [True]
Expand Down
22 changes: 18 additions & 4 deletions tests/test_ca_clearcache.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import epics
from epics import ca
import epics.ca
import epics.pv

import os
import time
import sys
import subprocess
import pvnames
enabledpv = pvnames.clear_cache_enabled
Expand All @@ -24,7 +23,22 @@ def run():
assert value is not None, \
"PV {} is offline".format(beaconpv)
time.sleep(0.2)
ca.clear_cache()
epics.ca.clear_cache()


def test_use_monitor():
# This test verifies that clear_cache clears subscriptions created by
# use_monitor=True prior clearing channels.
# Otherwise, EPICS will crash on an attempt to clear subscription
# on a cleared channel.
assert epics.caget(enabledpv, use_monitor=True) is not None, \
"PV {} is offline".format(enabledpv)

pv = epics.pv.get_pv(enabledpv)

epics.ca.clear_cache()

pv.disconnect()


def test_subscribe():
Expand Down

0 comments on commit 634fe76

Please sign in to comment.