Hello community,

here is the log from the commit of package SimGear for openSUSE:Factory checked 
in at 2020-12-12 20:30:32
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/SimGear (Old)
 and      /work/SRC/openSUSE:Factory/.SimGear.new.2328 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "SimGear"

Sat Dec 12 20:30:32 2020 rev:19 rq:854911 version:2020.3.4

Changes:
--------
--- /work/SRC/openSUSE:Factory/SimGear/SimGear.changes  2020-11-12 
22:46:15.662572036 +0100
+++ /work/SRC/openSUSE:Factory/.SimGear.new.2328/SimGear.changes        
2020-12-12 20:32:57.881889623 +0100
@@ -1,0 +2,6 @@
+Thu Dec 10 13:21:33 UTC 2020 - Stefan BrĂ¼ns <[email protected]>
+
+- Update to 2020.3.4
+  * No changelog available
+
+-------------------------------------------------------------------

Old:
----
  simgear-2020.3.2.tar.bz2

New:
----
  simgear-2020.3.4.tar.bz2

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ SimGear.spec ++++++
--- /var/tmp/diff_new_pack.RxfEcS/_old  2020-12-12 20:32:58.677890453 +0100
+++ /var/tmp/diff_new_pack.RxfEcS/_new  2020-12-12 20:32:58.677890453 +0100
@@ -20,10 +20,10 @@
 # in our requirements, i.e. the same version we have built against
 %define openscenegraph_version %(rpm -qa --nosignature --nodigest 
libOpenSceneGraph\*-devel | sed 's/.*-devel-\\(.*\\)-.*/\\1/')
 
-%define libname libSimGearCore-2020_3_2
+%define libname libSimGearCore-2020_3_4
 %define main_version 2020.3
 Name:           SimGear
-Version:        %{main_version}.2
+Version:        %{main_version}.4
 Release:        0
 Summary:        Simulator Construction Gear
 # https://sourceforge.net/p/flightgear/codetickets/1940/

++++++ simgear-2020.3.2.tar.bz2 -> simgear-2020.3.4.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/simgear-2020.3.2/simgear/constants.h 
new/simgear-2020.3.4/simgear/constants.h
--- old/simgear-2020.3.2/simgear/constants.h    2020-11-05 12:33:00.000000000 
+0100
+++ new/simgear-2020.3.4/simgear/constants.h    2020-12-01 10:16:23.000000000 
+0100
@@ -218,6 +218,9 @@
 #define SG_OBJECT_RANGE_ROUGH     9000.0
 #define SG_OBJECT_RANGE_DETAILED  1500.0
 
+/** Minimum expiry time of PagedLOD within the Tile.  Overridden by 
/sim/rendering/plod-minimum-expiry-time-secs **/
+#define SG_TILE_MIN_EXPIRY 180.0
+
 /** Radius of scenery tiles in m **/
 #define SG_TILE_RADIUS      14000.0
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/simgear-2020.3.2/simgear/environment/metar.cxx 
new/simgear-2020.3.4/simgear/environment/metar.cxx
--- old/simgear-2020.3.2/simgear/environment/metar.cxx  2020-11-05 
12:33:00.000000000 +0100
+++ new/simgear-2020.3.4/simgear/environment/metar.cxx  2020-12-01 
10:16:23.000000000 +0100
@@ -646,16 +646,21 @@
        double gust = NaN;
        if (*m == 'G') {
                m++;
-               if (!scanNumber(&m, &i, 2, 3))
+               if (!strncmp(m, "//", 2))       // speed not measurable
+                       m += 2, i = -1;
+               else if (!scanNumber(&m, &i, 2, 3))
                        return false;
-               gust = i;
+
+               if (i != -1)
+                       gust = i;
        }
+
        double factor;
        if (!strncmp(m, "KT", 2))
                m += 2, factor = SG_KT_TO_MPS;
-       else if (!strncmp(m, "KMH", 3))
+       else if (!strncmp(m, "KMH", 3))         // invalid Km/h
                m += 3, factor = SG_KMH_TO_MPS;
-       else if (!strncmp(m, "KPH", 3))         // ??
+       else if (!strncmp(m, "KPH", 3))         // invalid Km/h
                m += 3, factor = SG_KMH_TO_MPS;
        else if (!strncmp(m, "MPS", 3))
                m += 3, factor = 1.0;
