Please report new issues athttps://github.com/DOCGroup
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 ) { <snip> 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_Sequence<CORBA::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.
Accepting this bug
We should also make sure that the test is changed so that such kind of error is detected by our regression tests.
Set it to tao-support, no time at this moment to fix this.
Accepted on behalf of tao-support.