[thread] throw during new boost::thread() ??

if i allocate more than 5501 threads, subsequent threads fail to run. these threads live a very short time and only maybe ten max are alive at any one time. for example if i'm iterating over every song in my music library and doing some quick process, after about 5500 songs, the program stops working. i'm exiting the threads normally, so housekeeping is performed (tho it would be performed anyway, right?) i checked and when it crashes there are indeed only about five threads running. so SOME resource is not getting released, it's not my resource, it's something to do with boost::threads. as a test, i created one thread, then on that thread i loop and create 30,000 threads. the only thing the thread does is increment a counter and exit, so no more than a couple threads are live at once. why is it throwing an exception?? call stack: #0 0x001cebaf in boost::detail::sp_counted_impl_p<boost::detail::thread_data<CFork_Preemptive> >::sp_counted_impl_p at sp_counted_impl.hpp:67 #1 0x001cec0f in boost::detail::shared_count::shared_count<boost::detail::thread_data<CFork_Preemptive> > at shared_count.hpp:87 #2 0x001d008a in boost::shared_ptr<boost::detail::thread_data_base>::shared_ptr<boost::detail::thread_data<CFork_Preemptive> > at shared_ptr.hpp:187 #3 0x001d0110 in boost::thread::make_thread_info<CFork_Preemptive> at thread.hpp:136 #4 0x001d0149 in boost::thread::thread<CFork_Preemptive> at thread.hpp:186 #5 0x001c6e92 in CThreads::Fork at CThreads.cpp:765 template<class X> class sp_counted_impl_p: public sp_counted_base { private: X * px_; sp_counted_impl_p( sp_counted_impl_p const & ); sp_counted_impl_p & operator= ( sp_counted_impl_p const & ); typedef sp_counted_impl_p<X> this_type; public: explicit sp_counted_impl_p( X * px ): px_( px ) { <<--- throw happens right here #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) boost::sp_scalar_constructor_hook( px, sizeof(X), this ); #endif } virtual void dispose() // nothrow { #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) boost::sp_scalar_destructor_hook( px_, sizeof(X), this ); #endif boost::checked_delete( px_ ); }

