 |
Ok, so I am not going crazy :)
The Streams framework does not appear work as I understand it should, when you use it with a module containing stack-allocated or member variable based Tasks.
First, a member variable example of this problem:
1. Issue with C++NPv2 streams example ---------------------------------------
My earlier postings originated from an example test I had written based on the Streams example from p302 of C++NPv2.
The problem is that for member variable tasks, such as the one shown on p303 in the LogRec_Module template definition, when you call any member functions of the task related to being part of a module (that should have been setup when the task was inserted into the stream) the functions are not setup! For example, if a task is in a module, the module() member points to the module it is contained within.
However, if you add the code
if (module()) { ACE_DEBUG((LM_DEBUG, "Module is set")); } else { ACE_DEBUG((LM_DEBUG, "Module is NOT set")); }
to the open() and svc() functions within display_logfile.cpp and rebuild it, you will get the message that the module is NOT set. This was tested under both 5.3b (the APG source), and 5.4 (downloaded from Riverace sometime this week).
2. SEGV with stack allocated tasks in a stream -----------------------------------------------
In the process of trying to isolate the above issue, I wrote several tests, and one of those tests SEGVs for what appears to be a problem with the streams close() method. I combined a couple of working tests with the SEGV test into the following example: http://www.ovro.caltech.edu/~dwh/ace/simple_stream_segv.cpp The three tests in the code are:
1. Stream test with dynamically allocated tasks and module 2. Module delete test (with stack-based tasks) 3. Stream test with stack-based tasks and dynamically allocated module
run the tests using ./simple_stream_segv
Results:
1. Test 1 behaves as I would expect Streams to operate. The tasks within the module have all their 'task-in-a-module' properties setup correctly, i.e., they have their module pointers setup, module name, is_reader/writer etc.
Note that when you run this test, because the tasks are dynamically allocated, the messages from their destructors appear after the 'close the stream' message. The close method of the stream is probably calling the destructor of the module, which is responsible for deleting the tasks.
2. Test 2 dynamically allocates a module containing two stack-allocated tasks, and the module is told not to delete the tasks by passing M_DELETE_NONE. The module is then deleted, to confirm that it does not try to delete the reader or writer tasks.
The module is deleted correctly. (This is a precurser to the next test)
Note that when you run this test, because the tasks are stack allocated, the messages from their destructors appear after the 'exiting' message, once those objects go out of scope.
3. The module from test 2 is inserted into a stream. When close() is called on the stream, it tries to deallocate the tasks, causing a SEGV.
You can tell that the stream must be trying to delete the task too soon, as you see the task destructor output. In test 2, the destructor output comes when main goes out of scope.
Test 2 shows that if the module is deleted, there is no SEGV, so either the stream close method is trying to delete the tasks directly (I haven't had a chance to look at the code yet), or the module delete flag was changed somewhere in the code from M_DELETE_NONE to some other value that is causing it to attempt to delete the tasks.
Can anyone more knowledgeable with the implementation comment on these observations? I'll try to track down the problem if someone agrees with me that this is a real bug. Dave
|
|