question

Upvotes
Accepted
57 3 2 7

Help with segfault on rsslEncodeMapComplete after having added map summary data

Hi. I previously had an UPA server for testing that successfully was able to encode the Reuter's Domain Model Market By Price Refresh and Update messages. They were consumed successfully by an rssl consumer. I recently added summary data to the map that is the payload of this message. I didn't change the surrounding code much, but rsslEncodeMapComplete segfaults now. I error check every rssl API call and do not get errors, so I am unsure where I went wrong. I am working in x86_64 linux environment using the C API with RSSL_RWF_MAJOR_VERSION of 14 and RSSL_RWF_MINOR_VERSION of 0. Here is some very loose sample code showing what I am doing. I have omitted error checking for simplicity and sectioned off the area I added with extended slashes. The main function is at the bottom. Do you have any ideas of what I may have done wrong? I am yet to figure it out. The error must be in the part I added, but the segfault doesn't happen until the very end which makes it hard to know quite where I went wrong. Thank you very much for any help.

void encode_price_level(RsslEncodeIterator *encode_iterator)
{
    RsslMapEntry map_entry;
    rsslClearMapEntry(&map_entry);
    map_entry.action = RSSL_MPEA_ADD_ENTRY;
    map_entry.flags = RSSL_MPEF_NONE;
    
    RsslBuffer buffer;
    buffer.data = "12.123B";
    buffer.length = "12.123B";
    
    rsslEncodeMapEntryInit(encode_iterator, &map_entry, &buffer, 0);
    
    RsslFieldList field_list = RSSL_INIT_FIELD_LIST;
    field_list.flags = RSSL_FLF_HAS_STANDARD_DATA;
    rsslEncodeFieldListInit(encode_iterator, &field_list, NULL, 0);

    RsslFieldEntry field_entry = RSSL_INIT_FIELD_ENTRY;
    RsslReal real_value = RSSL_INIT_REAL;

    // price
    rsslClearFieldEntry(&field_entry);
    field_entry.fieldId = 3427;
    field_entry.dataType = RSSL_DT_REAL;
    rsslClearReal(&real_value);
    RsslDouble idouble = 10.000;
    rsslDoubleToReal(&real_value, &idouble, RSSL_RH_EXPONENT0);
    rsslEncodeFieldEntry(encode_iterator, &field_entry, &real_value);

    // quantity
    rsslClearFieldEntry(&field_entry);
    field_entry.fieldId = 4356;
    field_entry.dataType = RSSL_DT_REAL;
    rsslClearReal(&real_value);
    RsslDouble idouble = 1000.0;
    rsslDoubleToReal(&real_value, &idouble, RSSL_RH_EXPONENT0);
    rsslEncodeFieldEntry(encode_iterator, &field_entry, &real_value);

    // side
    rsslClearFieldEntry(&field_entry);
    field_entry.fieldId = 3428;
    field_entry.dataType = RSSL_DT_ENUM;
    RsslEnum side_enum = 1;
    rsslEncodeFieldEntry(encode_iterator, &field_entry, &side_enum);

    rsslEncodeFieldListComplete(encode_iterator, RSSL_TRUE);
    rsslEncodeMapEntryComplete(encode_iterator, RSSL_TRUE);
}

void sample_encode_mbp_refresh(RsslMsg *rssl_message, RsslEncodeIterator *encode_iterator, RsslBuffer *buffer)
{
    /* UPA RDM Usage Guide Section 8.2.2 */
    RsslRefreshMsg *market_by_price_refresh = (RsslRefreshMsg *) rssl_message;
    market_by_price_refresh->msgBase.domainType = RSSL_DMT_MARKET_BY_PRICE;
    market_by_price_refresh->msgBase.msgClass = RSSL_MC_REFRESH;
    market_by_price_refresh->msgBase.containerType = RSSL_DT_MAP;
    market_by_price_refresh->msgBase.streamId = 1000;
    market_by_price_refresh->state.streamState = RSSL_STREAM_OPEN;
    market_by_price_refresh->state.dataState = RSSL_DATA_OK;
    market_by_price_refresh->state.code = RSSL_SC_NONE;
    market_by_price_refresh->flags = RSSL_RFMF_HAS_MSG_KEY | RSSL_RFMF_REFRESH_COMPLETE;
    market_by_price_refresh->msgBase.msgKey.flags = RSSL_MKF_HAS_NAME_TYPE | RSSL_MKF_HAS_SERVICE_ID | RSSL_MKF_HAS_NAME;
    market_by_price_refresh->msgBase.msgKey.nameType = RDM_INSTRUMENT_NAME_TYPE_RIC;
    market_by_price_refresh->msgBase.msgKey.name.data = "SYMBOL_RIC";
    market_by_price_refresh->msgBase.msgKey.name.length = strlen("SYMBOL_RIC");
    market_by_price_refresh->msgBase.msgKey.serviceId = 42;

    /* Initiate encode */
    rsslClearEncodeIterator(encode_iterator);
    rsslSetEncodeIteratorBuffer(encode_iterator, buffer);
    rsslSetEncodeIteratorRWFVersion(encode_iterator, RSSL_RWF_MAJOR_VERSION, RSSL_RWF_MINOR_VERSION);
    rsslEncodeMsgInit(encode_iterator, rssl_message, 0);

    RsslMap map = RSSL_INIT_MAP;
    map.containerType = RSSL_DT_FIELD_LIST;
    map.flags =  RSSL_MPF_HAS_SUMMARY_DATA;
    map.keyPrimitiveType = RSSL_DT_BUFFER;
    // I have tried 0 and a large value for summaryMaxSize argument
    rsslEncodeMapInit(encode_iterator, &map, 0, 0);

    ///////////////////////////////////////////////////////////////////
    RsslFieldList field_list = RSSL_INIT_FIELD_LIST;
    field_list.flalgs = RSSL_FLF_HAS_STANDARD_DATA;
    RsslFieldEntry field_entry = RSSL_INIT_FIELD_ENTRY;
    rsslEncodeFieldListInit(encode_iterator, &field_list, NULL, 0);

    rsslClearFieldEntry(&field_entry);
    field_entry.fieldId = 6535;
    field_entry.dataType = RSSL_DT_INT;
    RsslInt int_value = 900;
    rsslEncodeFieldEntry(encode_iterator, &field_entry, &int_value);

    rsslClearFieldEntry(&field_entry);
    field_entry.fieldId = 6536;
    field_entry.dataType = RSSL_DT_INT;
    int_value = 800;
    rsslEncodeFieldEntry(encode_iterator, &field_entry, &int_value);

    rsslEncodeFieldListComplete(encode_iterator, RSSL_TRUE);
    rsslEncodeMapSummaryDataComplete(encode_iterator, RSSL_TRUE);
    ////////////////////////////////////////////////////////////////////////
    
    for (int price_level_idx = 0;  price_level_idx < 10; price_level_idx++) {
        encode_price_level(encode_iterator);
    }

    rsslEncodeMapComplete(encode_iterator, RsslBool success);
    rsslEncodeMsgComplete(encode_iterator, RsslBool success);

}

int main()
{
    RsslEncodeIterator encode_iterator = RSSL_INIT_ENCODE_ITERATOR;
    RsslBuffer rssl_buffer = RSSL_INIT_BUFFER;
    rssl_buffer.data = large_buffer;
    rssl_buffer.length = large_buffer_length;

    RsslMsg rssl_msg = RSSL_INIT_MSG;
    sample_encode_mbp_refresh(&rssl_msg, &encode_iterator, &rssl_buffer);
}
#technologyeta-apirsslencodingupa-api
icon clock
10 |1500

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

1 Answer

· Write an Answer
Upvotes
Accepted
87k 294 53 79

@bneway

Thank you for reaching out to us.

The encoding functions can return values so it is better to check the return values before calling the next encoding functions. For example:

if ((retVal = rsslEncodeMsgInit(encIter, (RsslMsg*)&refreshMsg, 0)) < RSSL_RET_SUCCESS)
    {
        /* error condition - switch our success value to false so we can roll back */
        success = RSSL_FALSE;
        /* print out message with return value string, value, and text */
        printf("Error %s (%d) encountered with rsslEncodeMsgInit().  Error Text: %s\n", 
                rsslRetCodeToString(retVal), retVal, rsslRetCodeInfo(retVal)); 
    }

I found several problems in the attached code.

1. The idouble variable is redefined.

// price
    rsslClearFieldEntry(&field_entry);
    field_entry.fieldId = 3427;
    field_entry.dataType = RSSL_DT_REAL;
    rsslClearReal(&real_value);
    RsslDouble idouble = 10.000;
    rsslDoubleToReal(&real_value, &idouble, RSSL_RH_EXPONENT0);
    rsslEncodeFieldEntry(encode_iterator, &field_entry, &real_value);
 
    // quantity
    rsslClearFieldEntry(&field_entry);
    field_entry.fieldId = 4356;
    field_entry.dataType = RSSL_DT_REAL;
    rsslClearReal(&real_value);
    RsslDouble idouble = 1000.0;
    rsslDoubleToReal(&real_value, &idouble, RSSL_RH_EXPONENT0); 

2. Passing the incorrect values to the rsslEncodeMapComplete and rsslEncodeMsgComplete method

    rsslEncodeMapComplete(encode_iterator, RsslBool success);
    rsslEncodeMsgComplete(encode_iterator, RsslBool success);

3. Invalid buffer initialization. The buffer.length should be 7.

    RsslBuffer buffer;
    buffer.data = "12.123B";
    buffer.length = "12.123B";
    
icon clock
10 |1500

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.