Hi Vlad,
Thanks for a patch to this problem.
I think this patch ensures that we never touches abt member variables of
the memory manager object after it has been destructed but just touches
the globally available "memoryManagerAvailable" variable.
I have applied the patch and rerun my test to verified that it solves
the problem.
OK to push!
..olav
PS You should be glad that Hakan is on vacation otherwise you would have
to make a test case for this :-)
Vladislav Vaintroub wrote:
> #At file:///C:/bzr/wacko-new-delete/
>
> 2769 Vladislav Vaintroub 2008-08-06
> Bug#38592: crash on exit() on Solaris
>
> The problem is that overridden new() operator is referencing
> static memoryManager object that has already been destroyed.
>
> Solution is to track whether memoryManager is still alive via
> another static variable memoryManagerAlive, set is set to true
> in the constructor and to false in the destructor.
>
> If memory manager is not alive, new() and delete() will use
> plain malloc()/free().
> modified:
> storage/falcon/MemMgr.cpp
> storage/falcon/MemMgr.h
>
> === modified file 'storage/falcon/MemMgr.cpp'
> --- a/storage/falcon/MemMgr.cpp 2008-08-01 17:56:28 +0000
> +++ b/storage/falcon/MemMgr.cpp 2008-08-06 10:33:37 +0000
> @@ -72,8 +72,9 @@ static const int guardBytes = sizeof(lon
> const int validateMinutia = 16;
>
> // Nominal memory limits at startup--final values set during initialization
> +bool memoryManagerAlive;
>
> -static MemMgr memoryManager(defaultRounding, FREE_OBJECTS_SIZE, HEAP_SIZE);
> +static MemMgr memoryManager(defaultRounding, FREE_OBJECTS_SIZE,
> HEAP_SIZE,&memoryManagerAlive);
> static MemMgr recordManager(defaultRounding, 2, HEAP_SIZE);
> //static MemMgr recordObjectManager (defaultRounding, sizeof(RecordVersion) + 100,
> HEAP_SIZE);
> static MemControl memControl;
> @@ -121,6 +122,9 @@ struct Client {
>
> void* MemMgrAllocateDebug (unsigned int s, const char *file, int line)
> {
> + if(!memoryManagerAlive)
> + return malloc(s);
> +
> void *object = memoryManager.allocateDebug(s, file, line);
>
> if (object == stopAddress)
> @@ -134,6 +138,11 @@ struct Client {
>
> void MemMgrRelease (void *object)
> {
> + if (!memoryManagerAlive)
> + {
> + free(object);
> + return;
> + }
> /***
> if (object == stopAddress)
> printf ("MemMgrRelease at %p\n", stopAddress);
> @@ -162,12 +171,18 @@ struct Client {
>
> void* MemMgrAllocate (unsigned int s)
> {
> - return memoryManager.allocate (s);
> + if(!memoryManagerAlive)
> + return malloc(s);
> + else
> + return memoryManager.allocate (s);
> }
>
> void MemMgrRelease (void *object)
> {
> - memoryManager.release (object);
> + if(!memoryManagerAlive)
> + free(object);
> + else
> + memoryManager.release (object);
> }
>
> void* MemMgrRecordAllocate (int size, const char *file, int line)
> @@ -269,7 +284,7 @@ void MemMgrLogDump()
> }
>
>
> -MemMgr::MemMgr(int rounding, int cutoff, int minAlloc)
> +MemMgr::MemMgr(int rounding, int cutoff, int minAlloc, bool *alive)
> {
> signature = defaultSignature;
> roundingSize = rounding;
> @@ -293,6 +308,11 @@ MemMgr::MemMgr(int rounding, int cutoff,
> //freeBlocks.nextLarger = freeBlocks.priorSmaller = &freeBlocks;
> //freeBlockTree = NULL;
> junk.larger = junk.smaller = &junk;
> + isAlive = alive;
> + if(alive)
> + {
> + *alive = true;
> + }
> }
>
>
> @@ -317,6 +337,8 @@ MemMgr::~MemMgr(void)
> bigHunks = bigHunk->nextHunk;
> releaseRaw (bigHunk);
> }
> + if (isAlive)
> + *isAlive = false;
> }
>
> MemBlock* MemMgr::alloc(int length)
> @@ -500,19 +522,11 @@ void* MemMgr::allocate(int size)
> int length = ROUNDUP(size, roundingSize) + OFFSET(MemBlock*, body) + guardBytes;
> MemBlock *memory;
>
> - if (signature)
> - {
> - length = ROUNDUP(length, sizeof (double));
> - memory = alloc (length);
> - memory->pool = this;
> - }
> - else
> - {
> - length = ROUNDUP(size, defaultRounding) + OFFSET(MemBlock*, body) + sizeof(long);
> - memory = (MemBlock*) allocRaw(length);
> - memory->pool = NULL;
> - memory->length = length;
> - }
> + ASSERT(signature == defaultSignature);
> + length = ROUNDUP(length, sizeof (double));
> + memory = alloc (length);
> + memory->pool = this;
> +
>
> #ifdef MEM_DEBUG
> memset (&memory->body, INIT_BYTE, size);
> @@ -533,19 +547,10 @@ void* MemMgr::allocateDebug(int size, co
> int length = ROUNDUP(size, roundingSize) + OFFSET(MemBlock*, body) + guardBytes;
> MemBlock *memory;
>
> - if (signature)
> - {
> - length = ROUNDUP(length, sizeof (double));
> - memory = alloc (length);
> - memory->pool = this;
> - }
> - else
> - {
> - length = ROUNDUP(size, defaultRounding) + OFFSET(MemBlock*, body) + sizeof(long);
> - memory = (MemBlock*) allocRaw(length);
> - memory->length = length;
> - memory->pool = NULL;
> - }
> + ASSERT(signature == defaultSignature);
> + length = ROUNDUP(length, sizeof (double));
> + memory = alloc (length);
> + memory->pool = this;
>
> #ifdef MEM_DEBUG
> memory->fileName = fileName;
>
> === modified file 'storage/falcon/MemMgr.h'
> --- a/storage/falcon/MemMgr.h 2008-05-14 18:39:57 +0000
> +++ b/storage/falcon/MemMgr.h 2008-08-06 10:33:37 +0000
> @@ -106,7 +106,8 @@ public:
> class MemMgr
> {
> public:
> - MemMgr(int rounding=defaultRounding, int cutoff=defaultCutoff, int
> minAllocation=defaultAllocation);
> + MemMgr(int rounding=defaultRounding, int cutoff=defaultCutoff,
> + int minAllocation=defaultAllocation, bool *alive = NULL);
> MemMgr(void* arg1, void* arg2);
> virtual ~MemMgr(void);
>
> @@ -129,6 +130,7 @@ public:
> uint64 activeMemory;
> int blocksAllocated;
> int blocksActive;
> + bool *isAlive;
>
> friend void MemMgrLogDump();
>
>
>
>