Skip to content

[BZ-1521] Demarshalling error in Real Time Event Service for small events #1521

@jwillemsen

Description

@jwillemsen
Field Value
Bugzilla ID 1521
Reporter srottoo
Assigned to DOC Center Support List (internal)
Product TAO
Component Real-Time Event Service
Version 1.3.1
Platform / OS All / All
Priority P3
Severity normal
Status ASSIGNED
Resolution
Created 2003-06-02 07:51:39 -0500

Originally posted by srottoo on 2003-06-02 07:51:39 -0500


If the example for Custom Marshal in $ACE_ROOT/orbsvcs/tests/EC_Custom_Marshal
is run with the default parameters for the supplier ,the consumer receives the
events as pushed by the supplier. By default the event size is 32. However
reducing the event_size to say 10 causes the consumer to print out a "No Data in
event" error message.

DESCRIPTION: 

Small-size events are not demarshalled correctly in the
rtecdefaulteventdatac.cpp file. This is the cause of the bug that causes a "no
data in event" error in the Custom Marshal example when -b < 27.

The test that fails in the example is:

  if (e.data.payload.mb () == 0) 
      ACE_DEBUG ((LM_DEBUG, "No data in event[%d]\n", i)); 

This happens for small events because the message block into which the data is
placed is processed differently for large events.

There are two cases when an event is received

  1. The event is small enough so that the whole message is read in one go.
  2. The event is too big and another read needs to be performed to get the message.

Eventually the following demarshalling code is executed at the following method
in rtecdefaulteventdatac.cpp

CORBA::Boolean operator>> (
TAO_InputCDR &strm,
EventPayload &_tao_sequence
)
{

  if (ACE_BIT_DISABLED (strm.start ()->flags (), 
  ACE_Message_Block::DONT_DELETE)) 
  { 
    TAO_ORB_Core* orb_core = strm.orb_core (); 
    if (orb_core != 0 && 
    strm.orb_core ()->resource_factory ()-> 
    input_cdr_allocator_type_locked () == 1) 
    { 
      TAO_Unbounded_Sequence<CORBA::Octet> *oseq = 
        ACE_static_cast(TAO_Unbounded_Sequence<CORBA::Octet>*, &_tao_sequence); 
      oseq->replace (_tao_seq_len, strm.start ()); 
      oseq->mb ()->wr_ptr (oseq->mb()->rd_ptr () + _tao_seq_len); 
      strm.skip_bytes (_tao_seq_len); 
      return 1; 
    } 
  } 
    return strm.read_octet_array (_tao_sequence.get_buffer (), _tao_seq_len); 

In the case where the event is not obtained in one read the DONT_DELETE bit of
the strm start message block
is set to 0 and the if part of the code is executed. This has the effect of
replacing the buffer in tao_sequence with an ACE_Message_Block which sets the
mb
field in _tao_sequence appropriately and everything works fine.

However if the event is small enough to be read in one go, the DONT_DELETE bit
stays at
1 and the if part of the code is not executed. Instead the
strm.read_octet_array() code is executed. However this code does NOT set the mb_
field. Instead it allocates a buffer of octets and only the buffer_ field is
set. The result is that when the client tries to access the data from the mb()
method the latter will return a value of 0 hence the "No data in event" message.

To see why the DONT_DELETE flags are different here is the relevant part of the
call stack when an event is received. This is the call stack when a big event is
received and which will clear the flag.

    C++ 
    TAOd.dll!TAO_GIOP_Message_Base::process_request_message(TAO_Transport *

transport=0x00eaf9e0, TAO_Queued_Data * qd=0x0012f564) Line 685 + 0x1e C++

    TAOd.dll!TAO_Transport::process_parsed_messages(TAO_Queued_Data *

qd=0x0012f564, TAO_Resume_Handle & rh={...}) Line 1950 + 0x33 C++

    TAOd.dll!TAO_Transport::consolidate_message(ACE_Message_Block &

incoming={...}, int missing_data=0, TAO_Resume_Handle & rh={...}, ACE_Time_Value

  • max_wait_time=0x00000000) Line 1639 C++

      TAOd.dll!TAO_Transport::parse_consolidate_messages(ACE_Message_Block &
    

block={...}, TAO_Resume_Handle & rh={...}, ACE_Time_Value *
max_wait_time=0x00000000) Line 1452 + 0x1b C++

    TAOd.dll!TAO_Transport::handle_input_i(TAO_Resume_Handle & rh={...},

ACE_Time_Value * max_wait_time=0x00000000, int __formal=0) Line 1386 + 0x17
C++

As we can see the consolidate_message method is called. This method calls

// Grow the buffer to the size of the message
ACE_CDR::grow (&incoming,
payload);

which clears the DONT_DELETE bit in the incoming message block's flag.

However in the case of a small event, consolidate_message is not called and the
flags stays at 1 causing the problem described above.

REPEAT BY: 

[What you did to get the error; include test program or session
transcript if at all possible. ]

SAMPLE FIX/WORKAROUND: 

One fix is to remove the if check so that the if part of the code is always
executed. I did this and it works.

The other way is to change the TAO_Unbounded_SequenceCORBA::Octet class so
that only ACE_Message_Blocks are used to store the data. Right now message
blocks are only used if the replace method of the class is called but that may
be by design.

Yet another way would be to clear the DONT_DELETE flag event explicitly in all
cases. However that has implications in terms of ownership.

It looks to me that the problem is in the TAO_Unbounded_Sequence<CORBA_Octet>
class which should always use message blocks instead of using them only
when the replace method is called.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions