Menu

#813 Segfault when pushing a change event with invalid quality

closed
nobody
C++ API
5
2017-01-06
2016-08-10
No

I've been able to reproduce reliably a segfault that started to appear after our tango 9 migration. It turns out that pushing a change event with an invalid quality from the code can cause the device server to segfault (not everytime though). Here is the server code I used to reproduce the issue:

import time
from tango.server import Device, DeviceMeta, command, attribute
from tango import DevState, AttrQuality

class SegfaultTest(Device):
    __metaclass__ = DeviceMeta

    def init_device(self):
        self.set_change_event('value', True, False)
        self.set_state(DevState.ON)

    @command
    def push_invalid(self):
        print('pushing invalid...')
        self.push_change_event(
            'value', 0.0, time.time(), AttrQuality.ATTR_INVALID)
        print('pushed!')

    @attribute
    def value(self):
        return -1

if __name__ == '__main__':
    SegfaultTest.run_server()

And the client code:

import tango.utils
from time import sleep

def test():
    cb = tango.utils.EventCallBack()
    proxy = tango.DeviceProxy('test/vinmic/segfault')
    eid = proxy.subscribe_event('value', tango.EventType.CHANGE_EVENT, cb)
    proxy.push_invalid()
    proxy.unsubscribe_event(eid)

while True:
    test()
    sleep(0.5)

I've also been able to reproduce the segfault with a C++ device server, though it might take longer for the server to crash (the python version usually crashes at the first iteration of the client script). I'm using tango 9.2.2 with patch 922_1.

Let me know if you need more information,

Thanks
/Vincent

Discussion

  • Vincent Michel

    Vincent Michel - 2016-08-16

    Here's the back trace (same for python and C++ devices):

    #0  copybuffer (newmax=5, this=0x7fffdc005970) at /usr/include/omniORB4/seqTemplatedecls.h:294
    #1  _CORBA_Sequence<double>::get_buffer (this=0x7fffdc005970, orphan=<optimized out>)
        at /usr/include/omniORB4/seqTemplatedecls.h:184
    #2  0x00007ffff78e0ce8 in Tango::DeviceImpl::data_into_net_object (this=<optimized out>, att=..., 
        aid=..., index=0, w_type=<optimized out>, del_seq=<optimized out>) at device.cpp:4910
    #3  0x00007ffff7899dce in Tango::Attribute::Attribute_2_AttributeValue (this=this@entry=0x689a50, 
        ptr_5=ptr_5@entry=0x7fffdc006b60, d=0x685c50) at attribute.cpp:3422
    #4  0x00007ffff78a4baa in Tango::Attribute::fire_change_event (this=this@entry=0x689a50, 
        except=except@entry=0x0) at attribute.cpp:3953
    #5  0x00007ffff78c7d00 in Tango::DeviceImpl::push_change_event (this=<optimized out>, 
        attr_name="value", p_data=0x6897a0, t=..., qual=Tango::ATTR_INVALID, x=1, y=0, release=false)
        at dev_event.cpp:1123
    
     
  • Andreas Persson

    Andreas Persson - 2016-08-16

    I have compared the relevant code to version 8.1.2. There has been some refactoring there. In Tango 8, DeviceImpl::data_into_net_object is not called from Attribute::Attribute_2_AttributeValue if the quality is ATTR_INVALID.

    Something like this seems to solve the problem:

    diff --git a/server/attribute.cpp b/server/attribute.cpp
    index c61d9ff..52bd92e 100644
    --- a/server/attribute.cpp
    +++ b/server/attribute.cpp
    @@ -3389,7 +3389,7 @@ void Attribute::Attribute_2_AttributeValue(Tango::AttributeValue_4 *ptr_4,Tango:
            Tango::AttributeValueList_4 dummy_list(1,1,ptr_4,false);
            aid.data_4 = &dummy_list;
    
    -       if ((name_lower != "state") && (name_lower != "status"))
    +       if ((name_lower != "state") && (name_lower != "status") && (quality != Tango::ATTR_INVALID))
             d->data_into_net_object(*this,aid,0,writable,false);
     }
    
    @@ -3417,7 +3417,7 @@ void Attribute::Attribute_2_AttributeValue(Tango::AttributeValue_5 *ptr_5,Tango:
            Tango::AttributeValueList_5 dummy_list(1,1,ptr_5,false);
            aid.data_5 = &dummy_list;
    
    -       if ((name_lower != "state") && (name_lower != "status"))
    +       if ((name_lower != "state") && (name_lower != "status") && (quality != Tango::ATTR_INVALID))
             d->data_into_net_object(*this,aid,0,writable,false);
    
            ptr_5->data_type = data_type;
    
     
  • Emmanuel Taurel

    Emmanuel Taurel - 2016-08-31

    Bug fixed in SVN.
    Andreas: thank's for the bug fix but note that I had also to add another small change due to this bug
    in file server/zmqeventsupplier.cpp. This is also in SVN for the same commit

    Cheers

    Emmanuel

     
  • Bourtembourg Reynald

    • Status: open --> closed
     

Log in to post a comment.