Segfault when using a MapView in two ApplicationWindows

808
11
12-14-2023 11:20 AM
Labels (2)
HunterMorganBell
New Contributor II

I get a segfault when trying to have two MapViews, one in 2 separate ApplicationWindows. The app I am developing has 2 windows and I need 2 different maps, one in each window. For some reason, when doing this, I get a segfault eventually. Sometimes it will crash during load, other times after a bit during interaction. I also notice sometimes when interacting (zooming in particular), the other map will show artifacts, flickering, other glitches.

Is there some sort of limitation to using multiple MapViews in multiple windows? I know I can easily put more than 1 MapView in a single window (see the scene-map sync example).

To note, these are 2 different MapView objects, I do not want them to be the same map.

To reproduce, use the Display a Map C++ example, and modify main.cpp to load 2 windows instead of 1:

engine.load(QUrl("qrc:/Samples/Maps/DisplayMap/main.qml"));
engine.load(QUrl("qrc:/Samples/Maps/DisplayMap/main.qml"));

 

0 Kudos
11 Replies
JamesBallard1
Esri Regular Contributor

Hi @HunterMorganBell. I tried your test code and I don't get any crashes with that, but that doesn't seem to replicate the scenario you are mentioning. It's still a single window, so it could be that the first MapView gets hidden behind the second one and remains idle forever.

One of my colleagues tried out a small test app we have that displays two scene views, each in their own window. No issues with that in macOS.

Can you provide us some more code to try so we can diagnose better? Also, what version of Qt and the Maps SDK do you have? We just released version 200.3.0 a few days ago

0 Kudos
HunterMorganBell
New Contributor II

That's odd you say that you only see a single window. When I call `engine.load()` twice I get a separate window for each. OS-specific nuance? I am running on Linux, I have not tried to replicate it on other OS's.

Here is some relevant dev environment info:

  • ArcGIS 200.3.0
  • Qt 6.5.2 (GCC_64)
  • Manjaro Linux (kernel 6.1.61-1-MANJARO)
  • KDE Plasma 5.27.9
  • X11
  • NVIDIA GeForce RTX 3090
  • NVIDIA Driver 470.223.02

I'll see if I can come up with something else (maybe two scenes instead of two maps) for test code, but here is a git diff patch of what I did to the arcgis-maps-sdk-samples-qt repo (just duplicating that line to load two windows)

 

diff --git a/ArcGISRuntimeSDKQt_CppSamples/Maps/DisplayMap/main.cpp b/ArcGISRuntimeSDKQt_CppSamples/Maps/DisplayMap/main.cpp
index 49990f8..0a1ec07 100644
--- a/ArcGISRuntimeSDKQt_CppSamples/Maps/DisplayMap/main.cpp
+++ b/ArcGISRuntimeSDKQt_CppSamples/Maps/DisplayMap/main.cpp
@@ -49,6 +49,7 @@ int main(int argc, char *argv[])

   // Set the source
   engine.load(QUrl("qrc:/Samples/Maps/DisplayMap/main.qml"));
+  engine.load(QUrl("qrc:/Samples/Maps/DisplayMap/main.qml"));

   return app.exec();
 }

 

0 Kudos
JamesBallard1
Esri Regular Contributor

@HunterMorganBell , thanks for the additional info. I tried on Linux and I do see what you are seeing now. Two app windows, and it mostly crashes very quickly. I will check with our team on this, but I suspect this is not the preferred way to create multiple app windows with Qt. It's suspicious that on macOS you only get a single app window with the same code.

The stack trace shows it's crashing in our rendering code, which isn't too surprising. I will let you know what we find, but in the meantime are you able to create multiple app windows some other way?

0 Kudos
HunterMorganBell
New Contributor II

I looked at different ways of doing multiple windows in QML, here's an official Qt example: https://doc.qt.io/qt-6/qtquick-window-example.html 

 

I tried something similar, basically modifying arcgis-maps-sdk-samples-qt/ArcGISRuntimeSDKQt_CppSamples/Maps/DisplayMap/main.qml to look like this:

 

 

import QtQuick
import QtQuick.Controls
import Esri.Samples

QtObject {
    property var mainWindow: Window {
        visible: true
        width: 800
        height: 600

        DisplayMap {
            anchors.fill: parent
        }
    }


    property var otherWindow: Window {
        visible: true
        width: 800
        height: 600

        DisplayMap {
            anchors.fill: parent
        }
    }
}

 

 Still get same issue. I tried adding a button and setting the otherWindow to be visible at a later but same issue too.

0 Kudos
JamesBallard1
Esri Regular Contributor

Thanks for the additional info. I've logged an internal bug so we can investigate further.

Are you able to share any details about your workflow? I'd like to understand more about what you're trying to accomplish.

0 Kudos
HunterMorganBell
New Contributor II

Thanks, hopefully you guys come across something. I wonder if there is some thread synchronization problem internally within the SDK Map and/or Scene objects when running multiple windows. I seem to remember each Qt window runs in its own QSG render thread.

 

I can't share too much but essentially I need a way to display a Scene on one monitor and a Map on another to view data from an unmanned aircraft. The Scene window shows the first person view of an aircraft, and the Map window shows the aircraft but from a 2D top-down perspective, along with a flight plan.

 

Wanted to have it split into 2 windows to maximize monitor real-estate versus having it in a single window.

0 Kudos
JamesBallard1
Esri Regular Contributor

Thanks for this info. I'll check with the team to see if there are other ways to accomplish this workflow while we investigate what might be wrong.

0 Kudos
JamesBallard1
Esri Regular Contributor

@HunterMorganBell 

One of my colleagues did some testing and found that setting this environment variable seems to be a viable workaround. We've not tested it extensively, but see if it works for your purposes.

QSG_RENDER_LOOP=basic

0 Kudos
HunterMorganBell
New Contributor II

I gave that a try and hey it's not segfaulting! I read more into that env var here.

One caveat is that since vsync is still enabled by default, 2 windows will only render at 30 fps (for a 60fps monitor) due to the basic render loop now being single-threaded. An acceptable workaround is to disable vsync for all but one window. You can also just disable vsync outright but you'll be rendering as fast as possible which isn't great.

 

QSurfaceFormat fmt = QSurfaceFormat::defaultFormat();
fmt.setSwapInterval(0); // disable vsync for all windows
QSurfaceFormat::setDefaultFormat(fmt);
...
QGuiApplication app(argc, argv);
...
engine.load(QUrl("qrc:/qml/Window1.qml"));
fmt.setSwapInterval(1); // enable vsync for second window
QSurfaceFormat::setDefaultFormat(fmt);
engine.load(QUrl("qrc:/qml/Window2.qml"));

 

 

0 Kudos