Mirror of the gdb mailing list
 help / color / mirror / Atom feed
* Re: configuring gdb 5.x for use with threads
       [not found] <20011102102321.D6507@a59252.upc-a.chello.nl>
@ 2001-11-06 21:13 ` peter
  2001-11-07  2:30   ` Kevin Buettner
  0 siblings, 1 reply; 4+ messages in thread
From: peter @ 2001-11-06 21:13 UTC (permalink / raw)
  To: gdb

[-- Attachment #1: Type: text/plain, Size: 2470 bytes --]

Hi,.

I rebuild my glibc+linuxthreads 2.2.4 agains my linuxkernel 2.4.15-pre5 SMP, a libthread_db-1.0.so was build.
I rebuild gdb 2001-11-16-cvs, it detected thread_db.h, even loads libthread_db.so.1 on startup. However I still can't debug multi-threaded apps. 

here's some output and the programm used to generate it.

can someone please tell me what I've done wrong or point me to the docs, I'll read.

regards,
Peter Zijlstra

---

peter@twins queue $ gcc -ggdb3 -o test test.c queue.c -D_REENTRANT -lpthread
peter@twins queue $ gdb ./test
GNU gdb 2001-11-16-cvs
Copyright 2001 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...
(gdb) run
Starting program: /home/peter/code/queue/./test 

Program received signal SIG32, Real-time event 32.
0x40068bc9 in sigsuspend () from /lib/libc.so.6
(gdb) bt
#0  0x40068bc9 in sigsuspend () from /lib/libc.so.6
#1  0x4002d6cf in pthread_getconcurrency () from /lib/libpthread.so.0
#2  0x4002ce99 in pthread_create () from /lib/libpthread.so.0
#3  0x08049206 in queue_create (queue_size_=16, workers_=3, reaper_=0x804890c <my_reaper>) at queue.c:160
#4  0x0804896e in main (argc=1, argv=0xbffff834) at test.c:38
#5  0x40057921 in __libc_start_main () from /lib/libc.so.6
(gdb) cont
Continuing.

Program received signal SIG32, Real-time event 32.
0x40068bc9 in sigsuspend () from /lib/libc.so.6
(gdb) 
Continuing.

Program received signal SIG32, Real-time event 32.
0x40068bc9 in sigsuspend () from /lib/libc.so.6
(gdb) 
Continuing.

Program received signal SIG32, Real-time event 32.
0x40068bc9 in sigsuspend () from /lib/libc.so.6
(gdb) 
Continuing.
==> starting packet 2, 12582912
==> starting packet 1, 13369344
==> starting packet 3, 12845056
<== ending packet: 2

Program received signal SIG32, Real-time event 32.
0x40068bc9 in sigsuspend () from /lib/libc.so.6
(gdb) ==> starting packet 4, 14155776
<== ending packet: 1
==> starting packet 5, 14417920
<=> wasting packet 1

<snip>

<== ending packet: 15
<=> wasting packet 15
<=> wasting packet 16
Quit
(gdb) info threads
(gdb) cont
Continuing.
==> starting packet 17, 9175040
==> starting packet 19, 8650752
==> starting packet 18, 8388608
<== ending packet: 17

...

[-- Attachment #2: test.c --]
[-- Type: text/plain, Size: 977 bytes --]

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>


#include "queue.h"

typedef struct {
	long long		wait;
	int		seq;
} my_data_t;

void my_processor( void * arg_) {
	my_data_t * data = (my_data_t *)arg_;

	if ( !data) return;

	printf( "==> starting packet %d, %lld\n", data->seq, data->wait);
	fflush( stdout);
	while ( --data->wait);
	printf( "<== ending packet: %d\n", data->seq);
	fflush( stdout);
}

void my_reaper( void * arg_) {
	my_data_t * data = (my_data_t *)arg_;

	printf( "<=> wasting packet %d\n", data->seq);
	fflush( stdout);

	free( arg_);
}

int main( int argc, char ** argv) {
	queue_t * work;
	int i;

	work = queue_create( 16, 3, my_reaper);

	sleep(1);

	for ( i=1; i<50; i++) {
		my_data_t * data = (my_data_t *)malloc( sizeof( my_data_t));
		data->seq = i;
		data->wait = (long long)(50^i) << 18;

		queue_insert( work, my_processor, (void *)data);
	}

	queue_insert_last( work);
	queue_wait_last( work);
	queue_destruct( work);

	return 0;
}

[-- Attachment #3: queue.c --]
[-- Type: text/plain, Size: 4713 bytes --]

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#include "queue.h"

//#define INC( q, x)	++(x) %= (q)->_queue_size;
#define INC( q, x)	({ ++(x); (x) %= (q)->_queue_size; (x); })

//#define pthread_mutex_lock( a) { pthread_mutex_lock( a); printf( "%p: got mutex\n", pthread_self()); fflush( stdout); }

static queue_elem_t * queue_create_elem( process_func_t func_, void * data_) {
	queue_elem_t * qe = (queue_elem_t *)malloc( sizeof( queue_elem_t));
	if ( !qe) return NULL;

	qe->_data = data_;
	qe->_process = func_;
	qe->_done = 0;

	pthread_mutex_init( &qe->_elem_lock, NULL);

	return qe;
}

static queue_elem_t * queue_get_next( queue_t * q_) {
	size_t head;
	queue_elem_t * qe = NULL;
	
	pthread_mutex_lock( &q_->_queue_lock);
	while ( q_->_size != q_->_queue_size && 
			q_->_next == q_->_head && 
			!q_->_quit)
		pthread_cond_wait( &q_->_queue_insert, &q_->_queue_lock);
	if ( !q_->_quit) {
		qe = q_->_queue[ q_->_next];
		INC( q_, q_->_next);
	}
	pthread_mutex_unlock( &q_->_queue_lock);

	return qe;
}

static void * queue_worker( void * arg_) {
	queue_t * q = (queue_t *)arg_;

	while ( !q->_quit) {
		queue_elem_t * qe = queue_get_next( q);
		if ( !qe) continue;
		pthread_mutex_lock( &qe->_elem_lock);
		if ( qe->_process && qe->_data)
			qe->_process( qe->_data);
		qe->_done = 1;
		pthread_cond_signal( &q->_elem_done);
		pthread_mutex_unlock( &qe->_elem_lock);
	}

	return NULL;
}

static void * queue_reaper( void * arg_) {
	queue_t * q = (queue_t *)arg_;

	while ( !q->_quit) {
		queue_elem_t * qe = NULL;
		pthread_mutex_lock( &q->_queue_lock);
		while ( q->_tail == q->_next && !q->_quit)
			pthread_cond_wait( &q->_elem_done, &q->_queue_lock);
		if ( !q->_quit) {
			qe = q->_queue[ q->_tail];
			q->_queue[ q->_tail] = NULL;
			INC( q, q->_tail);
			--q->_size;
			pthread_cond_signal( &q->_queue_remove);
		}
		pthread_mutex_unlock( &q->_queue_lock);
		if ( !qe) continue;

		// XXX: should sync if _elem_done was not tail elem.
		pthread_mutex_lock( &qe->_elem_lock);
		assert( qe->_done);
		if ( !qe->_process && !qe->_data) q->_last = 1;
		else q->_reap( qe->_data);
		pthread_mutex_unlock( &qe->_elem_lock);
	}

	return NULL;
}

void queue_insert( queue_t * q_, process_func_t func_, void * data_) {
	size_t head;
	queue_elem_t * qe = queue_create_elem( func_, data_);
	if ( !qe) return;

	pthread_mutex_lock( &q_->_queue_lock);
	while ( q_->_size && q_->_tail == q_->_head && !q_->_quit)
		pthread_cond_wait( &q_->_queue_remove, &q_->_queue_lock);
	if ( !q_->_quit) {
		q_->_last = 0;
		assert( q_->_queue[ q_->_head] == NULL);
		q_->_queue[ q_->_head] = qe;
		INC( q_, q_->_head);
		++q_->_size;
		pthread_cond_signal( &q_->_queue_insert);
	}
	pthread_mutex_unlock( &q_->_queue_lock);
}

void queue_insert_last( queue_t * q_) {
	queue_insert( q_, NULL, NULL);
}

void queue_wait_last( queue_t * q_) {
	pthread_mutex_lock( &q_->_queue_lock);
	while ( !q_->_last)
		pthread_cond_wait( &q_->_queue_remove, &q_->_queue_lock);
	pthread_mutex_unlock( &q_->_queue_lock);
}

queue_t * queue_create( size_t queue_size_, size_t workers_, process_func_t reaper_) {
	queue_t * q;
	int i;
	int rc;

	if ( workers_ < 1 || queue_size_ < workers_ || !reaper_)
		return NULL;

	q = (queue_t *)malloc( sizeof( queue_t));
	if ( !q) return NULL;
	
	q->_queue_size = queue_size_;
	q->_queue = (queue_elem_t **)malloc( queue_size_ * sizeof( queue_elem_t *));
	if ( !q->_queue) {
		free( q);
		return NULL;
	}
	for ( i=0; i<queue_size_; i++)
		q->_queue[i] = NULL;

	q->_head = q->_tail = q->_next = q->_size = 0;

	q->_quit = 0;
	q->_reap = reaper_;
	q->_last = 0;

	pthread_mutex_init( &q->_queue_lock, NULL);
	pthread_cond_init( &q->_queue_insert, NULL);
	pthread_cond_init( &q->_queue_remove, NULL);
	pthread_cond_init( &q->_elem_done, NULL);

	q->_workers = workers_;
	q->_tid_workers = (pthread_t *)malloc( workers_ * sizeof( pthread_t));
	if ( !q->_tid_workers) {
		free( q->_queue);
		free( q);
		return NULL;
	}

	pthread_mutex_lock( &q->_queue_lock);
	for ( i=0; i<workers_; i++)
		pthread_create( &q->_tid_workers[i], NULL, queue_worker, (void *)q);

	pthread_create( &q->_tid_reaper, NULL, queue_reaper, (void *)q);
	pthread_mutex_unlock( &q->_queue_lock);

	return q;
}

void queue_destruct( queue_t * q_) {
	int i;
	
	q_->_quit = 1;
	
	for ( i=0; i<q_->_workers; i++) {
		pthread_cond_broadcast( &q_->_queue_insert);
		pthread_join( q_->_tid_workers[i], NULL);
	}

	pthread_cond_signal( &q_->_elem_done);
	pthread_join( q_->_tid_reaper, NULL);

	pthread_mutex_destroy( &q_->_queue_lock);
	pthread_cond_destroy( &q_->_queue_insert);
	pthread_cond_destroy( &q_->_queue_remove);
	pthread_cond_destroy( &q_->_elem_done);
	
	free( q_->_tid_workers);
	free( q_->_queue);
	free( q_);
}

[-- Attachment #4: queue.h --]
[-- Type: text/plain, Size: 1510 bytes --]

#ifndef __QUEUE_INCLUDED
#define __QUEUE_INCLUDED

#include <pthread.h>

typedef void (*process_func_t)( void *);

typedef struct {
	void *			_data;
	process_func_t	_process;
	volatile int	_done;

	pthread_mutex_t	_elem_lock;
} queue_elem_t;

typedef struct {
	size_t			_queue_size;
	queue_elem_t **	_queue;
	volatile size_t	_head, _tail, _next, _size;

	volatile int	_quit;
	process_func_t	_reap;
	volatile int	_last;

	pthread_mutex_t	_queue_lock;
	pthread_cond_t	_queue_insert, _queue_remove;
	pthread_cond_t	_elem_done;

	size_t			_workers;
	pthread_t *		_tid_workers;
	pthread_t		_tid_reaper;
} queue_t;

/*
	queue_insert( queue_t *, process_func_t func, void * data) 
		inserts a job into the queue; executes: func( data)
*/
void queue_insert( queue_t *, process_func_t, void *);

/*
	queue_insert_last( queue_t *); same as queue_insert( queue_t *, NULL, NULL)
*/
void queue_insert_last( queue_t *);

/*
	queue_wait_last( queue_t *)
		waits for a (NULL,NULL) job to be processed

	XXX: queue_insert resets the last flag; 
*/
void queue_wait_last( queue_t *);

/*
	queue_create( size_t queue_size, size_t workers, process_func_t reaper)
	
	creates a queue of size #queue_size with #workers workers
	and calls reaper( job.data) for each enqueued job when done
	and in sequence

	returns: queue_t * on success; NULL on error;
*/
queue_t * queue_create( size_t, size_t, process_func_t);

/*
	queue_destruct( queue_t *)

	frees resources allocated by queue_create;
*/
void queue_destruct( queue_t *);

#endif

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: configuring gdb 5.x for use with threads
  2001-11-06 21:13 ` configuring gdb 5.x for use with threads peter
@ 2001-11-07  2:30   ` Kevin Buettner
  2001-11-08  7:09     ` peter
  0 siblings, 1 reply; 4+ messages in thread
From: Kevin Buettner @ 2001-11-07  2:30 UTC (permalink / raw)
  To: peter, gdb

On Nov 17,  2:27pm, peter@a59252.upc-a.chello.nl wrote:

> I rebuild my glibc+linuxthreads 2.2.4 agains my linuxkernel
> 2.4.15-pre5 SMP, a libthread_db-1.0.so was build.

Make sure that you have the following patch (to glibc) applied.  I too
was having problems with debugging multithreaded programs that were
linked against libraries from glibc 2.2.4.  This patch fixed the
problems that I was seeing...

2001-10-05  Kevin Buettner  <kevinb@cygnus.com>

	* pthread.c (__linuxthread_pthread_sizeof_descr): Change name
	to __linuxthreads_pthread_sizeof_descr to match name used by
	symbol_list_arr[LINUXTHREADS_PTHREAD_SIZEOF_DESCR] in
	linuxthreads_db/td_symbol_list.c.

===================================================================
RCS file: /cvs/glibc/libc/linuxthreads/pthread.c,v
retrieving revision 1.86
retrieving revision 1.87
diff -u -r1.86 -r1.87
--- libc/linuxthreads/pthread.c	2001/09/12 03:51:41	1.86
+++ libc/linuxthreads/pthread.c	2001/10/07 20:19:16	1.87
@@ -211,7 +211,7 @@
                                               h_descr);
 const int __pthread_offsetof_pid = offsetof(struct _pthread_descr_struct,
                                             p_pid);
-const int __linuxthread_pthread_sizeof_descr
+const int __linuxthreads_pthread_sizeof_descr
   = sizeof(struct _pthread_descr_struct);
 
 /* Forward declarations */



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: configuring gdb 5.x for use with threads
  2001-11-07  2:30   ` Kevin Buettner
@ 2001-11-08  7:09     ` peter
  2001-11-08  7:53       ` Daniel Jacobowitz
  0 siblings, 1 reply; 4+ messages in thread
From: peter @ 2001-11-08  7:09 UTC (permalink / raw)
  To: Kevin Buettner; +Cc: gdb

On Sat, Nov 17, 2001 at 09:53:49AM -0700, Kevin Buettner wrote:
> On Nov 17,  2:27pm, peter@a59252.upc-a.chello.nl wrote:
> 
> > I rebuild my glibc+linuxthreads 2.2.4 agains my linuxkernel
> > 2.4.15-pre5 SMP, a libthread_db-1.0.so was build.
> 
> Make sure that you have the following patch (to glibc) applied.  I too
> was having problems with debugging multithreaded programs that were
> linked against libraries from glibc 2.2.4.  This patch fixed the
> problems that I was seeing...
> 
> 2001-10-05  Kevin Buettner  <kevinb@cygnus.com>
> 
> 	* pthread.c (__linuxthread_pthread_sizeof_descr): Change name
> 	to __linuxthreads_pthread_sizeof_descr to match name used by
> 	symbol_list_arr[LINUXTHREADS_PTHREAD_SIZEOF_DESCR] in
> 	linuxthreads_db/td_symbol_list.c.
> 
> ===================================================================
> RCS file: /cvs/glibc/libc/linuxthreads/pthread.c,v
> retrieving revision 1.86
> retrieving revision 1.87
> diff -u -r1.86 -r1.87
> --- libc/linuxthreads/pthread.c	2001/09/12 03:51:41	1.86
> +++ libc/linuxthreads/pthread.c	2001/10/07 20:19:16	1.87
> @@ -211,7 +211,7 @@
>                                                h_descr);
>  const int __pthread_offsetof_pid = offsetof(struct _pthread_descr_struct,
>                                              p_pid);
> -const int __linuxthread_pthread_sizeof_descr
> +const int __linuxthreads_pthread_sizeof_descr
>    = sizeof(struct _pthread_descr_struct);
>  
>  /* Forward declarations */
> 

Hi,.

This patch wouldn't fix the problemm,. however I put on my stout shoes and build myself a libc from the cvs libc-2.2-branch. This did the trick. However there is another problem now ;-).

using gdb 5.0.93-2001-11-18-cvs the following happens: after attaching to a threaded programm, all threads that are in detached state and should exit, leak. this will continue until my process table swamps.

I'm a developer, and willing to put some (though limited; business is hard these days) time into this but I'm sort of in the dark here.

and help, hints, etc. appreciated.

regards,

Peter Zijlstra


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: configuring gdb 5.x for use with threads
  2001-11-08  7:09     ` peter
@ 2001-11-08  7:53       ` Daniel Jacobowitz
  0 siblings, 0 replies; 4+ messages in thread
From: Daniel Jacobowitz @ 2001-11-08  7:53 UTC (permalink / raw)
  To: peter; +Cc: Kevin Buettner, gdb

[please wrap lines]

On Mon, Nov 19, 2001 at 12:01:23PM +0100, peter@a59252.upc-a.chello.nl wrote:
> using gdb 5.0.93-2001-11-18-cvs the following happens: after
> attaching to a threaded programm, all threads that are in detached
> state and should exit, leak. this will continue until my process
> table swamps.
> 
> I'm a developer, and willing to put some (though limited; business is
> hard these days) time into this but I'm sort of in the dark here.
> 
> and help, hints, etc. appreciated.

This is a kernel bug.  It varies a little with kernel version, but the
patch looks like:

  http://sources.redhat.com/ml/bug-glibc/2000-12/msg00057.html

-- 
Daniel Jacobowitz                           Carnegie Mellon University
MontaVista Software                         Debian GNU/Linux Developer


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2001-11-19 14:53 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20011102102321.D6507@a59252.upc-a.chello.nl>
2001-11-06 21:13 ` configuring gdb 5.x for use with threads peter
2001-11-07  2:30   ` Kevin Buettner
2001-11-08  7:09     ` peter
2001-11-08  7:53       ` Daniel Jacobowitz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox