In order to debug a threaded application, you need
to link with -lcwd_r instead of -lcwd.

Threading only works on linux so far.
Use ./configure --disable-threading on other OS.

A core dump produced by a kernel 2.4 does not
contain enough information for gdb to debug all
threads.  Only the core dumping thread is dumped
and the other threads continue to run for a while.
There exists a kernel patch written by Intel/IBM
that fixes this problem; please read
http://www-124.ibm.com/developer/opensource/linux/projects/mtcoredumps/
Note: This patch, multithreaded coredumps support patch, has
      already been included in kernel 2.5.47 and higher.

The minimal version of gdb needed to debug multi-threaded
applications in a meaningful way has always been 5.2. However,
when using g++ 3.x or higher, you should be using at least gdb 6.0
(but using the _latest_ version of gdb is always the best idea!).
Try not to use -O2 or -fomit-frame-pointer if you want source
file and line numbers that make sense ;).

Be aware that gdb does hardly support namespaces and
will therefore frequently not find types or variables
in namespaces.  It doesn't look like that this will be
fixed very soon (2002-05-27) (see the thread that belongs
to http://sources.redhat.com/ml/gdb/2002-05/msg00278.html)
In order to specify namespaces in gdb you will have to
type them in full and put single quotes around it.
For example:
(gdb) p *(('some::name::space::ptr'*)0x8039214)

In order to debug NPTL (Native POSIX Threads Library)
you will need the gdb that comes with RedHat 9 (or fedora).
At the moment of writing (2003/6/27), the CVS HEAD of gdb
does not work with NPTL.

As of libcwd-0.99.31, support for NPTL was added. The
Thread Specific Data of libcwd now works as follows:
1) The first two calls to calloc() are assumed not to
   be internal but to be part of the initialization
   of libpthread.  At that moment there is no thread
   specific (or thread local) storage possible.
   The location lookup and the inclusion on the map<>
   that stores all allocations is delayed till the
   third call to calloc().  This call is assumed to
   be done before we reach main().  The two first
   calloc's are added as invisible allocations (don't
   show up in list_allocations_on()).
2) While configuring libcwd, the environment variable
   THREADSMAX is used as the maximum number of simultaneous
   running threads.  At the moment this means that
   this is the size of a static array with basic
   Thread Specific Data (TSD) for libcwd (basic because
   it doesn't contain the TSD that is needed to actually
   write debug output: debug output is turned off).
   When a new thread calls malloc(), or new, for the
   first time (or any other libcwd function, most likely
   turning on libcw_do or a debug channel), it is
   detected that this is a new thread and the new thread
   gets assigned one of the entries of this static array
   to be used as TSD.  As soon as possible the TSD is
   initialized fully (so writing debug output becomes
   possible) and a pthread key is added to be used as TSD.
   After initialization (a few miliseconds(?) after thread
   creation) the static array TSD is released again
   and the new thread now uses the pthread key.
3) When a thread terminates, libpthread will call a
   destructor call back function of the above key - along
   with any other user provided call backs for other keys.
   The destructor routine of the libcwd key will re-add
   itself three times without taking action, allowing
   user destructor routines to finish first,
   still able to use libcwd at that moment.  Finally
   it will release the key and move the TSD back to
   a free entry in the static array.  From that moment
   on debug output is inhibited, but no user code will
   be called anymore usually.  Basically, all that
   happens after that is that libpthread possibly calls
   free() to release the second level key hash table(s)
   it has (once per 32 keys).  These frees will then not
   be visible.  It is not possible to exactly determine
   when a thread finishes - therefore the following
   trick is being used: When a TSD struct is requested
   from within a call to free() (or delete to accommodate
   possible user key destruction routines that also re-add
   themselfs, or other keys, recursively more often than
   PTHREAD_DESTRUCTOR_ITERATIONS and which are called
   later then libcwd's destructor routine, and which use
   delete), then the existing static TSD is returned
   and when there is no static TSD that matches the
   thread - it is assumed that the array was full, and
   a new static TSD is returned without initializing it
   or creating a new pthread key for it (it is marked
   again as a 'terminating' thread).  However, when a TSD
   is requested from anywhere else - then libcwd assumes
   this is a NEW thread, and the TSD will be initialized
   when it doesn't already exist.
 IMPORTANT: This means that you are not allowed to *allocate*
   memory, or to write debug output (or use any other libcwd
   function), from a key destructor routine of a key that is
   added recursively from another, or the same, key destructor
   routine.
   The best thing to do is to avoid using pthread_setspecific()
   inside a key destructor routine - or at least not do that
   more often than PTHREAD_DESTRUCTOR_ITERATIONS - 2 times.

