pushing events from read method does not clear value flag
I found, that pushing event does not clean value_flag, event if value is cleand. Which makes this flag useless. This results in the crash in PyTango !, due to PyTango relays on this flag.
I added printout, when value is deleted, set and value_flag is set, and this is how it looks like:
The python code:
from tango import EventType
from tango.server import Device, attribute, command
from tango.test_context import DeviceTestContext
class MyDevice(Device):
def init_device(self):
super(MyDevice, self).init_device()
self.set_change_event("attr", True, False)
@attribute()
def attr(self):
self.push_change_event("attr", 1)
return 1
def cb(evnt):
print("Got event")
if __name__ == '__main__':
with(DeviceTestContext(MyDevice, debug=5)) as proxy:
eid = proxy.subscribe_event("attr", EventType.CHANGE_EVENT, cb)
proxy.push_event()
The printouts:
2025-03-24T09:57:58,695390+0100 DEBUG (device_2.cpp:928) dserver/MyDevice/MyDevice Device_2Impl::command_list_query_2 arrived
2025-03-24T09:57:58,695403+0100 DEBUG (device_2.cpp:943) dserver/MyDevice/MyDevice 4 command(s) for device
2025-03-24T09:57:58,695414+0100 DEBUG (device_2.cpp:1025) dserver/MyDevice/MyDevice Leaving Device_2Impl::command_list_query_2
2025-03-24T09:57:58,695682+0100 DEBUG (device_4.cpp:459) dserver/MyDevice/MyDevice Device_4Impl::command_inout_4 arrived, source = 2, command = push_event
2025-03-24T09:57:58,695698+0100 DEBUG (device_2.cpp:124) dserver/MyDevice/MyDevice Device_2Impl::command_inout_2 arrived, source = 2, command = push_event
2025-03-24T09:57:58,695707+0100 DEBUG (tango_monitor.h:152) dserver/MyDevice/MyDevice In get_monitor() test/nodb/mydevice cache, thread = 0, ctr = 0
2025-03-24T09:57:58,695725+0100 DEBUG (tango_monitor.h:203) dserver/MyDevice/MyDevice In rel_monitor() test/nodb/mydevice cache, ctr = 1, thread = 0
2025-03-24T09:57:58,695733+0100 DEBUG (tango_monitor.h:213) dserver/MyDevice/MyDevice Signalling !
2025-03-24T09:57:58,695742+0100 DEBUG (tango_monitor.h:152) dserver/MyDevice/MyDevice In get_monitor() test/nodb/mydevice, thread = 0, ctr = 0
2025-03-24T09:57:58,695749+0100 DEBUG (tango_monitor.h:152) dserver/MyDevice/MyDevice In get_monitor() test/nodb/mydevice, thread = 0, ctr = 1
2025-03-24T09:57:58,695756+0100 DEBUG (tango_monitor.h:181) dserver/MyDevice/MyDevice owner_thread !!
2025-03-24T09:57:58,695764+0100 DEBUG (device.cpp:1798) dserver/MyDevice/MyDevice DeviceImpl::command_inout(): command received : push_event
2025-03-24T09:57:58,695772+0100 DEBUG (subdev_diag.cpp:99) dserver/MyDevice/MyDevice SubDevDiag::get_associated_device() entering ...
2025-03-24T09:57:58,695779+0100 DEBUG (subdev_diag.cpp:105) dserver/MyDevice/MyDevice SubDevDiag::get_associated_device() found :
2025-03-24T09:57:58,695787+0100 DEBUG (subdev_diag.cpp:78) dserver/MyDevice/MyDevice SubDevDiag::set_associated_device() entering ...
2025-03-24T09:57:58,695795+0100 DEBUG (deviceclass.cpp:1152) dserver/MyDevice/MyDevice Entering DeviceClass::command_handler() method
2025-03-24T09:57:58,695833+0100 DEBUG (tango_monitor.h:152) dserver/MyDevice/MyDevice In get_monitor() test/nodb/mydevice, thread = 0, ctr = 2
2025-03-24T09:57:58,695842+0100 DEBUG (tango_monitor.h:181) dserver/MyDevice/MyDevice owner_thread !!
2025-03-24T09:57:58,695864+0100 DEBUG (attrsetval_templ.h:73) dserver/MyDevice/MyDevice Attribute::set_value() called
2025-03-24T09:57:58,695874+0100 DEBUG (attribute.h:1664) dserver/MyDevice/MyDevice Attribute::set_value_flag() to 1
2025-03-24T09:57:58,695882+0100 DEBUG (attribute.cpp:2963) dserver/MyDevice/MyDevice Attribute::generic_fire_event() for change entering ...
2025-03-24T09:57:58,695890+0100 DEBUG (attribute.cpp:2963) dserver/MyDevice/MyDevice Attribute::generic_fire_event() for alarm entering ...
2025-03-24T09:57:58,695902+0100 DEBUG (attribute.h:1671) dserver/MyDevice/MyDevice Attribute::get_value_flag(), ret: 1
2025-03-24T09:57:58,695911+0100 DEBUG (attribute.h:1671) dserver/MyDevice/MyDevice Attribute::get_value_flag(), ret: 1
2025-03-24T09:57:58,695919+0100 DEBUG (attribute.h:1671) dserver/MyDevice/MyDevice Attribute::get_value_flag(), ret: 1
2025-03-24T09:57:58,695932+0100 DEBUG (device.cpp:5165) dserver/MyDevice/MyDevice DeviceImpl::data_into_net_object() called
2025-03-24T09:57:58,695942+0100 DEBUG (zmqeventsupplier.cpp:1753) dserver/MyDevice/MyDevice ZmqEventSupplier::push_event_loop(): called for attribute attr
2025-03-24T09:57:58,695956+0100 DEBUG (zmqeventsupplier.cpp:1040) dserver/MyDevice/MyDevice ZmqEventSupplier::push_event(): called for attribute/pipe attr
2025-03-24T09:57:58,695990+0100 DEBUG (attribute.cpp:2147) dserver/MyDevice/MyDevice Attribute::delete_seq_and_reset_alarm() called
2025-03-24T09:57:58,696002+0100 DEBUG (attribute.cpp:2171) dserver/MyDevice/MyDevice Attribute::delete_seq() called
2025-03-24T09:57:58,696011+0100 DEBUG (tango_monitor.h:203) dserver/MyDevice/MyDevice In rel_monitor() test/nodb/mydevice, ctr = 3, thread = 0
2025-03-24T09:57:58,696025+0100 DEBUG (deviceclass.cpp:1262) dserver/MyDevice/MyDevice Leaving DeviceClass::command_handler() method
2025-03-24T09:57:58,696033+0100 DEBUG (subdev_diag.cpp:78) dserver/MyDevice/MyDevice SubDevDiag::set_associated_device() entering ...
2025-03-24T09:57:58,696043+0100 DEBUG (device.cpp:1848) dserver/MyDevice/MyDevice DeviceImpl::command_inout(): leaving method for command push_event
2025-03-24T09:57:58,696053+0100 DEBUG (tango_monitor.h:203) dserver/MyDevice/MyDevice In rel_monitor() test/nodb/mydevice, ctr = 2, thread = 0
2025-03-24T09:57:58,696065+0100 DEBUG (tango_monitor.h:203) dserver/MyDevice/MyDevice In rel_monitor() test/nodb/mydevice, ctr = 1, thread = 0
2025-03-24T09:57:58,696074+0100 DEBUG (tango_monitor.h:213) dserver/MyDevice/MyDevice Signalling !
As you see, we do:
2025-03-24T09:57:58,695864+0100 DEBUG (attrsetval_templ.h:73) dserver/MyDevice/MyDevice Attribute::set_value() called
2025-03-24T09:57:58,695874+0100 DEBUG (attribute.h:1664) dserver/MyDevice/MyDevice Attribute::set_value_flag() to 1
And then
2025-03-24T09:57:58,695990+0100 DEBUG (attribute.cpp:2147) dserver/MyDevice/MyDevice Attribute::delete_seq_and_reset_alarm() called
2025-03-24T09:57:58,696002+0100 DEBUG (attribute.cpp:2171) dserver/MyDevice/MyDevice Attribute::delete_seq() called
But there is no call to set value_flag to 0
This is Catch2 equivalent to pytango code:
#include "catch2_common.h"
template <class Base>
class EventDev : public Base
{
public:
using Base::Base;
~EventDev() override { }
void init_device() override
{
Base::set_change_event("attr", true, false);
}
void read_attribute(Tango::Attribute &att)
{
{
Tango::DevLong* val = new Tango::DevLong(1);
Tango::AutoTangoMonitor tango_guard(this);
att.set_value(val, 1, 0, true);
att.fire_change_event(nullptr);
}
if (!att.get_value_flag()){
Tango::DevLong* val_ret = new Tango::DevLong(1);
att.set_value(val_ret);
}
}
static void attribute_factory(std::vector<Tango::Attr *> &attrs)
{
{
auto long_attr = new TangoTest::AutoAttr<&EventDev::read_attribute>("attr", Tango::DEV_LONG);
attrs.push_back(long_attr);
}
}
};
TANGO_TEST_AUTO_DEV_TMPL_INSTANTIATE(EventDev, 4)
SCENARIO("Subscribe to event with simultaneous push")
{
int idlver = GENERATE(TangoTest::idlversion(4));
GIVEN("a device proxy to a simple IDLv" << idlver << " device")
{
TangoTest::Context ctx{"change_event_state", "EventDev", idlver};
auto device = ctx.get_proxy();
REQUIRE(idlver == device->get_idl_version());
AND_GIVEN("an event subscription to attr attribute")
{
TangoTest::CallbackMock<Tango::EventData> callback;
REQUIRE_NOTHROW(device->subscribe_event("attr", Tango::CHANGE_EVENT, &callback));
}
}
}
Edited by Yury Matveev