Hi, I am actually working on a complex project which uses OSG 3.0.1 on a Windows 7 Professional x64 SP1 platform with Visual Studio 2010 Premium SP1. Because I encountered random heap corruption errors, I was testing and debugging with different configurations of my program and could state the following: - the invalid heap occurs mostly around one of the notification strings - the problem occurs with all threading models except SingleThreaded - the problem occurs still with an "empty" osg::NotifyHandler subclass (which originally implements some custom logging mechanism) - the problem occurs still without a custom osg::NotifyHandler subclass, i.e. when using osg::StandardNotifyHandler by default
After all, I found the following forum thread which describes very similar experiences: http://forum.openscenegraph.org/viewtopic.php?t=9475 According to this forum thread, I designed my custom osg::NotifyHandler subclass thread-safe. Also, I checked out not to mix up incompatible binaries. My actual working project is not portable. But in order to track the problem on a non-Windows platform, I created another simple program which is inspired by the forum thread mentioned above. Here it is: #include <ctime> #include <cstdlib> #include <fstream> #include <OpenThreads/Thread> #include <osg/Notify> // empty logging handler class LogFileHandler : public osg::NotifyHandler { public: LogFileHandler(const char *filename) { } void notify(osg::NotifySeverity severity, const char *message) { } protected: ~LogFileHandler() { } }; // simple worker thread class MyThread : public OpenThreads::Thread { public: MyThread(int id) : m_id(id) { OSG_INFO << "CREATE THREAD " << m_id << std::endl; } protected: virtual void run() { int lines = 100000; // number of notifications generated by this thread for (int i = 0; i < lines; ++i) { // generate a random notification, e.g. "HELLO FROM THREAD 2: aaabbbcccccdde[...]zz..." OSG_INFO << "HELLO FROM THREAD " << m_id << ": "; int letters = 26; for (int j = 0; j < letters; ++j) { char c = 'a' + j; switch (std::rand() % 5 + 1) { case 1: OSG_INFO << c; break; case 2: OSG_INFO << c << c; break; case 3: OSG_INFO << c << c << c; break; case 4: OSG_INFO << c << c << c << c; break; case 5: OSG_INFO << c << c << c << c << c; break; } } OSG_INFO << "..." << std::endl; } } private: int m_id; }; // simple program int main(int argc, char **argv) { srand(time(NULL)); osg::setNotifyLevel(osg::DEBUG_FP); osg::setNotifyHandler(new LogFileHandler("log.txt")); // comment out this line: stdout will contain mixed up strings const int count = 2; // number of threads accessing the notification API concurrently MyThread *threads[count] = { }; for (int i = 0; i < count; ++i) { threads[i] = new MyThread(i); threads[i]->start(); } for (int i = 0; i < count; ++i) { while (threads[i]->isRunning()) { /* active wait until the worker thread ends */ } delete threads[i]; threads[i] = NULL; } return EXIT_SUCCESS; } The program essentially imitates a multi-threaded environment for the notification API by creating some worker threads. Every thread generates a bulk of random notifications and pushes them per OSG_INFO. I think, one can compare this scenario with the case where a verbose notify level is used in combination with a non-SingleThreaded threading model, or am I wrong? In my Win 7 x64 VS 2010 environment the result is the following: I got frequent heap corruption errors. The problem can be reproduced more or less depending on the number of concurrently running threads and if it is a debug or release build. If I comment out the use of the custom osg::NotifyHandler subclass (which defaults to osg::StandardNotifyHandler), I recognized mixed up strings and missing endl's in stdout. Furthermore, I tested this program with Lubuntu 12.0.4 x64 and the QtCreator from the QtSDK 4.8.1. At least in debug mode, I got frequent heap corruption errors. If I comment out the use of the custom osg::NotifyHandler subclass, I recognized mixed up strings (debug) and missing endl's (debug and release) in stdout as well. Concluding, for my actual working project I will run SingleThreaded to avoid heap corruption as it fits my needs at the moment. But I cannot overcome some questions: - Do I miss some well-known restrictions, when using the notification API with multi-threading? - IMHO the heap corruption is caused by the non-thread-safe access to the global static instance of osg::NotifyStream defined in Notify.cpp. All over OSG, it is accessed by a reference to std::ostream which is returned by the osg::notify() function in order to call operator << on it. Can someone check these facts and explain to me, why there is no locking mechanism or the like to make the stream thread-safe? I appreciate every enlightenment or correction! Matthias Schütze, Germany _______________________________________________ osg-users mailing list [email protected] http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

