Hi I don't know if this the right place to post a question/plea for help but,
I'm trying to write an external, that uses a pthread to do some speech synthesis without interrupting pd audio.
I'm getting a very strange problem.. its leaking memory when invoked within the thread.
After further investigation, I find that even a simple malloc/free is leaking all the memory it's allocating, even when called in the main pd thread, if there is another thread being created- its as if the act of making a new thread completely confuses malloc.
Any thoughts, would this be something to do with pd or with the c library (glibc/ubuntu)?
Thanks
Tim
I'd say it's most likely your code. I would be very surprised if libc is leaking memory. There are thousands of eyes looking at that code, and many millions using it in many ways. Pd code could have leaks, but mostly it is good.
Try posting your code.
.c
On Apr 15, 2008, at 10:18 AM, tim redfern wrote:
Hi I don't know if this the right place to post a question/plea for help but,
I'm trying to write an external, that uses a pthread to do some speech synthesis without interrupting pd audio.
I'm getting a very strange problem.. its leaking memory when invoked within the thread.
After further investigation, I find that even a simple malloc/free is leaking all the memory it's allocating, even when called in the main pd thread, if there is another thread being created- its as if the act of making a new thread completely confuses malloc.
Any thoughts, would this be something to do with pd or with the c library (glibc/ubuntu)?
Thanks
Tim
PD-dev mailing list PD-dev@iem.at http://lists.puredata.info/listinfo/pd-dev
------------------------------------------------------------------------ ----
¡El pueblo unido jamás será vencido!
Hi.. yup absolutely , theres something wrong with the way my code is interacting with pd and threads .. however what I'm doing is so simple I have to conclude there is something very strange amiss..
On Tue, 2008-04-15 at 14:56 -0400, Hans-Christoph Steiner wrote:
I'd say it's most likely your code. I would be very surprised if libc is leaking memory. There are thousands of eyes looking at that code, and many millions using it in many ways. Pd code could have leaks, but mostly it is good.
Try posting your code.
I've stripped this down to the simplest example possible. When this external is used, it has a bang method that launches a thread that does absolutely nothing. It also mallocs 1000000 bytes and frees them immediately (not even within the thread).
The test patch is::
#N canvas 0 0 450 300 10; #X obj 31 88 thread; #X obj 42 47 metro 1000; #X obj 39 8 tgl 15 0 empty empty empty 0 -6 0 10 -262144 -1 -1 0 1 ; #X obj 126 109 bng 15 250 50 0 empty empty empty 0 -6 0 10 -262144 -1 -1; #X connect 1 0 0 0; #X connect 1 0 3 0; #X connect 2 0 1 0;
As far as I can see, this leaks all of the memory that its allocating. The VIRT column of the pd entry in 'top' climbs at more than 1 meg per second.
However, if I comment out pthread_create then pd's memory use doesnt grow at all.
Heres the code...what am I doing wrong?
#include "m_pd.h" #include <stdlib.h>
#include <pthread.h>
pthread_attr_t gen_attr;
static t_class *thread_class;
typedef struct _thread { t_object x_obj; } t_thread;
void *threadtester( void* x_obj ) { t_thread *x= (t_thread *) x_obj;
//do nothing in particular
return 0; }
void thread_bang(t_thread *x) { char* temp=(char*)malloc(1000000); free(temp);
pthread_t stest; pthread_create (&stest,&gen_attr,threadtester,(void *) x); post("hello world!"); }
void *thread_new(void) { t_thread *x = (t_thread *)pd_new(thread_class);
return (void *)x; }
void thread_setup(void) { // //create parameters for low priority thread pthread_attr_init(&gen_attr); struct sched_param param; param.sched_priority = 15; //LOW priority (-20..20) pthread_attr_setschedparam( &gen_attr, ¶m );
thread_class = class_new(gensym("thread"), (t_newmethod)thread_new, 0, sizeof(t_thread), CLASS_DEFAULT, 0); class_addbang(thread_class, thread_bang); }
Hi Tim, list,
First, I never wrote anything with pthreads, so this may be way off the mark, but this looks suspicious:
tim redfern wrote:
void thread_bang(t_thread *x) { char* temp=(char*)malloc(1000000); free(temp);
pthread_t stest; pthread_create (&stest,&gen_attr,threadtester,(void *) x); post("hello world!");
}
stest disappears when the thread_bang() returns, the thread is still running, and maybe pthread internals write to stest after it is no longer there, which would be very bad: at best, a segmentation fault, at worst, no crash but wrong behaviour.
At a guess: malloc() a list node with the pthread_t in it, and store those nodes in a list in the Pd object struct.
Claude
Hi Claude,
stest disappears when the thread_bang() returns, the thread is still running, and maybe pthread internals write to stest after it is no longer there, which would be very bad: at best, a segmentation fault, at worst, no crash but wrong behaviour.
At a guess: malloc() a list node with the pthread_t in it, and store those nodes in a list in the Pd object struct.
I see what you mean, I don't think this is it though as:
-- its not crashing or giving errors (just leaking memory: memory which isn't even owned by the new thread)
-- pthreads aren't 'owned' by the code that calls them: a thread can exist even after the thread that calls it terminates. surely in this case the pointer to the thread must have been freed first.
-- I'm using the same method as in this well known tutorial on pthreads: https://computing.llnl.gov/tutorials/pthreads/#CreatingThreads
-- I've tried your suggestion of moving the pthread pointer to the scope of the external structure and it doesn't help: see even more simple example code below.
Can anyone else think of a reason why opening a new thread inside pd would confuse malloc like this? Or can anyone else verify that this code causes a leak (just to prove that I'm not going crazy!)
Thanks, Tim
--------The code
#include "m_pd.h" #include <stdlib.h> #include <pthread.h>
static t_class *thread_class;
typedef struct _thread { t_object x_obj; pthread_t stest; } t_thread;
void *threadtester( void* x_obj ) { t_thread *x= (t_thread *) x_obj; //do nothing in particular
return 0; }
void thread_bang(t_thread *x) { char* temp=(char*)malloc(1000000); free(temp); pthread_create (&x->stest,NULL,threadtester,(void *) x); post("hello world!"); }
void *thread_new(void) { t_thread *x = (t_thread *)pd_new(thread_class);
return (void *)x; }
void thread_setup(void) { thread_class = class_new(gensym("thread"), (t_newmethod)thread_new, 0, sizeof(t_thread), CLASS_DEFAULT, 0); class_addbang(thread_class, thread_bang); }
apologies, I figured out I needed to make the thread 'detached'.
thanks for your attention..
T
On Wed, 2008-04-16 at 19:25 +0100, Claude Heiland-Allen wrote:
Hi Tim, list,
First, I never wrote anything with pthreads, so this may be way off the mark, but this looks suspicious:
tim redfern wrote:
void thread_bang(t_thread *x) { char* temp=(char*)malloc(1000000); free(temp);
pthread_t stest; pthread_create (&stest,&gen_attr,threadtester,(void *) x); post("hello world!");
}
stest disappears when the thread_bang() returns, the thread is still running, and maybe pthread internals write to stest after it is no longer there, which would be very bad: at best, a segmentation fault, at worst, no crash but wrong behaviour.
At a guess: malloc() a list node with the pthread_t in it, and store those nodes in a list in the Pd object struct.
Claude