OK I created a small standalone program that shows the crash (attached).

To trigger the crash:

   1. Run debug version of osgmultiwindowtesttext. It will open 2 windows
   (Viewers) that contain text "Scene1" and "Scene2"
   2. Close one window -> it might crash. If it crashes, see debug info
   3. If it doesn't crash, then close the other window -> 2 new windows
   will be created -> go back to step 2

You may have to repeat step 2 many times (20 or more) before you see the
crash. The crash happens if the closed Viewer is destroyed while the open
Viewer is in the render stage for the Text.

During debug, the thread for the Viewer being destroyed will likely be in
the ~Camera() destructor. Meanwhile, the thread for the active Viewer will
be in its rendering traversal, at State::apply() for the Text's Program.
See my initial post for the codepath that ends up triggering the crash.

As I said before, I'm running on Win10, Nvidia GTX 980 (latest drivers),
Visual Studio 2013, OpenSceneGraph-3.6 branch (although it happens with
3.6.3 tag also).

I'm perfectly happy if the conclusion ends up being "don't destroy a Viewer
while another one is running". It's easy for me to pause all active Viewers
while destroying one.

Thanks,
Ravi

On Tue, Dec 18, 2018 at 2:28 PM Ravi Mathur <ravid...@utexas.edu> wrote:

> Hi Robert, yes I'm working on a standalone test program now. Multithreaded
> crashes are often hard to reproduce in a vacuum, but as soon as I have
> something I'll post here.
>
> I'm running on Win10, Nvidia GTX 980 (latest drivers), Visual Studio 2013,
> OpenSceneGraph-3.6 branch.
>
> Ravi
>
> On Tue, Dec 18, 2018 at 4:24 AM Robert Osfield <robert.osfi...@gmail.com>
> wrote:
>
>> Hi Ravi,
>>
>> My guess is that the new text implementation isn't the cause of the
>> crash, only it's the straw that broke the camels back, and actually there
>> is an underlying limitation with the OSG w..r.t you specific usage case.
>>
>> Could you create a small test program that reproduces the crash.  Details
>> on your OS/dev tools/hardware will be useful too.
>>
>> Cheers.
>> Robert.
>>
>> On Tue, 18 Dec 2018 at 08:50, Ravi Mathur <ravid...@utexas.edu> wrote:
>>
>>> Hello all,
>>>
>>> I'm seeing a crash on the OpenSceneGraph-3.6 branch that occurs when I
>>> have two CompositeViewers that contain Text objects in their scenes. My
>>> simplified scenario is this:
>>> - 2 CompositeViewers, each in singlethreaded mode, but being run at the
>>> same time in separate threads (via OpenThreads::Thread wrappers)
>>> - The viewers do not share scenes or contexts, and each has a single
>>> Text object as its scene
>>> - Each viewer is destroyed immediately after its run() loop returns
>>> (needed for my application)
>>>
>>> Both viewers animate just fine in their own windows. The crash happens
>>> if one viewer is being destroyed while the other is actively rendering.
>>> Note that it only seems to crash if there are Text objects in each scene,
>>> and did not crash with the old (pre-3.6) Text implementation.
>>>
>>> Is this usage model ok in the first place? Robert, I read your post in
>>> this recent thread
>>> <http://forum.openscenegraph.org/viewtopic.php?t=16844> in which you
>>> advise against manually destroying viewers. Should I assume that I was just
>>> lucky in getting away with this until now? The new Text implementation
>>> seems to be the only thing that triggers the crash.
>>>
>>> In case anybody is interested, the crash happens due to this sequence of
>>> calls:
>>> - ~CompositeViewer() calls GraphicsContext::close(), which deletes its
>>> State
>>> - ~CompositeViewer() then destroys its osgViewer::View, which in turn
>>> destroys its Camera
>>> - ~Camera() eventually calls osgText::releaseGLObjects() with a null
>>> State.
>>> - osgText::releaseGLObjects(null) deletes text-related objects
>>> (Programs) on ALL contexts
>>> - The other CompositeViewer, which is actively rendering its Text on
>>> another context, crashes with an access violation since its Text-related
>>> Programs were just deleted.
>>>
>>> Thanks,
>>> Ravi
>>> _______________________________________________
>>> 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
>>
>
#include <OpenThreads/Thread>
#include <osg/Geode>
#include <osgText/Text>
#include <osgViewer/Viewer>

class ThreadedViewer : public OpenThreads::Thread
{
public:
  ThreadedViewer(osg::Node* scene)
  {
    // Set up Viewer
    _viewer = new osgViewer::Viewer;
    _viewer->setSceneData(scene);

    // Name camera so it's easier to identify during debug
    _viewer->getCamera()->setName("Master camera for " + scene->getName());
  }

  /** Inherited from OpenThreads::Thread. Called on thread launch. */
  virtual void run()
  {
    _viewer->setUpViewInWindow(200, 200, 640, 480);

    // Set up processor affinity for render and database threads
    // First let OSG configure affinity
    _viewer->configureAffinity();

    // Set up singlethreaded mode and ensure that viewers can operate
    // on any core. NOTE: I know this is not optimal for rendering, but
    // here it's just for test purposes. Allowing simultaneous viewers
    // to operate on different cores increases their performance and
    // increases the likelihood that the crash conditions will be met.
    _viewer->setProcessorAffinity(OpenThreads::Affinity());
    _viewer->setUseConfigureAffinity(false);
    _viewer->setThreadingModel(osgViewer::ViewerBase::SingleThreaded);   
    
    // Run viewer
    _viewer->run();

    // Force viewer to delete
    // This can crash OTHER viewers that are in their rendering stage
    _viewer = nullptr;
  }

protected:
  osg::ref_ptr<osgViewer::Viewer> _viewer;
};

osg::Node* createScene(const std::string& name)
{
  // Create text
  osgText::Text* text = new osgText::Text;
  text->setDataVariance(osg::Object::DYNAMIC);
  text->setCharacterSizeMode(osgText::Text::SCREEN_COORDS);
  text->setAxisAlignment(osgText::Text::SCREEN);
  text->setFontResolution(20, 20);
  text->setCharacterSize(20);
  text->setFont("arial.ttf");
  text->setText(name);

  // Geode to hold the geometry
  osg::Geode* geode = new osg::Geode();
  geode->addDrawable(text);
  geode->setName(name);
  osg::StateSet *stateset = geode->getOrCreateStateSet();
  stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
  return geode;
}

int main(int argc, char** argv)
{
  // Parse user inputs
  osg::ArgumentParser arguments(&argc, argv);

  while (true)
  {
    OSG_NOTICE << "Creating 2 threaded viewers. Close both windows to create 2 
more." << std::endl;
    ThreadedViewer viewer1(createScene("Scene1"));
    ThreadedViewer viewer2(createScene("Scene2"));

    viewer1.startThread();
    viewer2.startThread();

    viewer1.join();
    viewer2.join();
  }

  return 0;
}
_______________________________________________
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to