Solved

delete blocking at a semaphore...

Posted on 2000-02-16
11
222 Views
Last Modified: 2010-04-02
I am compiling an multithread app under solaris 2.5.1 fully patched, and running on solaris 7.

The app locks up, including all other threads with zero CPU usage.

I allocate a char array, then use it, then I free it.

Is there a known problem with 2.5.1 compilation, and solaris7 running? if not, how do I fix this bug? It is not readilly repeatable.

The following is a GDB attach...

Symbols already loaded for /usr/lib/libthread.so.1
0xdf6c25d1 in _lwp_sema_wait () from /usr/lib/libc.so.1
(gdb) bt
#0  0xdf6c25d1 in _lwp_sema_wait () from /usr/lib/libc.so.1
#1  0xdf61cc61 in _park () from /usr/lib/libthread.so.1
#2  0xdf61c8d7 in _swtch () from /usr/lib/libthread.so.1
#3  0xdf61df52 in _mutex_adaptive_lock () from /usr/lib/libthread.so.1
#4  0xdf61dd6c in mutex_lock () from /usr/lib/libthread.so.1
#5  0xdf6ce8a5 in free () from /usr/lib/libc.so.1
#6  0xdfaf259c in __builtin_delete () from /gems/lib/liblogging.so.1
#7  0xdfaf25e7 in __builtin_vec_delete () from /gems/lib/liblogging.so.1
#8  0x819639c in CallShell::activate (this=0x82a98f8) at CallShell.cpp:160


0
Comment
Question by:nigel5
  • 6
  • 5
11 Comments
 
LVL 22

Expert Comment

by:nietod
Comment Utility
Is it possible that you've corrupted the heap?  Look for cases where you might write to memory past the ends of a allocated block of memory (not necessarily this block)

Is the code short enough to post?
0
 

Author Comment

by:nigel5
Comment Utility
I have a CppString class that has been unit tested to death, so there is nothing in there. I do use heap allocations, but the only place I allocate an array of chars is in the function outlined.

This code has not changed in ages, and it has been called lots, so this is a very recent bug.

The code (fragmented)..

bool CallShell::activate()
{
   vector<CppString> args = getArgs();  // returns the command line to call
   unsigned num = args.size() + 1;      // plus one for the NULL
   char** sys = new char*[num];
   int stat_avail = 0;                  // set when command completed
   int status = 1;                      // exit status of the command

   // fill system command line
   for(int i = 0; i < num; i++)
   {
      // CppString has a char* operator, passing back its reference
      sys[i] = args[i];
   }
   sys[num] = NULL;

   my_bexec(sys[0], sys, &stat_avail, &stat);
   while(stat_avail == 0)
   {
      // sleep for a 1/10 second waiting for child
      my_usleep(10000);
   }

   // no need to delete sys[0-num] as destructor of vector deletes its
   // elements, this deletes the buffers stored in this array.
   // delete will call destructors on each element, but this is a char*
   // for which there is no destructor.
   delete [] sys;

   // rturn exit status.
   return status == 0;
}
0
 

Author Comment

by:nigel5
Comment Utility
Oh, the stack trace provided in the original question occurs in the line...

   delete [] sys;
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
You are corrupting the heap.

char** sys = new char*[num];
    *   *   *
sys[num] = NULL;

the allocation allocates num items that are indexed from 0 to num-1.  but then you set the "numth" one to NULL.

You need to allocate num+1 items.
0
 

Author Comment

by:nigel5
Comment Utility
Oops, sorry, typo, the chunk of code (cut and pasted this time)...

l is the list of args
ssd is the secure shell directory
call() returns the command

      int num = l.size() + 1; // plus 1 for sys command
      char** sys = new char* [num + 1]; // plus 1 for NULL terminator
      CppString c = ssd + "/" + call();
      sys[0] = c;

      for(int i = 1; i < num; i++)
      {
         if(super_debug) cout << "adding arg to call args : " << l[i-1] << endl;
         sys[i] = l[i-1];
      }
      sys[num] = NULL;
0
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 
LVL 22

Expert Comment

by:nietod
Comment Utility
What is my_bexec?
0
 

Author Comment

by:nigel5
Comment Utility
my_bexec is a wrapper round vfork, it has a whole management thing around it, waiting for SIGCHLD and all that.

Signals are wrapped in the way outlined by the POSIX standard.
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
Could it be messing uop memory?  What does it do with sys?

We're not psychics so we can't find the bug without seeing the code an knowing a lot more about yoru program.  You'll either have to provide more info or work on debugging it yourself.

You might try commenting out other portions of the program and seee fi the bug can be made to go away, then add parts back again and see if it appears and in this way home in on the error.
0
 

Author Comment

by:nigel5
Comment Utility
The bug is very *VERY* intermitent, in fact it is the first time it has happened. The reason I am asking is because new and delete have kernel dependant functionality, and I was wondering if there was a known incompatibility between compiling on a lower version of Solaris, and running on a different one. new and delete should never fail but for corruption (which should be picked up with a profiler i.e. purify/insure++), or due to some other inconsistency in OS.

there currently is a memory leak under investigation, using a C interface, but the fragment where this falls over has been checked, and is clean, there are no frees in this section. why would a mutex stay locked if a free deletes memory allocated with new?

my_bexec does nothing with the passed char** arg but run a vfork, and then a bexec to start another process. The status, and stat_avail, are stored in a list. When the child process exits, it sends a SIGCHLD, message, the exit status value is then put into status, and sta_avail set to 1.
0
 
LVL 22

Accepted Solution

by:
nietod earned 50 total points
Comment Utility
>> I was wondering if there was a known
>> incompatibility between compiling on a
>> lower version of Solaris, and running on
>> a different one
That would be EXTREMELY unlikely.  Programs are designed fundamentally to be forward compatible because you never know what version of the OS it will run under.  And if a mistake was made in thid design, it would almost certainly be detected as soon as the OS was released, so it is unlikely tha you would stumble upon it.
0
 

Author Comment

by:nigel5
Comment Utility
Thanks.
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

728 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now