Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

not using waitForThread() results in zombie ofThreads on OSX, leading to a crash over time #2506

Closed
armadillu opened this issue Aug 23, 2013 · 13 comments

Comments

@armadillu
Copy link
Contributor

When launching an ofThread for which you don't need to join to with the main thread (i.e. writing a file to disk), ofThread doesn't clean up after himself. This results in a zombie thread that takes up resources. On OSX I can launch around 6485 threads like this one; after that I get a crash (libc++abi.dylib: terminate called throwing an exception). I would imagine this affects all posix-thread based OS's.

I built a tiny example demonstrating the issue. This has been going on since day one of ofThread, not new to 0.08. You can get the XCode 0.08 example here.

Basically, I think an ofThread that returns from its threadedFunction() and has not been requested to join with the main thread should be detached by ofThread himself before exiting run(). In fact, there's an Android-only #ifdef doing exactly that, although it always detaches. You want to make sure the thread is not being waited to be joined with, as this won't work after you detach it ("After pthread_detach() has been issued, it is not valid to try to pthread_join() with the target thread") see here.

The thing is, ofThread is now using Poco threads, which must certainly be wrapping posix threads on OSX, but it's as not clear as it was with the previous versions of ofThread, which were using direct posix-thread calls. The Poco thread API doesn't seem to offer a call to detach, and using posix calls directly feels off, as poco has no mention of posix threads at all.

My proposed changes:

  1. a boolean named "threadBeingWaitedFor" in ofThread that's set to true when waitForThread() is called on that thread
  2. this:
void ofThread::run(){

    (...)

    threadedFunction();

    #ifdef TARGET_OS_X //////////////////////// PROPOSED FIX
    if(!threadBeingWaitedFor){ //if threadedFunction() ended and the thread is not being waited for, detach it before exiting.
        pthread_detach(pthread_self()); 
    }
    #endif //////////////////////////////////// END FIX
    threadRunning = false;
    (...)
}
@bakercp
Copy link
Member

bakercp commented Aug 23, 2013

Yes, I've run into this too!

Here's what's happening in our particular 1.4.6 poco branch on OSX:

Edit:
https://github.com/pocoproject/poco/blob/poco-1.4.6/Foundation/src/Thread_POSIX.cpp

@arturoc
Copy link
Member

arturoc commented Aug 23, 2013

this was actually working before porting ofThread to poco, where the threads were detached on stop, at least on the poxis version. isn't there an equivalent to detach using poco? just so we make this multiplatform

@armadillu
Copy link
Contributor Author

@arturoc they were being detached if you called stopThread on them though. If you just did let them die silently I recall they weren't being detached?

@armadillu
Copy link
Contributor Author

And no, weirdly enough I couldn't find a "detach" method in poco's Thread class.

@armadillu
Copy link
Contributor Author

Is there a planned fix for this in the 0.8.1 release?
I haven't been following lately, but I don't see anything solving this issue...

@bakercp
Copy link
Member

bakercp commented Mar 13, 2014

#2505 should help with this. Also, upgrading Poco will help solve this. It appears neither will happen in the next bug-fix release, but will be delayed for further testing after 0.8.1 drops.

@bakercp
Copy link
Member

bakercp commented Apr 2, 2014

Hey @armadillu can you post a minimum running example code to test this? I'd like to dig into it a bit. I'm thinking that this could be an bug related to an old POCO build.

@armadillu
Copy link
Contributor Author

there is one attached, in the first post, here's the link https://www.dropbox.com/s/5exappb0t7hh4p4/threadDeath.zip

@armadillu
Copy link
Contributor Author

and yeah, this could be fixable from poco: pocoproject/poco#79

@bilderbuchi
Copy link
Member

which Poco are we on, currently? Older than poco-1.5.2-rc2, which is where that poco issue was fixed?

@bakercp
Copy link
Member

bakercp commented Apr 2, 2014

We're on 1.4.3. We really need an upgrade. 1.5.2-rc2 is (almost?) ready
to compile for all platforms using apothecary.


http://christopherbaker.net

On Wed, Apr 2, 2014 at 3:57 PM, Christoph Buchner
notifications@github.comwrote:

which Poco are we on, currently? Older than poco-1.5.2-rc2, which is where
that poco issue was fixed?

Reply to this email directly or view it on GitHubhttps://github.com//issues/2506#issuecomment-39382524
.

@cyburgee
Copy link

cyburgee commented May 6, 2014

This issue wasn't fixed in 0.8.1 was it? My of app always throws a "Poco::SystemException: System exception" at the line:

thread.start(*this);

in

void ofThread::startThread(bool blocking, bool verbose)

after my thread has run a few thousand times

@cyburgee
Copy link

cyburgee commented May 6, 2014

@armadillu your proposed changes need modification. If waitForThread(bool stop) is called after the thread has been detached, thread.tryjoin(10000) will throw an exception. I think this is because detaching the thread does not necessarily make thread.isRunning() return false. I changed the condition:

if(thread.isRunning())

to:

 if(threadRunning)

and that seems to have solved my problem for now, however I doubt this is safe in all cases that use ofThread

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants