[mapguide-commits] r10233 - in branches/4.0/MgDev: Common/Foundation/System Common/Geometry/CoordinateSystem Common/MdfParser Oem/geos/include/geos/geomgraph Oem/geos/src/geomgraph Oem/geos/src/operation/overlay Server/src/Common/Thread Server/src/Core Server/src/Services/Feature Server/src/Services/Kml Server/src/Services/Tile Server/src/UnitTesting
svn_mapguide at osgeo.org
svn_mapguide at osgeo.org
Fri Oct 30 03:42:01 PDT 2026
Author: jng
Date: 2026-10-30 03:41:59 -0700 (Fri, 30 Oct 2026)
New Revision: 10233
Modified:
branches/4.0/MgDev/Common/Foundation/System/XmlUtil.cpp
branches/4.0/MgDev/Common/Geometry/CoordinateSystem/CoordinateSystemFactory.cpp
branches/4.0/MgDev/Common/MdfParser/IOGridColorBands.cpp
branches/4.0/MgDev/Oem/geos/include/geos/geomgraph/EdgeRing.h
branches/4.0/MgDev/Oem/geos/src/geomgraph/EdgeRing.cpp
branches/4.0/MgDev/Oem/geos/src/operation/overlay/MaximalEdgeRing.cpp
branches/4.0/MgDev/Oem/geos/src/operation/overlay/MinimalEdgeRing.cpp
branches/4.0/MgDev/Oem/geos/src/operation/overlay/PolygonBuilder.cpp
branches/4.0/MgDev/Server/src/Common/Thread/ThreadBase.cpp
branches/4.0/MgDev/Server/src/Core/Server.cpp
branches/4.0/MgDev/Server/src/Services/Feature/FdoForcedOneToOneFeatureReader.cpp
branches/4.0/MgDev/Server/src/Services/Kml/ServerKmlService.cpp
branches/4.0/MgDev/Server/src/Services/Tile/TileCacheDefault.cpp
branches/4.0/MgDev/Server/src/UnitTesting/TestRasterStylization.cpp
branches/4.0/MgDev/Server/src/UnitTesting/TestTileService.cpp
Log:
Plug the leaks reported by mgserver test all on Linux
The Debug `mgserver test all` run reported 647,644 bytes in 1,587 allocations - 27 direct and
216 indirect records - and now produces no LeakSanitizer report at all. Most of the records
were a counted reference dropped on the line that used it; the rest were process-lifetime
state that only a teardown can reach, and one was a thread that outlived the wait intended to
stop it. 610 cases ran with 608 passing before and after (the two failures are TestLogManager
cases, unchanged by this work).
* Common/Foundation/System/XmlUtil.cpp: MgXmlUtil::ToBytes() released the serializer and the
format target but not the DOMLSOutput that createLSOutput() hands to its caller, which is
9,120 B in 190 records carrying no frames of their own (XMemory::operator new). It is
released now.
* Common/Geometry/CoordinateSystem/CoordinateSystemFactory.cpp and Server/src/Core/Server.cpp:
EnumerateCoordinateSystems makes CS-Map read the whole Category.CSD into process globals -
CSrdCategoryEx, 265,536 B in 245 records - and only CSrlsCategories() releases them. The
catalog itself is not destroyed at shutdown, because live coordinate system objects still
hold 22 references to it, and CS-Map is compiled without ASan, so its C globals are not LSan
roots: a cache still resident at teardown reads as leaked. MgCoordinateSystemFactory::
DeleteCatalog() - which already existed - now calls CSrlsCategories(), and MgServer::fini()
calls it in the "orderly clean up applicable static manager objects" block. Freeing it only
at static destruction would not have helped: LSan's check is an atexit handler and runs
before __cxa_finalize.
* Common/MdfParser/IOGridColorBands.cpp: StartElement() creates one ChannelBand per
<RedBand>/<GreenBand>/<BlueBand> and EndElement() only copies their values into the
GridColorBands it adopts, so nothing else ever owned them - 2,592 B in 27 records. Deleted
in ~IOGridColorBands.
* Oem/geos/src/operation/overlay/{PolygonBuilder,MaximalEdgeRing,MinimalEdgeRing}.cpp and
Oem/geos/src/geomgraph/EdgeRing.cpp (declaration in include/geos/geomgraph/EdgeRing.h): a
TopologyException escaping PolygonBuilder::add() left maxEdgeRings, edgeRings and
freeHoleList behind - 4,800 B direct and about 15 KB indirect - and SnapIfNeededOverlayOp
retries the operation with snapped inputs, so a *passing* geometry suite was leaking the
partial result of every failed attempt. add(), buildMaximalEdgeRings() and
buildMinimalEdgeRings() release what they built before rethrowing, with each ring's
ownership moved by nulling its vector entry (and resizing maxEdgeRings) so that the
caller's cleanup cannot delete it a second time. A ring constructor that throws runs no
destructor either, so EdgeRing::cleanupAfterFailedConstruction() releases the point
sequence or the ring it was given, and the MaximalEdgeRing/MinimalEdgeRing constructors
call it from a catch (...) { ...; throw; }.
* Server/src/Common/Thread/ThreadBase.cpp: MgThreadBase::Activate() spawned its threads with
THR_DETACHED, and ACE_Task::wait() on a detached thread returns immediately (measured: 0 us,
against 500 us for a joinable thread doing the same half-second of work), so the waits in
MgLogManager::StopLogThread, MgServerManager::StopWorkerThreads and MgServer::svc were
no-ops. main() then called ACE::fini() with the log thread still running, which finalised
ACE's thread-specific-storage machinery before that thread exited, so its ACE_Log_Msg
(4,216 B), the log message's 4,097 B buffer and its ACE_Thread_Exit (16 B) were never
released. The threads are joinable now (THR_NEW_LWP without THR_DETACHED), which makes the
existing waits actually wait: every pool prints "Exiting thread" before
MgServer::~MgServer().
* Server/src/Services/Tile/TileCacheDefault.cpp: MgTileCacheDefault::GetMapFromDefinition()
passed MgUserInformation::GetCurrentUserInfo() - a counted reference - straight to
MgSiteConnection::Open(), 4 x 320 B. Held in a Ptr<MgUserInformation> now.
* Server/src/Services/Kml/ServerKmlService.cpp: GetPointStyleImageUrl() called
layer->GetLayerDefinition()->ToString(), dropping the definition id's reference (272 B). The
id is held in a Ptr<MgResourceIdentifier> and reused for the lookup further down, which
fetched it a second time.
* Server/src/Services/Feature/FdoForcedOneToOneFeatureReader.cpp: GetIdentityHash() used a raw
FdoStringElement* for FdoStringCollection::GetItem(), which returns an AddRef'ed element -
3 x 48 B. It is an FdoPtr now.
* Server/src/UnitTesting/TestRasterStylization.cpp: PublishFeatureSource() dropped the class
collection MgFeatureSchema::GetClasses() returns - 1,800 B for the collection and 285 KB
indirect, being every class definition, property definition and string behind it - and the
two footprint checks dereferenced GetLowerLeftCoordinate()/GetUpperRightCoordinate() on an
MgEnvelope inline, for 1,280 B in 10 records. Each is held in a Ptr.
* Server/src/UnitTesting/TestTileService.cpp: two tests allocated a runtime map with a raw
MgMap* and never released it. The map was not itself in the report: MgLayerCollection keeps
a raw back-pointer to its map, so what LSan saw was one cycle in which every chunk was
reachable from another, and 172 KB of indirect records was the sign of it. Ptr<MgMap> now.
The binding surface does not move. No .i file, MapGuideApiGen.xml or SwigCommon fragment is
touched, MgCoordinateSystemFactory::DeleteCatalog() already existed, and the only header in the
change (Oem/geos/include/geos/geomgraph/EdgeRing.h) is internal GEOS, so there is nothing to
re-cut in the API dumps.
Modified: branches/4.0/MgDev/Common/Foundation/System/XmlUtil.cpp
===================================================================
--- branches/4.0/MgDev/Common/Foundation/System/XmlUtil.cpp 2026-10-25 09:28:58 UTC (rev 10232)
+++ branches/4.0/MgDev/Common/Foundation/System/XmlUtil.cpp 2026-10-30 10:41:59 UTC (rev 10233)
@@ -778,6 +778,11 @@
MG_XML_CATCH(L"MgXmlUtil.ToBytes")
delete theSerializer;
+ // the output descriptor is owned by the caller of createLSOutput(), not by the serializer
+ if (NULL != theOutputDesc)
+ {
+ theOutputDesc->release();
+ }
delete memTarget;
MG_XML_THROW()
Modified: branches/4.0/MgDev/Common/Geometry/CoordinateSystem/CoordinateSystemFactory.cpp
===================================================================
--- branches/4.0/MgDev/Common/Geometry/CoordinateSystem/CoordinateSystemFactory.cpp 2026-10-25 09:28:58 UTC (rev 10232)
+++ branches/4.0/MgDev/Common/Geometry/CoordinateSystem/CoordinateSystemFactory.cpp 2026-10-30 10:41:59 UTC (rev 10233)
@@ -40,6 +40,7 @@
#include "CoordSysGridGeneric.h" //for CCoordinateSystemGridGeneric
#include "CoordinateSystemFactory.h" //for MgCoordinateSystemFactory
#include "CoordinateSystemCache.h"
+#include "cs_map.h"
using namespace CSLibrary;
@@ -180,6 +181,12 @@
sm_pCatalog->Release();
sm_pCatalog = NULL;
}
+
+ // CS-Map keeps the category dictionary it has read in process globals, which only
+ // CSrlsCategories() releases. The catalog above does not necessarily get destroyed here -
+ // live coordinate system objects hold references to it - so release the dictionary
+ // directly; CS-Map re-reads the file if anything asks for a category after this point.
+ CSrlsCategories();
}
Modified: branches/4.0/MgDev/Common/MdfParser/IOGridColorBands.cpp
===================================================================
--- branches/4.0/MgDev/Common/MdfParser/IOGridColorBands.cpp 2026-10-25 09:28:58 UTC (rev 10232)
+++ branches/4.0/MgDev/Common/MdfParser/IOGridColorBands.cpp 2026-10-30 10:41:59 UTC (rev 10233)
@@ -52,6 +52,12 @@
IOGridColorBands::~IOGridColorBands()
{
+ // StartElement() creates one ChannelBand per band element, and EndElement() only copies
+ // their values into the GridColorBands it adopts, so these instances are never owned by
+ // anything else and have to be released here.
+ delete this->m_redChannel;
+ delete this->m_greenChannel;
+ delete this->m_blueChannel;
}
Modified: branches/4.0/MgDev/Oem/geos/include/geos/geomgraph/EdgeRing.h
===================================================================
--- branches/4.0/MgDev/Oem/geos/include/geos/geomgraph/EdgeRing.h 2026-10-25 09:28:58 UTC (rev 10232)
+++ branches/4.0/MgDev/Oem/geos/include/geos/geomgraph/EdgeRing.h 2026-10-30 10:41:59 UTC (rev 10233)
@@ -171,6 +171,14 @@
void addPoints(Edge *edge, bool isForward, bool isFirstEdge);
+ /** \brief
+ * Release the geometry built so far.
+ *
+ * A constructor of a derived class which throws runs no destructor, so the
+ * point sequence and the ring it created leak unless it releases them here.
+ */
+ void cleanupAfterFailedConstruction();
+
/// a list of EdgeRings which are holes in this EdgeRing
std::vector<EdgeRing*> holes;
Modified: branches/4.0/MgDev/Oem/geos/src/geomgraph/EdgeRing.cpp
===================================================================
--- branches/4.0/MgDev/Oem/geos/src/geomgraph/EdgeRing.cpp 2026-10-25 09:28:58 UTC (rev 10232)
+++ branches/4.0/MgDev/Oem/geos/src/geomgraph/EdgeRing.cpp 2026-10-30 10:41:59 UTC (rev 10233)
@@ -109,6 +109,23 @@
#endif
}
+/*protected*/
+void
+EdgeRing::cleanupAfterFailedConstruction()
+{
+ // ownership of [pts] passes to [ring] when the ring is created, see the destructor
+ if ( ring == NULL )
+ {
+ delete pts;
+ }
+ else
+ {
+ delete ring;
+ }
+ pts = NULL;
+ ring = NULL;
+}
+
bool
EdgeRing::isIsolated()
{
Modified: branches/4.0/MgDev/Oem/geos/src/operation/overlay/MaximalEdgeRing.cpp
===================================================================
--- branches/4.0/MgDev/Oem/geos/src/operation/overlay/MaximalEdgeRing.cpp 2026-10-25 09:28:58 UTC (rev 10232)
+++ branches/4.0/MgDev/Oem/geos/src/operation/overlay/MaximalEdgeRing.cpp 2026-10-30 10:41:59 UTC (rev 10233)
@@ -52,8 +52,17 @@
:
EdgeRing(start, geometryFactory)
{
- computePoints(start);
- computeRing();
+ try
+ {
+ computePoints(start);
+ computeRing();
+ }
+ catch (...)
+ {
+ // a throwing constructor runs no destructor, so release what we built
+ cleanupAfterFailedConstruction();
+ throw;
+ }
#if GEOS_DEBUG
cerr << "MaximalEdgeRing[" << this << "] ctor" << endl;
#endif
Modified: branches/4.0/MgDev/Oem/geos/src/operation/overlay/MinimalEdgeRing.cpp
===================================================================
--- branches/4.0/MgDev/Oem/geos/src/operation/overlay/MinimalEdgeRing.cpp 2026-10-25 09:28:58 UTC (rev 10232)
+++ branches/4.0/MgDev/Oem/geos/src/operation/overlay/MinimalEdgeRing.cpp 2026-10-30 10:41:59 UTC (rev 10233)
@@ -41,8 +41,17 @@
:
geomgraph::EdgeRing(start, geometryFactory)
{
- computePoints(start);
- computeRing();
+ try
+ {
+ computePoints(start);
+ computeRing();
+ }
+ catch (...)
+ {
+ // a throwing constructor runs no destructor, so release what we built
+ cleanupAfterFailedConstruction();
+ throw;
+ }
#if GEOS_DEBUG
std::cerr << "MinimalEdgeRing[" << this << "] ctor" << std::endl;
#endif
Modified: branches/4.0/MgDev/Oem/geos/src/operation/overlay/PolygonBuilder.cpp
===================================================================
--- branches/4.0/MgDev/Oem/geos/src/operation/overlay/PolygonBuilder.cpp 2026-10-25 09:28:58 UTC (rev 10232)
+++ branches/4.0/MgDev/Oem/geos/src/operation/overlay/PolygonBuilder.cpp 2026-10-30 10:41:59 UTC (rev 10233)
@@ -108,16 +108,39 @@
PlanarGraph::linkResultDirectedEdges(nodes->begin(), nodes->end());
vector<MaximalEdgeRing*> maxEdgeRings;
- buildMaximalEdgeRings(dirEdges, maxEdgeRings);
-
vector<EdgeRing*> freeHoleList;
vector<MaximalEdgeRing*> edgeRings;
- buildMinimalEdgeRings(maxEdgeRings, shellList, freeHoleList, edgeRings);
- sortShellsAndHoles(edgeRings, shellList, freeHoleList);
+ // A TopologyException thrown here is not fatal: SnapIfNeededOverlayOp retries the
+ // operation with snapped inputs. The rings built for the failed attempt are not owned
+ // by anything the caller can see, so they have to be released before the exception
+ // leaves this function - otherwise every retried overlay leaks its partial result.
+ try
+ {
+ buildMaximalEdgeRings(dirEdges, maxEdgeRings);
+ buildMinimalEdgeRings(maxEdgeRings, shellList, freeHoleList, edgeRings);
- placeFreeHoles(shellList, freeHoleList);
- //Assert: every hole on freeHoleList has a shell assigned to it
+ // [sortShellsAndHoles] hands every ring over to one of the two lists
+ sortShellsAndHoles(edgeRings, shellList, freeHoleList);
+ edgeRings.clear();
+
+ placeFreeHoles(shellList, freeHoleList);
+ //Assert: every hole on freeHoleList has a shell assigned to it
+ }
+ catch (...)
+ {
+ for(size_t i=0, n=maxEdgeRings.size(); i<n; ++i)
+ delete maxEdgeRings[i];
+ for(size_t i=0, n=edgeRings.size(); i<n; ++i)
+ delete edgeRings[i];
+ for(size_t i=0, n=freeHoleList.size(); i<n; ++i)
+ {
+ // a hole which has already been assigned to a shell is owned by that shell
+ if (freeHoleList[i]->getShell() == NULL)
+ delete freeHoleList[i];
+ }
+ throw;
+ }
}
/*public*/
@@ -164,6 +187,9 @@
{ // cleanup if that happens (see stmlf-cases-20061020.xml)
for(size_t i=oldSize, n=maxEdgeRings.size(); i<n; i++)
delete maxEdgeRings[i];
+ // ...and drop them from the vector, so that the caller's own cleanup does not
+ // delete them a second time
+ maxEdgeRings.resize(oldSize);
//cerr << "Exception! " << e.what() << endl;
throw;
}
@@ -188,27 +214,52 @@
for(size_t i=0, n=maxEdgeRings.size(); i<n; ++i)
{
MaximalEdgeRing *er = maxEdgeRings[i];
+ // this ring is owned by this function from here on: [-add()] cleans up
+ // whatever is still in the vector if we throw
+ maxEdgeRings[i] = NULL;
#if GEOS_DEBUG
- cerr<<"buildMinimalEdgeRings: maxEdgeRing "<<i<<" has "<<er->getMaxNodeDegree()<<" maxNodeDegree"<<endl;
+ cerr<<"buildMinimalEdgeRings: maxEdgeRing "<<i<<" has "<<er->getMaxNodeDegree()<<" maxNodeDegree"<<endl;
#endif
if (er->getMaxNodeDegree()>2)
{
- er->linkDirectedEdgesForMinimalEdgeRings();
vector<MinimalEdgeRing*> minEdgeRings;
- er->buildMinimalRings(minEdgeRings);
- // at this point we can go ahead and attempt to place
- // holes, if this EdgeRing is a polygon
- EdgeRing *shell=findShell(&minEdgeRings);
- if(shell != NULL)
+ EdgeRing *shell = NULL;
+ bool shellHandedOver = false;
+ try
{
- placePolygonHoles(shell, &minEdgeRings);
- newShellList.push_back(shell);
+ er->linkDirectedEdgesForMinimalEdgeRings();
+ er->buildMinimalRings(minEdgeRings);
+ // at this point we can go ahead and attempt to place
+ // holes, if this EdgeRing is a polygon
+ shell=findShell(&minEdgeRings);
+ if(shell != NULL)
+ {
+ placePolygonHoles(shell, &minEdgeRings);
+ newShellList.push_back(shell);
+ shellHandedOver = true;
+ }
+ else
+ {
+ freeHoleList.insert(freeHoleList.end(),
+ minEdgeRings.begin(),
+ minEdgeRings.end() );
+ minEdgeRings.clear(); // now owned by [freeHoleList]
+ }
}
- else
+ catch (...)
{
- freeHoleList.insert(freeHoleList.end(),
- minEdgeRings.begin(),
- minEdgeRings.end() );
+ // release the rings this iteration created but has not handed over,
+ // so that they do not outlive the exception
+ for(size_t j=0, m=minEdgeRings.size(); j<m; ++j)
+ {
+ EdgeRing *ring = minEdgeRings[j];
+ // a ring which already has a shell is owned by that shell, and a
+ // shell which is already in [newShellList] is owned by the builder
+ if (ring == shell ? !shellHandedOver : ring->getShell() == NULL)
+ delete ring;
+ }
+ delete er;
+ throw;
}
delete er;
}
Modified: branches/4.0/MgDev/Server/src/Common/Thread/ThreadBase.cpp
===================================================================
--- branches/4.0/MgDev/Server/src/Common/Thread/ThreadBase.cpp 2026-10-25 09:28:58 UTC (rev 10232)
+++ branches/4.0/MgDev/Server/src/Common/Thread/ThreadBase.cpp 2026-10-30 10:41:59 UTC (rev 10233)
@@ -40,7 +40,13 @@
{
INT32 nResult = 0;
- if (activate(THR_DETACHED | THR_NEW_LWP, m_nThreads) == -1)
+ // The threads have to be joinable: every shutdown path stops them with an MB_STOP
+ // message and then waits (MgLogManager::StopLogThread, MgServerManager::StopWorkerThreads,
+ // MgServer::svc), and ACE_Task::wait() on a THR_DETACHED thread returns immediately
+ // instead of waiting. A thread which outlives that wait is still running when main()
+ // calls ACE::fini(), which releases ACE's thread-specific-storage machinery - so the
+ // per-thread ACE_Log_Msg/ACE_Thread_Exit of that thread are never freed.
+ if (activate(THR_NEW_LWP, m_nThreads) == -1)
{
ACE_ERROR ((LM_ERROR, ACE_TEXT("%p\n"), ACE_TEXT("MgThreadBase::activate")));
nResult = -1;
Modified: branches/4.0/MgDev/Server/src/Core/Server.cpp
===================================================================
--- branches/4.0/MgDev/Server/src/Core/Server.cpp 2026-10-25 09:28:58 UTC (rev 10232)
+++ branches/4.0/MgDev/Server/src/Core/Server.cpp 2026-10-30 10:41:59 UTC (rev 10233)
@@ -164,6 +164,11 @@
MgLoadBalanceManager::Terminate();
MgLongTransactionManager::Terminate();
+ // The coordinate system catalog is a static that holds CS-Map's in-memory dictionaries,
+ // which are plain C globals in a library that is not ASan-instrumented - so they are only
+ // visible to a leak check if they are released here rather than at static destruction.
+ MgCoordinateSystemFactory::DeleteCatalog();
+
MgLicenseManager* licenseManager = MgLicenseManager::GetInstance();
ACE_ASSERT(NULL != licenseManager);
licenseManager->Terminate();
Modified: branches/4.0/MgDev/Server/src/Services/Feature/FdoForcedOneToOneFeatureReader.cpp
===================================================================
--- branches/4.0/MgDev/Server/src/Services/Feature/FdoForcedOneToOneFeatureReader.cpp 2026-10-25 09:28:58 UTC (rev 10232)
+++ branches/4.0/MgDev/Server/src/Services/Feature/FdoForcedOneToOneFeatureReader.cpp 2026-10-30 10:41:59 UTC (rev 10233)
@@ -250,7 +250,7 @@
bool append = false;
wchar_t tbuff[256];
//Don't bother with IsNull() checks. These are identity property values, how can they be null?
- FdoStringElement* el = m_idPropNames->GetItem(i);
+ FdoPtr<FdoStringElement> el = m_idPropNames->GetItem(i);
FdoStringP str = el->GetString();
FdoString* name = (FdoString*)str;
Modified: branches/4.0/MgDev/Server/src/Services/Kml/ServerKmlService.cpp
===================================================================
--- branches/4.0/MgDev/Server/src/Services/Kml/ServerKmlService.cpp 2026-10-25 09:28:58 UTC (rev 10232)
+++ branches/4.0/MgDev/Server/src/Services/Kml/ServerKmlService.cpp 2026-10-30 10:41:59 UTC (rev 10233)
@@ -884,8 +884,11 @@
STRING MgServerKmlService::GetPointStyleImageUrl(STRING agentUri, MgLayer* layer, double scale, CREFSTRING sessionId)
{
+ // GetLayerDefinition() returns a counted reference: hold it rather than dropping it inline
+ Ptr<MgResourceIdentifier> resId = layer->GetLayerDefinition();
+
STRING strLegendImage = agentUri + L"?OPERATION=GetLegendImage&LAYERDEFINITION=";
- strLegendImage += layer->GetLayerDefinition()->ToString();
+ strLegendImage += resId->ToString();
strLegendImage += L"&SCALE=" ;
STRING strScale;
@@ -895,7 +898,6 @@
STRING strGeomType;
STRING strCategoryIndex = L"-1";
//get layer definition
- Ptr<MgResourceIdentifier> resId = layer->GetLayerDefinition();
unique_ptr<MdfModel::LayerDefinition> ldf(MgLayerBase::GetLayerDefinition(m_svcResource, resId));
MdfModel::VectorLayerDefinition* vl = dynamic_cast<MdfModel::VectorLayerDefinition*>(ldf.get());
Modified: branches/4.0/MgDev/Server/src/Services/Tile/TileCacheDefault.cpp
===================================================================
--- branches/4.0/MgDev/Server/src/Services/Tile/TileCacheDefault.cpp 2026-10-25 09:28:58 UTC (rev 10232)
+++ branches/4.0/MgDev/Server/src/Services/Tile/TileCacheDefault.cpp 2026-10-30 10:41:59 UTC (rev 10233)
@@ -918,8 +918,11 @@
{
// get the service from our helper method
Ptr<MgResourceService> resourceService = GetResourceServiceForMapDef(mapDefinition, L"MgTileCacheDefault.GetMapFromDefinition");
+ // GetCurrentUserInfo() returns a counted reference, which has to be held rather than
+ // passed on inline: dropping it leaks the caller thread's user information
+ Ptr<MgUserInformation> userInfo = MgUserInformation::GetCurrentUserInfo();
Ptr<MgSiteConnection> siteConn = new MgSiteConnection();
- siteConn->Open(MgUserInformation::GetCurrentUserInfo());
+ siteConn->Open(userInfo);
map = new MgMap(siteConn);
map->Create(resourceService, mapDefinition, mapString);
cachedMap = new MgMemoryStreamHelper();
Modified: branches/4.0/MgDev/Server/src/UnitTesting/TestRasterStylization.cpp
===================================================================
--- branches/4.0/MgDev/Server/src/UnitTesting/TestRasterStylization.cpp 2026-10-25 09:28:58 UTC (rev 10232)
+++ branches/4.0/MgDev/Server/src/UnitTesting/TestRasterStylization.cpp 2026-10-30 10:41:59 UTC (rev 10233)
@@ -363,7 +363,8 @@
REQUIRE(schemas->GetCount() > 0);
Ptr<MgFeatureSchema> schema = schemas->GetItem(0);
- Ptr<MgClassDefinition> klass = schema->GetClasses()->GetItem(0);
+ Ptr<MgClassDefinitionCollection> classes = schema->GetClasses();
+ Ptr<MgClassDefinition> klass = classes->GetItem(0);
Ptr<MgPropertyDefinitionCollection> properties = klass->GetProperties();
for (INT32 i = 0; i < properties->GetCount() && rasterProperty.empty(); ++i)
@@ -631,10 +632,12 @@
REQUIRE(GetRasterFootprint(svcFeature, fsId, featureName, rasterProperty,
rasterExtent, imageXSize, imageYSize));
- double minX = rasterExtent->GetLowerLeftCoordinate()->GetX();
- double minY = rasterExtent->GetLowerLeftCoordinate()->GetY();
- double maxX = rasterExtent->GetUpperRightCoordinate()->GetX();
- double maxY = rasterExtent->GetUpperRightCoordinate()->GetY();
+ Ptr<MgCoordinate> lowerLeft = rasterExtent->GetLowerLeftCoordinate();
+ Ptr<MgCoordinate> upperRight = rasterExtent->GetUpperRightCoordinate();
+ double minX = lowerLeft->GetX();
+ double minY = lowerLeft->GetY();
+ double maxX = upperRight->GetX();
+ double maxY = upperRight->GetY();
int factor = (std::max)(imageXSize, imageYSize) / REAL_RENDER_MAX_DIM;
if (factor < 1)
@@ -779,10 +782,12 @@
REQUIRE(GetRasterFootprint(svcFeature, fsId, featureName, rasterProperty,
rasterExtent, imageXSize, imageYSize));
- double minX = rasterExtent->GetLowerLeftCoordinate()->GetX();
- double minY = rasterExtent->GetLowerLeftCoordinate()->GetY();
- double maxX = rasterExtent->GetUpperRightCoordinate()->GetX();
- double maxY = rasterExtent->GetUpperRightCoordinate()->GetY();
+ Ptr<MgCoordinate> lowerLeft = rasterExtent->GetLowerLeftCoordinate();
+ Ptr<MgCoordinate> upperRight = rasterExtent->GetUpperRightCoordinate();
+ double minX = lowerLeft->GetX();
+ double minY = lowerLeft->GetY();
+ double maxX = upperRight->GetX();
+ double maxY = upperRight->GetY();
STRING csWkt = GetRasterCoordinateSystem(svcFeature, fsId);
if (csWkt.empty())
Modified: branches/4.0/MgDev/Server/src/UnitTesting/TestTileService.cpp
===================================================================
--- branches/4.0/MgDev/Server/src/UnitTesting/TestTileService.cpp 2026-10-25 09:28:58 UTC (rev 10232)
+++ branches/4.0/MgDev/Server/src/UnitTesting/TestTileService.cpp 2026-10-30 10:41:59 UTC (rev 10233)
@@ -1489,7 +1489,7 @@
// make a runtime map
Ptr<MgResourceIdentifier> tsdres = new MgResourceIdentifier(L"Library://UnitTests/TileSets/XYZ.TileSetDefinition");
- MgMap* map = new MgMap(m_siteConnection);
+ Ptr<MgMap> map = new MgMap(m_siteConnection);
map->Create(m_svcResource, tsdres, L"XYZTileSet");
REQUIRE(0 == map->GetFiniteDisplayScaleCount());
@@ -1517,7 +1517,7 @@
// make a runtime map
Ptr<MgResourceIdentifier> tsdres = new MgResourceIdentifier(L"Library://UnitTests/TileSets/Sheboygan.TileSetDefinition");
- MgMap* map = new MgMap(m_siteConnection);
+ Ptr<MgMap> map = new MgMap(m_siteConnection);
map->Create(tsdres, mapName);
Ptr<MgResourceIdentifier> mdfId = map->GetMapDefinition();
More information about the mapguide-commits
mailing list