user04
(Olivier Neveu)
October 20, 2020, 3:17pm
1
Hello dear all,
I’m almost new to Tango and encountered what I think is a problem (but I could be wrong about that).
I searched online for a bit but couldn’t find anything.
Here it is :
I wrote a very simple device server : a command to call join on a thread (named “pushThread”) and one attribute.
The thread “pushThread” calls the “push_change_event” method on the attribute 20 times at 10 Hz.
When I call the “join” method from the main thread before the end of the “pushThread” thread, the “push_change_event” method throws an exception with the following details :
Origin : TangoMonitor::get_monitor
Desc : Not able to acquire serialization (dev, class or process) monitor
Reason : API_CommandTimedOut
I don’t think it’s a big problem, but the “push_change_event” method hangs for a few seconds before throwing the exception so it’s a bit annoying.
Maybe this topic will interest someone ?
Best regards, Olivier Neveu
Hi Olivier,
Your issue is the same as the one reported (for pytango) in Concurrently executing a command and pushing event leads to dead lock · Issue #39 · tango-controls/TangoTickets · GitHub
The behaviour you’re seeing is currently expected.
In particular, the following comment in this issue applies to your use case too:
opened 08:51AM - 09 Jul 20 UTC
closed 04:06PM - 06 Apr 22 UTC
We have a DS that, when started, continuously push events with `push_change_even… t` in the context of an ancillary thread. When executing the Stop command, the ancillary thread is cleaned up, but sometime the thread is already executing `push_change_event` when the stop command is processed. My understanding is that the command takes a lock and then `push_change_event` try to take it as well, which gives:
```
Exception in thread Thread-1:
Traceback (most recent call last):
File "/home/debionne/miniconda3/envs/pytango/lib/python3.6/threading.py", line 916, in _bootstrap_inner
self.run()
File "dead_lock.py", line 26, in run
self._device.push_change_event("noise", self._device.read_noise())
PyTango.DevFailed: DevFailed[
DevError[
desc = Not able to acquire serialization (dev, class or process) monitor
origin = TangoMonitor::get_monitor
reason = API_CommandTimedOut
severity = ERR]
```
Setting the `SerialModel` to `NO_SYNC` fixes the issue but it's not a good option.
The following code shows the issue:
```py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time
import threading
import numpy
from tango import DevState
from tango.server import run
from tango.server import Device
from tango.server import attribute, command
class DeadLock(Device) :
noise = attribute(label="Noise",
dtype=((int,),),
max_dim_x=1024, max_dim_y=1024)
class PushingThread(threading.Thread):
def __init__(self, device):
self._stop = False
self._device = device
super(DeadLock.PushingThread, self).__init__()
self.timestamp = time.time()
def run(self):
while self._stop is False:
self._device.push_change_event("noise", self._device.read_noise())
self.timestamp=time.time()
def init_device(self):
Device.init_device(self)
self._lock = threading.Condition()
self._stop = False
self.set_change_event('noise', True, False)
self._pushing_event_thread = self.PushingThread(self)
self._pushing_event_thread.start()
def read_noise(self):
return numpy.random.random_integers(1000, size=(100, 100))
@command
def start(self):
self.set_state(DevState.ON)
@command
def stop(self):
with self._lock:
self._pushing_event_thread._stop=True
self._lock.notify()
self._pushing_event_thread.join()
self.set_state(DevState.OFF)
if __name__ == "__main__":
DeadLock.run_server()
```
Kind regards,
Reynald
user04
(Olivier Neveu)
February 16, 2021, 4:11pm
3
Hi Reynald,
I don’t know why but it is only now that I see your message.
I’m so sorry : it is very late to say thank you.
So, thank you very much.
Best regards,
Olivier