@@ -680,18 +685,28 @@
 {
        char *m = _m;
        int from, to;
-       if (!scanNumber(&m, &from, 3))
+
+       if (!strncmp(m, "///", 3))      // direction not measurable
+               m += 3, from = -1;
+       else if (!scanNumber(&m, &from, 3))
                return false;
+
        if (*m++ != 'V')
                return false;
-       if (!scanNumber(&m, &to, 3))
+
+       if (!strncmp(m, "///", 3))      // direction not measurable
+               m += 3, to = -1;
+       else if (!scanNumber(&m, &to, 3))
                return false;
+
        if (!scanBoundary(&m))
                return false;
+
        _m = m;
        _wind_range_from = from;
        _wind_range_to = to;
        _grpcount++;
+
        return true;
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/simgear-2020.3.2/simgear/environment/test_metar.cxx 
new/simgear-2020.3.4/simgear/environment/test_metar.cxx
--- old/simgear-2020.3.2/simgear/environment/test_metar.cxx     2020-11-05 
12:33:00.000000000 +0100
+++ new/simgear-2020.3.4/simgear/environment/test_metar.cxx     2020-12-01 
10:16:23.000000000 +0100
@@ -81,6 +81,15 @@
     SGMetar m1("2020/10/23 16:55 LIVD 231655Z /////KT 9999 OVC025 10/08 Q1020 
RMK OVC VIS MIN 9999 BLU");
     SG_CHECK_EQUAL(m1.getWindDir(), -1);
     SG_CHECK_EQUAL_EP2(m1.getWindSpeed_kt(), -1, TEST_EPSILON);
+
+    SGMetar m2("2020/10/21 16:55 LIVD 211655Z /////KT CAVOK 07/03 Q1023 RMK 
SKC VIS MIN 9999 BLU");
+    SG_CHECK_EQUAL(m2.getWindDir(), -1);
+    SG_CHECK_EQUAL_EP2(m2.getWindSpeed_kt(), -1, TEST_EPSILON);
+
+    SGMetar m3("2020/11/17 16:00 CYAZ 171600Z 14040G//KT 10SM -RA OVC012 12/11 
A2895 RMK NS8 VIA CYXY SLP806 DENSITY ALT 900FT");
+    SG_CHECK_EQUAL(m3.getWindDir(), 140);
+    SG_CHECK_EQUAL_EP2(m3.getWindSpeed_kt(), 40, TEST_EPSILON);
+    SG_CHECK_EQUAL_EP2(m3.getGustSpeed_kt(), SGMetarNaN, TEST_EPSILON);
 }
 
 void test_wind_unit_not_specified()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/simgear-2020.3.2/simgear/io/DNSClient.cxx 
new/simgear-2020.3.4/simgear/io/DNSClient.cxx
--- old/simgear-2020.3.2/simgear/io/DNSClient.cxx       2020-11-05 
12:33:00.000000000 +0100
+++ new/simgear-2020.3.4/simgear/io/DNSClient.cxx       2020-12-01 
10:16:23.000000000 +0100
@@ -61,6 +61,10 @@
 
     struct dns_ctx * ctx;
     static size_t instanceCounter;
+
+    using RequestVec = std::vector<Request_ptr>;
+
+    RequestVec _activeRequests;
 };
 
 size_t Client::ClientPrivate::instanceCounter = 0;
@@ -78,6 +82,11 @@
 {
 }
 
+void Request::cancel()
+{
+    _cancelled = true;
+}
+
 bool Request::isTimeout() const
 {
     return (time(NULL) - _start) > _timeout_secs;
@@ -114,18 +123,20 @@
 {
     SRVRequest * r = static_cast<SRVRequest*>(data);
     if (result) {
-        r->cname = result->dnssrv_cname;
-        r->qname = result->dnssrv_qname;
-        r->ttl = result->dnssrv_ttl;
-        for (int i = 0; i < result->dnssrv_nrr; i++) {
-            SRVRequest::SRV_ptr srv(new SRVRequest::SRV);
-            r->entries.push_back(srv);
-            srv->priority = result->dnssrv_srv[i].priority;
-            srv->weight = result->dnssrv_srv[i].weight;
-            srv->port = result->dnssrv_srv[i].port;
-            srv->target = result->dnssrv_srv[i].name;
+        if (!r->isCancelled()) {
+            r->cname = result->dnssrv_cname;
+            r->qname = result->dnssrv_qname;
+            r->ttl = result->dnssrv_ttl;
+            for (int i = 0; i < result->dnssrv_nrr; i++) {
+                SRVRequest::SRV_ptr srv(new SRVRequest::SRV);
+                r->entries.push_back(srv);
+                srv->priority = result->dnssrv_srv[i].priority;
+                srv->weight = result->dnssrv_srv[i].weight;
+                srv->port = result->dnssrv_srv[i].port;
+                srv->target = result->dnssrv_srv[i].name;
+            }
+            std::sort(r->entries.begin(), r->entries.end(), sortSRV);
         }
-        std::sort( r->entries.begin(), r->entries.end(), sortSRV );
         free(result);
     }
     r->setComplete();
@@ -134,11 +145,16 @@
 void SRVRequest::submit( Client * client )
 {
     // if service is defined, pass service and protocol
-    if (!dns_submit_srv(client->d->ctx, getDn().c_str(), _service.empty() ? 
NULL : _service.c_str(), _service.empty() ? NULL : _protocol.c_str(), 0, 
dnscbSRV, this )) {
+    auto q = dns_submit_srv(client->d->ctx, getDn().c_str(), _service.empty() 
? NULL : _service.c_str(),
+                            _service.empty() ? NULL : _protocol.c_str(),
+                            0, dnscbSRV, this);
+
+    if (!q) {
         SG_LOG(SG_IO, SG_ALERT, "Can't submit dns request for " << getDn());
         return;
     }
     _start = time(NULL);
+    _query = q;
 }
 
 TXTRequest::TXTRequest( const std::string & dn ) :
@@ -151,22 +167,24 @@
 {
     TXTRequest * r = static_cast<TXTRequest*>(data);
     if (result) {
-        r->cname = result->dnstxt_cname;
-        r->qname = result->dnstxt_qname;
-        r->ttl = result->dnstxt_ttl;
-        for (int i = 0; i < result->dnstxt_nrr; i++) {
-          //TODO: interprete the .len field of dnstxt_txt?
-          auto rawTxt = reinterpret_cast<char*>(result->dnstxt_txt[i].txt);
-          if (!rawTxt) {
-              continue;
-          }
-
-          const string txt{rawTxt};
-          r->entries.push_back(txt);
-          string_list tokens = simgear::strutils::split( txt, "=", 1 );
-          if( tokens.size() == 2 ) {
-            r->attributes[tokens[0]] = tokens[1];
-          }
+        if (!r->isCancelled()) {
+            r->cname = result->dnstxt_cname;
+            r->qname = result->dnstxt_qname;
+            r->ttl = result->dnstxt_ttl;
+            for (int i = 0; i < result->dnstxt_nrr; i++) {
+                //TODO: interprete the .len field of dnstxt_txt?
+                auto rawTxt = 
reinterpret_cast<char*>(result->dnstxt_txt[i].txt);
+                if (!rawTxt) {
+                    continue;
+                }
+
+                const string txt{rawTxt};
+                r->entries.push_back(txt);
+                string_list tokens = simgear::strutils::split(txt, "=", 1);
+                if (tokens.size() == 2) {
+                    r->attributes[tokens[0]] = tokens[1];
+                }
+            }
         }
         free(result);
     }
@@ -176,11 +194,13 @@
 void TXTRequest::submit( Client * client )
 {
     // protocol and service an already encoded in DN so pass in NULL for both
-    if (!dns_submit_txt(client->d->ctx, getDn().c_str(), DNS_C_IN, 0, 
dnscbTXT, this )) {
+    auto q = dns_submit_txt(client->d->ctx, getDn().c_str(), DNS_C_IN, 0, 
dnscbTXT, this);
+    if (!q) {
         SG_LOG(SG_IO, SG_ALERT, "Can't submit dns request for " << getDn());
         return;
     }
     _start = time(NULL);
+    _query = q;
 }
 
 
@@ -195,27 +215,29 @@
 {
     NAPTRRequest * r = static_cast<NAPTRRequest*>(data);
     if (result) {
-        r->cname = result->dnsnaptr_cname;
-        r->qname = result->dnsnaptr_qname;
-        r->ttl = result->dnsnaptr_ttl;
-        for (int i = 0; i < result->dnsnaptr_nrr; i++) {
-            if( !r->qservice.empty() && r->qservice != 
result->dnsnaptr_naptr[i].service )
-                continue;
-
-            //TODO: case ignore and result flags may have more than one flag
-            if( !r->qflags.empty() && r->qflags != 
result->dnsnaptr_naptr[i].flags )
-                continue;
-
-            NAPTRRequest::NAPTR_ptr naptr(new NAPTRRequest::NAPTR);
-            r->entries.push_back(naptr);
-            naptr->order = result->dnsnaptr_naptr[i].order;
-            naptr->preference = result->dnsnaptr_naptr[i].preference;
-            naptr->flags = result->dnsnaptr_naptr[i].flags;
-            naptr->service = result->dnsnaptr_naptr[i].service;
-            naptr->regexp = result->dnsnaptr_naptr[i].regexp;
-            naptr->replacement = result->dnsnaptr_naptr[i].replacement;
+        if (!r->isCancelled()) {
+            r->cname = result->dnsnaptr_cname;
+            r->qname = result->dnsnaptr_qname;
+            r->ttl = result->dnsnaptr_ttl;
+            for (int i = 0; i < result->dnsnaptr_nrr; i++) {
+                if (!r->qservice.empty() && r->qservice != 
result->dnsnaptr_naptr[i].service)
+                    continue;
+
+                //TODO: case ignore and result flags may have more than one 
flag
+                if (!r->qflags.empty() && r->qflags != 
result->dnsnaptr_naptr[i].flags)
+                    continue;
+
+                NAPTRRequest::NAPTR_ptr naptr(new NAPTRRequest::NAPTR);
+                r->entries.push_back(naptr);
+                naptr->order = result->dnsnaptr_naptr[i].order;
+                naptr->preference = result->dnsnaptr_naptr[i].preference;
+                naptr->flags = result->dnsnaptr_naptr[i].flags;
+                naptr->service = result->dnsnaptr_naptr[i].service;
+                naptr->regexp = result->dnsnaptr_naptr[i].regexp;
+                naptr->replacement = result->dnsnaptr_naptr[i].replacement;
+            }
+            std::sort(r->entries.begin(), r->entries.end(), sortNAPTR);
         }
-        std::sort( r->entries.begin(), r->entries.end(), sortNAPTR );
         free(result);
     }
     r->setComplete();
@@ -223,11 +245,13 @@
 
 void NAPTRRequest::submit( Client * client )
 {
-    if (!dns_submit_naptr(client->d->ctx, getDn().c_str(), 0, dnscbNAPTR, this 
)) {
+    auto q = dns_submit_naptr(client->d->ctx, getDn().c_str(), 0, dnscbNAPTR, 
this);
+    if (!q) {
         SG_LOG(SG_IO, SG_ALERT, "Can't submit dns request for " << getDn());
         return;
     }
     _start = time(NULL);
+    _query = q;
 }
 
 
@@ -242,6 +266,7 @@
 
 void Client::makeRequest(const Request_ptr& r)
 {
+    d->_activeRequests.push_back(r);
     r->submit(this);
 }
 
@@ -252,6 +277,19 @@
         return;
 
     dns_ioevent(d->ctx, now);
+
+    // drop our owning ref to completed requests,
+    // and cancel any which timed out
+    auto it = std::remove_if(d->_activeRequests.begin(), 
d->_activeRequests.end(),
+                             [this](const Request_ptr& r) {
+                                 if (r->isTimeout()) {
+                                     dns_cancel(d->ctx, 
reinterpret_cast<struct dns_query*>(r->_query));
+                                     return true;
+                                 }
+
+                                 return r->isComplete();
+                             });
+    d->_activeRequests.erase(it, d->_activeRequests.end());
 }
 
 } // of namespace DNS
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/simgear-2020.3.2/simgear/io/DNSClient.hxx 
new/simgear-2020.3.4/simgear/io/DNSClient.hxx
--- old/simgear-2020.3.2/simgear/io/DNSClient.hxx       2020-11-05 
12:33:00.000000000 +0100
+++ new/simgear-2020.3.4/simgear/io/DNSClient.hxx       2020-12-01 
10:16:23.000000000 +0100
@@ -40,28 +40,38 @@
 {
 
 class Client;
+
+using UDNSQueryPtr = void*;
+
 class Request : public SGReferenced
 {
 public:
     Request( const std::string & dn );
     virtual ~Request();
-    std::string getDn() const { return _dn; }
+    const std::string& getDn() const { return _dn; }
     int getType() const { return _type; }
     bool isComplete() const { return _complete; }
     bool isTimeout() const;
     void setComplete( bool b = true ) { _complete = b; }
+    bool isCancelled() const { return _cancelled; }
 
     virtual void submit( Client * client) = 0;
 
+    void cancel();
+
     std::string cname;
     std::string qname;
     unsigned ttl;
 protected:
+    friend class Client;
+
+    UDNSQueryPtr _query = nullptr;
     std::string _dn;
     int _type;
     bool _complete;
     time_t _timeout_secs;
     time_t _start;
+    bool _cancelled = false;
 };
 typedef SGSharedPtr<Request> Request_ptr;
 
@@ -69,7 +79,7 @@
 {
 public:
     NAPTRRequest( const std::string & dn );
-    virtual void submit( Client * client );
+    void submit(Client* client) override;
 
     struct NAPTR : SGReferenced {
         int order;
@@ -92,7 +102,7 @@
 public:
     SRVRequest( const std::string & dn );
     SRVRequest( const std::string & dn, const string & service, const string & 
protocol );
-    virtual void submit( Client * client );
+    void submit(Client* client) override;
 
     struct SRV : SGReferenced {
       int priority;
@@ -112,7 +122,7 @@
 {
 public:
     TXTRequest( const std::string & dn );
-    virtual void submit( Client * client );
+    void submit(Client* client) override;
 
     typedef std::vector<string> TXT_list;
     typedef std::map<std::string,std::string> TXT_Attribute_map;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/simgear-2020.3.2/simgear/io/HTTPRepository.cxx 
new/simgear-2020.3.4/simgear/io/HTTPRepository.cxx
--- old/simgear-2020.3.2/simgear/io/HTTPRepository.cxx  2020-11-05 
12:33:00.000000000 +0100
+++ new/simgear-2020.3.4/simgear/io/HTTPRepository.cxx  2020-12-01 
10:16:23.000000000 +0100
@@ -994,7 +994,10 @@
       }
 
       void onDone() override {
-        file->close();
+          if (file) {
+              file->close();
+          }
+
         if (responseCode() == 200) {
           std::string hash =
               strutils::encodeHex(sha1_result(&hashContext), HASH_LENGTH);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/simgear-2020.3.2/simgear/package/Root.cxx 
new/simgear-2020.3.4/simgear/package/Root.cxx
--- old/simgear-2020.3.2/simgear/package/Root.cxx       2020-11-05 
12:33:00.000000000 +0100
+++ new/simgear-2020.3.4/simgear/package/Root.cxx       2020-12-01 
10:16:23.000000000 +0100
@@ -722,12 +722,6 @@
     auto catIt = d->catalogs.find(aCat->id());
     d->fireRefreshStatus(aCat, aReason);
 
-    if (aReason == Delegate::STATUS_IN_PROGRESS) {
-        d->refreshing.insert(aCat);
-    } else {
-        d->refreshing.erase(aCat);
-    }
-
     if (aCat->isUserEnabled() &&
         (aReason == Delegate::STATUS_REFRESHED) && 
         (catIt == d->catalogs.end())) 
@@ -761,6 +755,17 @@
         }
     } // of catalog is disabled
 
+    // remove from refreshing /after/ checking for enable / disabled, since for
+    // new catalogs, the reference in d->refreshing might be our /only/
+    // reference to the catalog. Once the refresh is done (either failed or
+    // succeeded) the Catalog will be in either d->catalogs or
+    // d->disabledCatalogs
+    if (aReason == Delegate::STATUS_IN_PROGRESS) {
+      d->refreshing.insert(aCat);
+    } else {
+      d->refreshing.erase(aCat);
+    }
+
     if (d->refreshing.empty()) {
         d->fireRefreshStatus(CatalogRef(), Delegate::STATUS_REFRESHED);
         d->firePackagesChanged();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/simgear-2020.3.2/simgear/props/props.cxx 
new/simgear-2020.3.4/simgear/props/props.cxx
--- old/simgear-2020.3.2/simgear/props/props.cxx        2020-11-05 
12:33:00.000000000 +0100
+++ new/simgear-2020.3.4/simgear/props/props.cxx        2020-12-01 
10:16:23.000000000 +0100
@@ -19,6 +19,10 @@
 #include <sstream>
 #include <iomanip>
 #include <iterator>
+#include <exception> // can't use sg_exception becuase of PROPS_STANDALONE
+#include <mutex>
+#include <thread>
+
 #include <stdio.h>
 #include <string.h>
 
@@ -51,11 +55,15 @@
 
 struct SGPropertyNodeListeners
 {
+  /* Protect _num_iterators and _items. We use a recursive mutex to allow
+  nested access to work as normal. */
+  std::recursive_mutex  _rmutex;
+
   /* This keeps a count of the current number of nested invocations of
   forEachListener(). If non-zero, other code higher up the stack is iterating
   _items[] so for example code must not erase items in the vector. */
   int _num_iterators = 0;
-  
+
   std::vector<SGPropertyChangeListener *> _items;
 };
 
@@ -2406,6 +2414,7 @@
   if (_listeners == 0)
     _listeners = new SGPropertyNodeListeners;
 
+  std::lock_guard<std::recursive_mutex> lock(_listeners->_rmutex);
   /* If there's a nullptr entry (a listener that was unregistered), we
   overwrite it. This ensures that listeners that routinely unregister+register
   themselves don't make _listeners->_items grow unnecessarily. Otherwise simply
@@ -2429,9 +2438,13 @@
 {
   if (_listeners == 0)
     return;
+  /* We use a std::unique_lock rather than a std::lock_guard because we may
+  need to unlock early. */
+  std::unique_lock<std::recursive_mutex> lock(_listeners->_rmutex);
   vector<SGPropertyChangeListener*>::iterator it =
     find(_listeners->_items.begin(), _listeners->_items.end(), listener);
   if (it != _listeners->_items.end()) {
+    assert(_listeners->_num_iterators >= 0);
     if (_listeners->_num_iterators) {
       /* _listeners._items is currently being iterated further up the stack in
       this thread by one or more nested invocations of forEachListener(), so
@@ -2450,6 +2463,7 @@
       _listeners->_items.erase(it);
       listener->unregister_property(this);
       if (_listeners->_items.empty()) {
+        lock.unlock();
         delete _listeners;
         _listeners = 0;
       }
@@ -2511,9 +2525,11 @@
     )
 {
   if (!_listeners) return;
-  
+
+  std::lock_guard<std::recursive_mutex> lock(_listeners->_rmutex);
+  assert(_listeners->_num_iterators >= 0);
   _listeners->_num_iterators += 1;
-  
+
   /* We need to use an index here when iterating _listeners->_items, not an
   iterator. This is because a listener may add new listeners, causing the
   vector to be reallocated, which would invalidate any iterator. */
@@ -2528,10 +2544,12 @@
       }
     }
   }
-  
+
   _listeners->_num_iterators -= 1;
-  
+  assert(_listeners->_num_iterators >= 0);
+
   if (_listeners->_num_iterators == 0) {
+
     /* Remove any items that have been set to nullptr. */
     _listeners->_items.erase(
         std::remove(_listeners->_items.begin(), _listeners->_items.end(), 
(SGPropertyChangeListener*) nullptr),
@@ -2547,6 +2565,7 @@
 int SGPropertyNode::nListeners() const
 {
   if (!_listeners) return 0;
+  std::lock_guard<std::recursive_mutex> lock(_listeners->_rmutex);
   int   n = 0;
   for (auto listener: _listeners->_items) {
     if (listener)   n += 1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/simgear-2020.3.2/simgear/scene/tgdb/ReaderWriterSTG.cxx 
new/simgear-2020.3.4/simgear/scene/tgdb/ReaderWriterSTG.cxx
--- old/simgear-2020.3.2/simgear/scene/tgdb/ReaderWriterSTG.cxx 2020-11-05 
12:33:00.000000000 +0100
+++ new/simgear-2020.3.4/simgear/scene/tgdb/ReaderWriterSTG.cxx 2020-12-01 
10:16:23.000000000 +0100
@@ -212,7 +212,8 @@
             STGObjectsQuadtree quadtree((GetModelLODCoord()), (AddModelLOD()));
             quadtree.buildQuadTree(_objectStaticList.begin(), 
_objectStaticList.end());
             osg::ref_ptr<osg::Group> group = quadtree.getRoot();
-            group->setName("STG-group-A");
+            string group_name = string("STG-group-A 
").append(_bucket.gen_index_str());
+            group->setName(group_name);
             group->setDataVariance(osg::Object::STATIC);
 
             simgear::AirportSignBuilder 
signBuilder(_options->getMaterialLib(), _bucket.get_center());
@@ -586,10 +587,12 @@
     {
         osg::ref_ptr<SGReaderWriterOptions> options;
         options = SGReaderWriterOptions::copyOrCreate(opt);
+        float pagedLODExpiry = 
atoi(options->getPluginStringData("SimGear::PAGED_LOD_EXPIRY").c_str());
 
         osg::ref_ptr<osg::Group> terrainGroup = new osg::Group;
         terrainGroup->setDataVariance(osg::Object::STATIC);
-        terrainGroup->setName("terrain");
+        std::string terrain_name = string("terrain 
").append(bucket.gen_index_str());
+        terrainGroup->setName(terrain_name);
 
         if (_foundBase) {
             for (auto stgObject : _objectList) {
@@ -637,11 +640,13 @@
         } else {
             osg::PagedLOD* pagedLOD = new osg::PagedLOD;
             pagedLOD->setCenterMode(osg::PagedLOD::USE_BOUNDING_SPHERE_CENTER);
-            pagedLOD->setName("pagedObjectLOD");
+            std::string name = string("pagedObjectLOD 
").append(bucket.gen_index_str());
+            pagedLOD->setName(name);
 
             // This should be visible in any case.
             // If this is replaced by some lower level of detail, the parent 
LOD node handles this.
             pagedLOD->addChild(terrainGroup, 0, 
std::numeric_limits<float>::max());
+            pagedLOD->setMinimumExpiryTime(0, pagedLODExpiry);
 
             // we just need to know about the read file callback that itself 
holds the data
             osg::ref_ptr<DelayLoadReadFileCallback> readFileCallback = new 
DelayLoadReadFileCallback;
@@ -658,10 +663,11 @@
 
             // Objects may end up displayed up to 2x the object range.
             pagedLOD->setRange(pagedLOD->getNumChildren(), 0, 2.0 * 
_object_range_rough);
+            pagedLOD->setMinimumExpiryTime(pagedLOD->getNumChildren(), 
pagedLODExpiry);
             pagedLOD->setRadius(SG_TILE_RADIUS);
-            SG_LOG( SG_TERRAIN, SG_DEBUG, "Tile PagedLOD Center: " << 
pagedLOD->getCenter().x() << "," << pagedLOD->getCenter().y() << "," << 
pagedLOD->getCenter().z() );
-            SG_LOG( SG_TERRAIN, SG_DEBUG, "Tile PagedLOD Range: " << (2.0 * 
_object_range_rough));
-            SG_LOG( SG_TERRAIN, SG_DEBUG, "Tile PagedLOD Radius: " << 
SG_TILE_RADIUS);
+            SG_LOG( SG_TERRAIN, SG_DEBUG, "Tile " << bucket.gen_index_str() << 
" PagedLOD Center: " << pagedLOD->getCenter().x() << "," << 
pagedLOD->getCenter().y() << "," << pagedLOD->getCenter().z() );
+            SG_LOG( SG_TERRAIN, SG_DEBUG, "Tile " << bucket.gen_index_str() << 
" PagedLOD Range: " << (2.0 * _object_range_rough));
+            SG_LOG( SG_TERRAIN, SG_DEBUG, "Tile " << bucket.gen_index_str() << 
" PagedLOD Radius: " << SG_TILE_RADIUS);
             return pagedLOD;
         }
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/simgear-2020.3.2/simgear-version 
new/simgear-2020.3.4/simgear-version
--- old/simgear-2020.3.2/simgear-version        2020-11-05 12:33:00.000000000 
+0100
+++ new/simgear-2020.3.4/simgear-version        2020-12-01 10:16:23.000000000 
+0100
@@ -1 +1 @@
-2020.3.2
+2020.3.4
_______________________________________________
openSUSE Commits mailing list -- [email protected]
To unsubscribe, email [email protected]
List Netiquette: https://en.opensuse.org/openSUSE:Mailing_list_netiquette
List Archives: 
https://lists.opensuse.org/archives/list/[email protected]

Reply via email to