On Sat, Aug 21, 2010 at 3:44 PM, David M. Cotter <me@davecotter.com> wrote:
if i allocate more than 5501 threads, subsequent threads fail to run.
these threads live a very short time and only maybe ten max are alive at any one time.
for example if i'm iterating over every song in my music library and doing some quick process, after about 5500 songs, the program stops working.
i'm exiting the threads normally, so housekeeping is performed (tho it would be performed anyway, right?)
i checked and when it crashes there are indeed only about five threads running. so SOME resource is not getting released, it's not my resource, it's something to do with boost::threads.
as a test, i created one thread, then on that thread i loop and create 30,000 threads. the only thing the thread does is increment a counter and exit, so no more than a couple threads are live at once.
why is it throwing an exception??
call stack:
#0 0x001cebaf in boost::detail::sp_counted_impl_p<boost::detail::thread_data<CFork_Preemptive> >::sp_counted_impl_p at sp_counted_impl.hpp:67 #1 0x001cec0f in boost::detail::shared_count::shared_count<boost::detail::thread_data<CFork_Preemptive> > at shared_count.hpp:87 #2 0x001d008a in boost::shared_ptr<boost::detail::thread_data_base>::shared_ptr<boost::detail::thread_data<CFork_Preemptive> > at shared_ptr.hpp:187 #3 0x001d0110 in boost::thread::make_thread_info<CFork_Preemptive> at thread.hpp:136 #4 0x001d0149 in boost::thread::thread<CFork_Preemptive> at thread.hpp:186 #5 0x001c6e92 in CThreads::Fork at CThreads.cpp:765
template<class X> class sp_counted_impl_p: public sp_counted_base { private:
X * px_;
sp_counted_impl_p( sp_counted_impl_p const & ); sp_counted_impl_p & operator= ( sp_counted_impl_p const & );
typedef sp_counted_impl_p<X> this_type;
public:
explicit sp_counted_impl_p( X * px ): px_( px ) { <<--- throw happens right here #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) boost::sp_scalar_constructor_hook( px, sizeof(X), this ); #endif }
virtual void dispose() // nothrow { #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) boost::sp_scalar_destructor_hook( px_, sizeof(X), this ); #endif boost::checked_delete( px_ ); }
Unsure about posix, but on Windows anyway, 5k threads is a *LOT*! You are probably running out of kernel handles, paged pool, or process space (each thread will take about 2 megs of stack space unless you change linker options). You should redesign it to use a task pattern (anything you would put in a thread you would put in a task instead, then have a threadpool, usually equal to the number of CPU's, and have them churn through the tasks, there are pre-made handlers for such a thing in the Boost Vault/sandbox, named Boost.Task I think).

Unsure about posix, but on Windows anyway, 5k threads is a *LOT*! You are probably running out of kernel handles, paged pool, or process space (each thread will take about 2 megs of stack space unless you change linker options). WHAT???? you MUST be mistaken? two MEGABYTES of stack space for a thread??? that seems totally crazy. are you SURE about that??
You should redesign okay well, that may be outside the scope of what is possible at this time. everything *used to* work perfectly fine, when i used pthreads directly, before i switched to using boost::threads.
so i KNOW i'm not asking for something crazy. i should be able to spawn an infinite number of threads during the lifetime of my application, provided they terminate gracefully and clean up and recycle and whatnot, and that i don't spawn ten zillion at one time. yes this is on posix. and i shouldn't be "running out" of anything since the threads die right away, as i said there are really no more than five or ten threads at once. once a thread dies, don't it's resources get "recycled" ??

On Aug 21, 2010, at 6:45 PM, David M. Cotter wrote:
Unsure about posix, but on Windows anyway, 5k threads is a *LOT*! You are probably running out of kernel handles, paged pool, or process space (each thread will take about 2 megs of stack space unless you change linker options). WHAT???? you MUST be mistaken? two MEGABYTES of stack space for a thread??? that seems totally crazy. are you SURE about that??
Well....on Windows the default stack size is 1 MByte....but you can verify for yourself....http://msdn.microsoft.com/en-us/library/ms686774(VS.85).aspx ;) Ciao, Andreas

At Sat, 21 Aug 2010 14:44:04 -0700, David M. Cotter wrote:
if i allocate more than 5501 threads, subsequent threads fail to run.
This sounds like a really good application for a threadpool.
these threads live a very short time and only maybe ten max are alive at any one time.
for example if i'm iterating over every song in my music library and doing some quick process, after about 5500 songs, the program stops working.
i'm exiting the threads normally, so housekeeping is performed (tho it would be performed anyway, right?)
i checked and when it crashes there are indeed only about five threads running. so SOME resource is not getting released, it's not my resource, it's something to do with boost::threads.
Well, if things are *really* borked when it crashes, you might not be getting an accurate count of the running threads, or perhaps they've all exited by the time you actually check. No matter how quick the task, without something to keep the number of actual simultaneous threads under control, you *are* very likely launching all 5500 of them at once in a way that—at best—will never perform well. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

these threads live a very short time and only maybe ten max are alive at any one time.
for example if i'm iterating over every song in my music library and doing some quick process, after about 5500 songs, the program stops working.
i'm exiting the threads normally, so housekeeping is performed (tho it would be performed anyway, right?)
i checked and when it crashes there are indeed only about five threads running. so SOME resource is not getting released, it's not my resource, it's something to do with boost::threads.
Well, if things are *really* borked when it crashes, you might not be getting an accurate count of the running threads, or perhaps they've all exited by the time you actually check. No matter how quick the task, without something to keep the number of actual simultaneous threads under control, you *are* very likely launching all 5500 of them at once in a way that—at best—will never perform well.
well, things aren't borked, i can assure you that no more than ten are running at once during my test, i increment a "live" count and a "done" count, and they never differ by more than say five. if they do, i assert. so it's simply not possible that more than five are live at once. put another way, i have a live thread count that in inc's when a thread is created and dec's when a thread is destroyed. and that count never goes over five. performance has never been an issue. in my actual app i'm not actually just performing a tight loop spawning threads. there's a lot happening between spawnings and threads close at the same rate they are opened. again i've never had more than about five open at once.

how about this: i changed my test to do one thread at a time, wait for it to complete, then do the next thread again, throws an exception from the same location after 5496 threads (note my app spawns several other threads just to get running, so the number may be off by the time i run the test

On Sat, Aug 21, 2010 at 04:29:28PM -0700, David M. Cotter wrote:
how about this: i changed my test to do one thread at a time, wait for it to complete, then do the next thread
again, throws an exception from the same location after 5496 threads (note my app spawns several other threads just to get running, so the number may be off by the time i run the test
How do you create your threads? new'd on free store? local variable? other? If you're allocating with say new and forget to delete, you might be running out of thread handles as you'll have zombies hanging around. -- Lars Viklund | zao@acc.umu.se

If you're allocating with say new and forget to delete, you might be running out of thread handles as you'll have zombies hanging around.
okay that explains it. previously i had been using the pthread impl wrapped by MacOS thread manager calls. in that impl, when a thread exits, it self-disposes. i made an assumption (surprise) this would behave the same way. when i put a "delete thread" in the destructor, everything started working again!! YAY thanks for that one little tip, something i should be well aware of at this point but you know, the forest / trees problem sometimes gets the best of us! thanks again!

On Sun, Aug 22, 2010 at 9:07 AM, David M. Cotter <me@davecotter.com> wrote:
If you're allocating with say new and forget to delete, you might be running out of thread handles as you'll have zombies hanging around.
okay that explains it. previously i had been using the pthread impl wrapped by MacOS thread manager calls. in that impl, when a thread exits, it self-disposes. i made an assumption (surprise) this would behave the same way. when i put a "delete thread" in the destructor, everything started working again!!
YAY thanks for that one little tip, something i should be well aware of at this point but you know, the forest / trees problem sometimes gets the best of us!
The next question might be why you are dynamically allocating thread objects at all, and, if you really must, why you aren't managing them with smart pointers. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On Sat, Aug 21, 2010 at 3:29 PM, David M. Cotter <me@davecotter.com> wrote:
how about this: i changed my test to do one thread at a time, wait for it to complete, then do the next thread
again, throws an exception from the same location after 5496 threads (note my app spawns several other threads just to get running, so the number may be off by the time i run the test
If so, it should be easy for you to produce a minimal (1 digestible source file), reproducible example that demonstrates the problem. If you can post that, I'm sure we can help you. -- Dave Abrahams BoostPro Computing http://www.boostpro.com
participants (6)
-
Andreas Masur
-
Dave Abrahams
-
David Abrahams
-
David M. Cotter
-
Lars Viklund
-
OvermindDL1