knowledge-database (beta)

Current group: comp.soft-sys.ace

[ace-users] Streams flags deallocation policy error

[ace-users] Streams flags deallocation policy error  
David Hawkins
From:David Hawkins
Subject:[ace-users] Streams flags deallocation policy error
Date:22 Jan 2005 19:41:29 -0600
Hi,

I have been trying to track down a SEGV in a module
pushed into a stream and I have found the problem.

If you pass a stack-based, or member variable task
into an ACE_Module, you set the close flag to
M_DELETE_NONE, which in Module.h is 0 (zero).

The module will adhere to this allocation policy if
used in a stand-alone test, i.e., if you dynamically
allocate a module, initialize it with stack based tasks,
and delete the module, then no SEGV occurs.

However, if you push that same module into a stream,
a SEGV occurs when the stream destructs that module!?

The issue is that the Stream::close() function also
has a set of flags, and the default is M_DELETE = 3,
whereas the Module::close() default is M_DELETE_NONE = 0.

Inside Module::close() is the comment:

// Only pay attention to the flags parameter if we haven't already
// set the task delete policies.
if (this->flags_ == 0)
ACE_SET_BITS (flags_, flags);

However, the value 0 IS a delete policy, it says to delete NONE.
If stream.close() is called, then the default stream close argument
of 3 is passed down to the module close inside Stream::pop()
and the conditional code above changes the delete policy
from M_DELETE_NONE to M_DELETE, which triggers the attempt
by the module to delete its tasks.

I believe the solution to this might be to introduce either
a default flags_ value of -1, and change the test above
to check for flags_ < 0, or to introduce another member to
the enumeration, eg. M_DELETE_UNKNOWN (delete policy unknown,
not set).

There is also some confusion with regard to the use of flags
in the Streams module. The flags parameter is used to determine
both the module tasks deletion policy AND the deletion policy
of the module itself (I believe this is incorrect). For example:

template int
ACE_Stream::pop (int flags)
{
ACE_TRACE ("ACE_Stream::pop");
if (this->stream_head_->next () == this->stream_tail_)
return -1;
else
{
// Skip over the ACE_Stream head.
ACE_Module *top_mod = this->stream_head_->next ();
ACE_Module *new_top = top_mod->next ();

this->stream_head_->next (new_top);

// Close the top ACE_Module.
top_mod->close (flags);

>>>> This line calls module close, with a flags parameter that determines
>>>> the task deletion policy, possibly over-riding M_DELETE_NONE
>>>> with M_DELETE and causing a SEGV. (as discussed above)

// Don't delete the Module unless the flags request this.
if (flags != ACE_Module::M_DELETE_NONE)
delete top_mod;

>>>> Hang on, if I have stack allocated tasks in a dynamically
>>>> allocated module, then this line of code will not delete
>>>> the dynamically allocated module!
>>>> Similarly, if I have dynamically allocated tasks in a
>>>> stack allocated module, this code will try to delete the
>>>> statically allocated module!
>>>> The task delete flags can NOT be used to determine both
>>>> the deletion policy of the tasks AND the module.

this->stream_head_->writer ()->next (new_top->writer ());
new_top->reader ()->next (this->stream_head_->reader ());
return 0;
}
}

Its not clear to me why the Stream::close flags are not just
the deletion policy of the MODULE, since the module deletion
policy has ALREADY been setup during the creation of the
module. In that case, the top_mod call above should
just be top_mod->close(), and the Stream could just
have its own enumeration to indicate the deletion
policy of the modules it contains.

One could argue that if you always dynamically allocate your
tasks and your modules, that you'll never see this issue.
True, but the code still has bugs. I'd prefer to report, and
if possible assist in fixing the bugs to make ACE a better
package.

Here is a set of tests, one of which exibits the SEGV:

Test number:
1. Dynamic tasks
2. Dynamic tasks, stream.close(0)
3. Stack tasks ** will SEGV **
4. Stack tasks, stream.close(0)

http://www.ovro.caltech.edu/~dwh/ace/stream_segv.cpp

The third test SEGV's since exit from main triggers the
default Stream::close(M_DELETE) call, which over-writes the
M_DELETE_NONE policy setup in the module.


I'm sorry for posting questions so much. I figure this is the
ACE users group, and I am a new ACE user. I'm kind of surprized
to find I am the first to stumble over these issues.
Especially since I only stumbled over them by starting
from the example in C++NPv2. If an ACE developer could
respond as to whether I should come up with a set of tests,
and a patch to the module/stream files. Then I'll happily
do that.


Cheers
Dave Hawkins
Caltech.
   

Copyright © 2006 knowledge-database   -   All rights reserved