Re: [osg-users] Old really nasty OpenThreads bug?
Hi Anders, On 3/12/10 22:05 , Anders Backman wrote: > This is a WINDOWS problem only. > > ... > To reply Juan, the problem of using static variables for destruction is that > it causes exactly this problem :-) > > If the static variable is defined in the MAIN-APP, it works just fine. In > the same way that atexit() works when it is called from the main-app. > > It is when the static variable (in your case static Deallocator deallocator) > is defined in the .dll file for our library the problem occurs. I've always had problems with Windows applications that do this sort of thing, namely allocating memory in one unit (dll/exe, for lack of a better word) and deleting it in another. The way it was explained to me is that dll and exe have separate heap management, and so allocating an object from one heap and returning it to another doesn't work. I worked around this by making sure that memory is always allocated/freed within the same unit. Worst case this meant to move common functionality into a header file and duplicated the code in both the exe and the dll. But I seem to remember that by some compiler switches you can actually avoid this mess! (Hear, Hear!) I was somewhat surprised that MS haven't added debug code to check for this by tracking where a piece of memory was allocated. Is it possible this is the case in your application? Cheers, /ulrich ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] Old really nasty OpenThreads bug?
Well, I have done some thorough googling on the matter, and it is a general problem in dll-vs-atexit-static variables problem. So it is most probably not a bug in OpenThreads. Lets close that issue. Each dll has its own "order of destruction" for static variables, combine that with that each dll-has its own order of execution of atexit() it becomes a problem. Smack the condition-locks that windows use internally for loading dll, which by the way are handled as static variables, you have a mess. Lights down, thanks for the attention :-) /A On Fri, Dec 3, 2010 at 12:59 PM, Robert Osfield wrote: > Hi Anders, > > I'm pretty sure is not a threading issue / bug in OpenThreads, I > believe it's an issue of proper management of the destruction order of > objects/implementations. When you use singletons you have to be > particularly careful if you are relying upon automatic clean up > provided by the static object destruction. > > One way you could handle the issue of implementations provided by > dll's being unloaded prior to your singleton destructing is for the > dll to have a static varaible that on the dll's unloaded/destruction > will call the singleton to remove/clean up itself and instances of > threads it provides correctly. If when the singleton gets destructed > and their are still threads there that need destructing it can do so. > > To do it I think you'll probably need not just the Thread subclasses > in the plugin/library but also a statically created CleanUp class that > when it destructs it knows about which types of Threads are associated > with it and need cleaning up. One way to do this might be have this > helper class create and destroy the Threads that are associate with > that plugin/library, maintaining a local list of these Threads. The > singleton then wouldn't directly have the list of threds, just a list > of the help class. > > Robert. > ___ > osg-users mailing list > osg-users@lists.openscenegraph.org > http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org > -- ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] Old really nasty OpenThreads bug?
Hi Anders, I'm pretty sure is not a threading issue / bug in OpenThreads, I believe it's an issue of proper management of the destruction order of objects/implementations. When you use singletons you have to be particularly careful if you are relying upon automatic clean up provided by the static object destruction. One way you could handle the issue of implementations provided by dll's being unloaded prior to your singleton destructing is for the dll to have a static varaible that on the dll's unloaded/destruction will call the singleton to remove/clean up itself and instances of threads it provides correctly. If when the singleton gets destructed and their are still threads there that need destructing it can do so. To do it I think you'll probably need not just the Thread subclasses in the plugin/library but also a statically created CleanUp class that when it destructs it knows about which types of Threads are associated with it and need cleaning up. One way to do this might be have this helper class create and destroy the Threads that are associate with that plugin/library, maintaining a local list of these Threads. The singleton then wouldn't directly have the list of threds, just a list of the help class. Robert. ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] Old really nasty OpenThreads bug?
Hi Anders In that case I'm afraid I cannot help you because I seldom use Windows and I don't know enough about dll termination issues. Sorry, Juan ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] Old really nasty OpenThreads bug?
This is a WINDOWS problem only. It works under Linux, MacOSX just fine. Sorry for not pointing it out more clearly. To reply Juan, the problem of using static variables for destruction is that it causes exactly this problem :-) If the static variable is defined in the MAIN-APP, it works just fine. In the same way that atexit() works when it is called from the main-app. It is when the static variable (in your case static Deallocator deallocator) is defined in the .dll file for our library the problem occurs. So I can recreate exactly the same problem by using static deallocators instead of atexit(): 1. If deallocation of the thread occurs in "main", it works 2. If deallocation of the thread occurs in "dll" it hangs. Same code works in Linux/Mac regardless of gcc version. We have "deallocators" in the form of Singletons, which are handled by a SingletonManager, which is responsible of shutting things down in a specific order. Problem is just, when should the "destructors" be called? Explicitly: main() { ... shutdown(); // Works fine, thread dies happy. } or implicitly by the scope of static variables? (preferred so that user does not have to call shutdown(); /A On Fri, Dec 3, 2010 at 11:20 AM, Robert Osfield wrote: > Hi Anders, > > I have just had a look at your test example and it fails to compile > under linux due to the atexit() method. > > Reviewing the code I'm a bit confused why you are using atexit() > method at all. The OSG itself has lots of threads, objects and > singleton created in difference places at different times and works > fine with a platform specific exit mechanism, so I would have thought > it should be possible for your app as well. > > Robert. > ___ > osg-users mailing list > osg-users@lists.openscenegraph.org > http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org > -- __ Anders Backman, CTO Algoryx Simulation AB Uminova Science Park, Box 7973, SE-907 19 Umeå, Sweden and...@algoryx.se http://www.algoryx.se Cell: +46-70-392 64 67 ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] Old really nasty OpenThreads bug?
Hi Anders, I've tried your app on Linux and works fine. I've also reviwed the code and it seems to be OK. However I don't know about Windows dll stuff so you might be overlooking something (atexit called after process threads are cancelled?). In any case, as Robert says, the atexit function can be completely avoided using static variables and class destructors, and it's probably safer. Why don't you try this modified version of your example to see what happens?: #define OTBUG_LIBRARY #include "otbugdll.h" struct Deallocator { ~Deallocator() { if (t != 0) { t->cancel(); delete t; } } OpenThreads::Thread *t; }; static Deallocator deallocator; // Register atexit that will delete the thread void regThread( OpenThreads::Thread *t) { deallocator.t = t; } Robert Osfield wrote: Hi Anders, I have just had a look at your test example and it fails to compile under linux due to the atexit() method. Reviewing the code I'm a bit confused why you are using atexit() method at all. The OSG itself has lots of threads, objects and singleton created in difference places at different times and works fine with a platform specific exit mechanism, so I would have thought it should be possible for your app as well. Robert. ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] Old really nasty OpenThreads bug?
Hi Anders, I have just had a look at your test example and it fails to compile under linux due to the atexit() method. Reviewing the code I'm a bit confused why you are using atexit() method at all. The OSG itself has lots of threads, objects and singleton created in difference places at different times and works fine with a platform specific exit mechanism, so I would have thought it should be possible for your app as well. Robert. ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] Old really nasty OpenThreads bug?
Hi Anders, I haven't tested out the app yet, but my first thought is that perhaps the clean up on exit is destroying the thread objects + implementation prior to the singleton destructor cleaning up. I have seen a number of issues like this over the years, and one just has to be careful about what gets destructed when to make sure the runtime has all the parts it needs to clean up correctly. This clean up issue doesn't require a bug in OpenThreads/Win32 threads for it occur, it can occur simply due to destruction order. Have you tested you test app out on any other platforms? Robert. On Thu, Dec 2, 2010 at 9:06 PM, Anders Backman wrote: > Hi all. > Im using OpenSceneGraph 2.8.3 under windows. Visual studio 2008. > However, this problem has been around for at least 2 years, so it existed in > previous versions too. > I have finally after two years? isolated the bug I reported quite a while > back: http://lists.openscenegraph.org/htdig.cgi/osg-users-openscenegraph.org/2008-May/011360.html > I took a deep breath, and after quite a few hours I managed to isolate the > problem into one .dll file and one .exe file. > The problem: > Assume I have an application, it creates a thread. > For various reason, I want to register this thread to a function for later > destruction (in our lib we give the pointer of the thread to a singleton > which later destroys the thread). In this example, its just registers a > function in atexit() which will delete the thread. > Notice that this call to atexit() is done within ANOTHER DLL (otbugdll.cpp). > When the app exits, the atexit() is called and the thread is destroyed. But > the problem is that it hangs at the call to m_block.release() in the > destructor. > If I instead call atexit() from the main app, everything works just fine. > This means, that the call to delete for the thread is the same, its just > initiated from an atexit() call done from main(). > > What this does, is that we need to have a call: > ThreadPool::instance()->shutdown(); > that HAVE to be called BEFORE the end of the scope of main. Really > irritating. > We cant use atexit() from within the library (because it is done from a > separate lib/dll, which regenerates the problem). > > To build this, you need to set the OSG_DIR path to your OpenSceneGraph > install, run cmake on it, and build the project. > If SHOULD_HANG is defined it will...hang. > http://www8.cs.umu.se/~andersb/otbug.zip > > > I have done just about everything I can come up with to try to resolve this > problem, but nothing works. > I have tried to use a DllMain() function, which catches the events for > attaching and detaching the dll, and doing the delete of the thread there. I > have tried every combination of singletons, static variables etc, but it all > fails. > So the above example is not really exactly my original problem, but it > reproduces the problem quite nicely. I cannot really see what the problem > is. > The flow of code is exactly the same no matter if SHOULD_HANG is defined or > not. > It might be a bug in how OpenThreads use the win32 threading API. > OR it might be a limitation of the Win32 threading API. > Thankful for any help on this matter. > It has been on my mind now for more two years. > /Anders > -- > > > ___ > osg-users mailing list > osg-users@lists.openscenegraph.org > http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org > > ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
[osg-users] Old really nasty OpenThreads bug?
Hi all. Im using OpenSceneGraph 2.8.3 under windows. Visual studio 2008. However, this problem has been around for at least 2 years, so it existed in previous versions too. I have finally after two years? isolated the bug I reported quite a while back: http://lists.openscenegraph.org/htdig.cgi/osg-users-openscenegraph.org/2008-May/011360.html I took a deep breath, and after quite a few hours I managed to isolate the problem into one .dll file and one .exe file. The problem: Assume I have an application, it creates a thread. For various reason, I want to register this thread to a function for later destruction (in our lib we give the pointer of the thread to a singleton which later destroys the thread). In this example, its just registers a function in atexit() which will delete the thread. Notice that this call to atexit() is done within ANOTHER DLL (otbugdll.cpp). When the app exits, the atexit() is called and the thread is destroyed. But the problem is that it hangs at the call to m_block.release() in the destructor. If I instead call atexit() from the main app, everything works just fine. This means, that the call to delete for the thread is the same, its just initiated from an atexit() call done from main(). What this does, is that we need to have a call: ThreadPool::instance()->shutdown(); that HAVE to be called BEFORE the end of the scope of main. Really irritating. We cant use atexit() from within the library (because it is done from a separate lib/dll, which regenerates the problem). To build this, you need to set the OSG_DIR path to your OpenSceneGraph install, run cmake on it, and build the project. If SHOULD_HANG is defined it will...hang. http://www8.cs.umu.se/~andersb/otbug.zip I have done just about everything I can come up with to try to resolve this problem, but nothing works. I have tried to use a DllMain() function, which catches the events for attaching and detaching the dll, and doing the delete of the thread there. I have tried every combination of singletons, static variables etc, but it all fails. So the above example is not really exactly my original problem, but it reproduces the problem quite nicely. I cannot really see what the problem is. The flow of code is exactly the same no matter if SHOULD_HANG is defined or not. It might be a bug in how OpenThreads use the win32 threading API. OR it might be a limitation of the Win32 threading API. Thankful for any help on this matter. It has been on my mind now for more two years. /Anders -- ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org