From 5db3100c443db6fc5f9abf0a2f44579d6f5ce4a3 Mon Sep 17 00:00:00 2001
From: Martyn Gigg <martyn.gigg@stfc.ac.uk>
Date: Mon, 10 May 2010 11:10:12 +0000
Subject: [PATCH] Fix an issue with symbol visibility on machines using ld
 (linux/mac). Dlopen was not able to find some symbols defined but not
 referenced in the core Mantid libraries due to the default behaviour for
 dynamic executables being to only export the symbols referenced at link time.
 This was causing issues with Group/UnGroup notifications. Re #1224

---
 .../API/inc/MantidAPI/AnalysisDataService.h   |   8 +-
 .../Mantid/Algorithms/src/GroupWorkspaces.cpp |   2 +-
 .../Algorithms/src/UnGroupWorkspaces.cpp      | 102 +++++++-----------
 Code/Mantid/Main/SConscript                   |  26 ++---
 Code/qtiplot/qtiplot/qtiplot.pro              |   5 +
 .../qtiplot/qtiplot/src/Mantid/MantidDock.cpp |  19 +---
 Code/qtiplot/qtiplot/src/Mantid/MantidUI.cpp  |  32 +++---
 Code/qtiplot/qtiplot/src/Mantid/MantidUI.h    |  12 +--
 8 files changed, 86 insertions(+), 120 deletions(-)

diff --git a/Code/Mantid/API/inc/MantidAPI/AnalysisDataService.h b/Code/Mantid/API/inc/MantidAPI/AnalysisDataService.h
index 425878167f5..7ba0ecb36b4 100644
--- a/Code/Mantid/API/inc/MantidAPI/AnalysisDataService.h
+++ b/Code/Mantid/API/inc/MantidAPI/AnalysisDataService.h
@@ -104,11 +104,11 @@ typedef const Poco::AutoPtr<Mantid::Kernel::DataService<Mantid::API::Workspace>:
 typedef Mantid::Kernel::DataService<Mantid::API::Workspace>::RenameNotification WorkspaceRenameNotification;
 typedef const Poco::AutoPtr<Mantid::Kernel::DataService<Mantid::API::Workspace>::RenameNotification>& WorkspaceRenameNotification_ptr;
 
-typedef Mantid::Kernel::DataService<Mantid::API::Workspace>::GroupWorkspacesNotification GroupWorkspacesNotification;
-typedef const Poco::AutoPtr<Mantid::Kernel::DataService<Mantid::API::Workspace>::GroupWorkspacesNotification>& GroupWorkspacesNotification_ptr;
+typedef Mantid::Kernel::DataService<Mantid::API::Workspace>::GroupWorkspacesNotification WorkspacesGroupedNotification;
+typedef const Poco::AutoPtr<Mantid::Kernel::DataService<Mantid::API::Workspace>::GroupWorkspacesNotification>& WorkspacesGroupedNotification_ptr;
 
-typedef Mantid::Kernel::DataService<Mantid::API::Workspace>::UnGroupWorkspaceNotification UnGroupWorkspaceNotification;
-typedef const Poco::AutoPtr<Mantid::Kernel::DataService<Mantid::API::Workspace>::UnGroupWorkspaceNotification>& UnGroupWorkspaceNotification_ptr;
+typedef Mantid::Kernel::DataService<Mantid::API::Workspace>::UnGroupWorkspaceNotification WorkspaceUnGroupedNotification;
+typedef const Poco::AutoPtr<Mantid::Kernel::DataService<Mantid::API::Workspace>::UnGroupWorkspaceNotification>& WorkspaceUnGroupedNotification_ptr;
 
 
 } // Namespace API
diff --git a/Code/Mantid/Algorithms/src/GroupWorkspaces.cpp b/Code/Mantid/Algorithms/src/GroupWorkspaces.cpp
index 33ca9940560..bc874569520 100644
--- a/Code/Mantid/Algorithms/src/GroupWorkspaces.cpp
+++ b/Code/Mantid/Algorithms/src/GroupWorkspaces.cpp
@@ -88,7 +88,7 @@ namespace Mantid
 
       // Notify listeners that a new grop has been created
       Mantid::API::AnalysisDataService::Instance().notificationCenter.postNotification(
-        new Kernel::DataService<Workspace>::GroupWorkspacesNotification(inputworkspaces));	
+        new WorkspacesGroupedNotification(inputworkspaces));	
 
     }
 
diff --git a/Code/Mantid/Algorithms/src/UnGroupWorkspaces.cpp b/Code/Mantid/Algorithms/src/UnGroupWorkspaces.cpp
index ba9f26a910c..0afbc924ab2 100644
--- a/Code/Mantid/Algorithms/src/UnGroupWorkspaces.cpp
+++ b/Code/Mantid/Algorithms/src/UnGroupWorkspaces.cpp
@@ -5,67 +5,47 @@
 
 namespace Mantid
 {
-	namespace Algorithms
-	{
-		DECLARE_ALGORITHM(UnGroupWorkspace)
-		using namespace Kernel;
-		using namespace API;
-		///Initialisation method
-		void UnGroupWorkspace::init()
-		{
-			declareProperty("InputWorkspace","","Name of the input workspace to ungroup" );
-
-		}
-		/** Executes the algorithm
-		*  @throw std::runtime_error If the selected workspace is not a group workspace
-		*/
-		void UnGroupWorkspace::exec()
-		{
-			try
-			{				
-				std::string inputws=getProperty("InputWorkspace");
-				// send this notification to mantidplot to add the group member workspaces to mantid tree
-				// this is bcoz the ADS remove will delete the group workspace and its member workspaces from mantid tree
-				//send this before ADS remove to mantidplot
-				Mantid::API::AnalysisDataService::Instance().notificationCenter.postNotification(
-					new Kernel::DataService<Workspace>::UnGroupWorkspaceNotification(inputws));	
-
-				
-				Workspace_sptr wsSptr=API::AnalysisDataService::Instance().retrieve(inputws);
-				if(wsSptr)
-				{
-					//if this is group workspace
-					WorkspaceGroup_sptr wsGrpSptr=boost::dynamic_pointer_cast<WorkspaceGroup>(wsSptr);
-					if(wsGrpSptr)
-					{	//delete the group workspace
-						API::AnalysisDataService::Instance().remove(inputws);
-
-					}
-					else
-					{
-						throw std::runtime_error("Selected Workspace is not a Groupworkspace to Ungroup ");
-					}
-				}
-
-			}
-			catch(std::invalid_argument &)
-			{
-				throw;
-			}
-			catch(Mantid::Kernel::Exception::NotFoundError& )
-			{//if not a valid object in analysis data service
-				throw ;
-			}
-			catch(std::runtime_error&)
-			{
-				throw;
-			}
-			catch(std::exception& )
-			{
-				throw;
-			}
-
-		}
+  namespace Algorithms
+  {
+    
+    DECLARE_ALGORITHM(UnGroupWorkspace)
+    
+    using namespace Kernel;
+    using namespace API;
+    
+    ///Initialisation method
+    void UnGroupWorkspace::init()
+    {
+      declareProperty("InputWorkspace","","Name of the input workspace to ungroup" );
 
+    }
+    
+    /** Executes the algorithm
+     *  @throw std::runtime_error If the selected workspace is not a group workspace
+     */
+    void UnGroupWorkspace::exec()
+    {
+      std::string inputws=getProperty("InputWorkspace");
+      // send this notification to mantidplot to add the group member workspaces to mantid tree
+      // this is bcoz the ADS remove will delete the group workspace and its member workspaces from mantid tree
+      //send this before ADS remove to mantidplot
+      Mantid::API::AnalysisDataService::Instance().notificationCenter.postNotification(new Mantid::API::WorkspaceUnGroupedNotification(inputws));
+      
+      Workspace_sptr wsSptr=API::AnalysisDataService::Instance().retrieve(inputws);
+      if(wsSptr)
+      {
+	//if this is group workspace
+	WorkspaceGroup_sptr wsGrpSptr=boost::dynamic_pointer_cast<WorkspaceGroup>(wsSptr);
+	if(wsGrpSptr)
+	{
+	  API::AnalysisDataService::Instance().remove(inputws);
 	}
+	else
+	{
+	  throw std::runtime_error("Selected Workspace is not a Groupworkspace to Ungroup ");
+	}
+      }
+    }
+
+  }
 }
diff --git a/Code/Mantid/Main/SConscript b/Code/Mantid/Main/SConscript
index 635c883b4b7..d4d361f1599 100644
--- a/Code/Mantid/Main/SConscript
+++ b/Code/Mantid/Main/SConscript
@@ -9,32 +9,28 @@ from socket import gethostname
 
 import MantidBuild
 
-
 Import('env')
 myenv = env.Clone()
 myenv.Append(CPPDEFINES=[('IN_MANTID_MAIN',1)])
 #shared_list = env['SHARED_LIST']
 #static_list = env['STATIC_LIST']
-libList = env['MYLIBLIST']
-libDirList = env['MYLIBDIRLIST']
+libList = myenv['MYLIBLIST']
+libDirList = myenv['MYLIBDIRLIST']
+
+if os.name == 'posix':
+    # MG: By default, ld populates the symbol table with only those referenced within the linked libraries.
+    # Given that we use dlopen we may not necessarily reference all symbols at link time so we need to 
+    # ensure that the symbol table is populated with all symbols defined within the linked libraries.
+    myenv.Append(LINKFLAGS=['-Wl,--export-dynamic'])
 
 
 #GET LIST OF CPPS
 codeFolder = os.path.abspath('.')
 listCpps = MantidBuild.getCPPFiles(codeFolder)
 
-myenv_dynamic = myenv.Clone()
-myenv_dynamic.Append(LIBS=libList)
-myenv_dynamic.Append(LIBPATH=libDirList)
-myenv_dynamic.Append(LIBPATH='#Bin/Shared')
-shared = myenv_dynamic.Program('main',listCpps, PDB='main.pdb')
-
-#myenv_static = myenv.Clone()
-#myenv_static.Append(LIBS=libList)
-#myenv_static.Append(LIBPATH=libDirList)
-#myenv_static.Append(LIBPATH='#Bin/Static')
-#myenv_static.Append(LINKFLAGS=['-static'])
-#myenv_static.Program('main_static', listCpps, PDB='main_static.pdb')
+myenv.Append(LIBS=libList)
+myenv.Append(LIBPATH=libDirList)
+shared = myenv.Program('main',listCpps, PDB='main.pdb')
 
 retval = { 'shared': shared }
 Return('retval')
diff --git a/Code/qtiplot/qtiplot/qtiplot.pro b/Code/qtiplot/qtiplot/qtiplot.pro
index defa53947ae..c6f24b761af 100644
--- a/Code/qtiplot/qtiplot/qtiplot.pro
+++ b/Code/qtiplot/qtiplot/qtiplot.pro
@@ -100,6 +100,11 @@ unix:!macx {
 
 # dynamically link against dependencies if they are installed system-wide
 unix {
+  # MG: By default, ld populates the symbol table with only those referenced within the linked libraries.
+  # Given that Mantid uses dlopen it may not necessarily reference all symbols at link time. We therefore need to 
+  # ensure that the symbol table is populated with all symbols defined within the linked libraries.
+  QMAKE_LFLAGS += -Wl,--export-dynamic
+
   LIBS         += -lqscintilla2
   LIBS         += -lmuparser
 
diff --git a/Code/qtiplot/qtiplot/src/Mantid/MantidDock.cpp b/Code/qtiplot/qtiplot/src/Mantid/MantidDock.cpp
index 2f6ad309d8e..fc34bb713f3 100644
--- a/Code/qtiplot/qtiplot/src/Mantid/MantidDock.cpp
+++ b/Code/qtiplot/qtiplot/src/Mantid/MantidDock.cpp
@@ -83,6 +83,8 @@ MantidDockWidget::MantidDockWidget(MantidUI *mui, ApplicationWindow *parent) :
           this, SLOT(updateWorkspaceEntry(const QString &, Mantid::API::Workspace_sptr)));
   connect(m_mantidUI, SIGNAL(workspace_replaced(const QString &, Mantid::API::Workspace_sptr)),
           this, SLOT(updateWorkspaceEntry(const QString &, Mantid::API::Workspace_sptr)));
+  connect(m_mantidUI, SIGNAL(workspace_ungrouped(const QString &)),
+          this, SLOT(workspaceGroupRemoved(const QString &)));
   connect(m_mantidUI, SIGNAL(workspace_removed(const QString &)),
           this, SLOT(removeWorkspaceEntry(const QString &)));
   connect(m_mantidUI, SIGNAL(workspaces_cleared()), m_tree, SLOT(clear()));
@@ -483,8 +485,6 @@ bool MantidDockWidget::isItWorkspaceGroupParentItem(Mantid::API::Workspace_sptr
 
 void MantidDockWidget::removeWorkspaceEntry(const QString & ws_name)
 {
-  // Check if we need to unroll a workspace group before removing it
-  workspaceGroupRemoved(ws_name);
 
   //This will only ever be of size zero or one
   QList<QTreeWidgetItem *> name_matches = m_tree->findItems(ws_name,Qt::MatchFixedString);
@@ -531,21 +531,6 @@ void MantidDockWidget::removeWorkspaceEntry(const QString & ws_name)
  */
 void MantidDockWidget::workspaceGroupRemoved(const QString& wsGroupName)
 {
-  Workspace_sptr workspace;
-  try
-  {
-    workspace = Mantid::API::AnalysisDataService::Instance().retrieve(wsGroupName.toStdString());
-  }
-  catch(Mantid::Kernel::Exception::NotFoundError&)
-  {
-    return;
-  }
-  
-  if( !boost::dynamic_pointer_cast<Mantid::API::WorkspaceGroup_sptr>(workspace) ) 
-  {
-    return;
-  }
-
   QList<QTreeWidgetItem*> match_items=m_tree->findItems(wsGroupName,Qt::MatchFixedString);
   if(match_items.isEmpty())
   {
diff --git a/Code/qtiplot/qtiplot/src/Mantid/MantidUI.cpp b/Code/qtiplot/qtiplot/src/Mantid/MantidUI.cpp
index ce1da08c25d..9fabd91c993 100644
--- a/Code/qtiplot/qtiplot/src/Mantid/MantidUI.cpp
+++ b/Code/qtiplot/qtiplot/src/Mantid/MantidUI.cpp
@@ -111,10 +111,9 @@ m_appWindow(aw)
     Mantid::API::AnalysisDataService::Instance().notificationCenter.addObserver(m_replaceObserver);
     Mantid::API::AnalysisDataService::Instance().notificationCenter.addObserver(m_deleteObserver);
     Mantid::API::AnalysisDataService::Instance().notificationCenter.addObserver(m_clearADSObserver);
-	Mantid::API::AnalysisDataService::Instance().notificationCenter.addObserver(m_renameObserver);
-	Mantid::API::AnalysisDataService::Instance().notificationCenter.addObserver(m_groupworkspacesObserver);
-	Mantid::API::AnalysisDataService::Instance().notificationCenter.addObserver(m_ungroupworkspaceObserver);
-	
+    Mantid::API::AnalysisDataService::Instance().notificationCenter.addObserver(m_renameObserver);
+    Mantid::API::AnalysisDataService::Instance().notificationCenter.addObserver(m_groupworkspacesObserver);
+    Mantid::API::AnalysisDataService::Instance().notificationCenter.addObserver(m_ungroupworkspaceObserver);
 
 
     mantidMenu = new QMenu(m_appWindow);
@@ -199,12 +198,13 @@ void MantidUI::shutdown()
 MantidUI::~MantidUI()
 {
   if( m_algMonitor ) delete m_algMonitor;
+  Mantid::API::AnalysisDataService::Instance().notificationCenter.removeObserver(m_groupworkspacesObserver);
+  Mantid::API::AnalysisDataService::Instance().notificationCenter.removeObserver(m_ungroupworkspaceObserver);
   Mantid::API::AnalysisDataService::Instance().notificationCenter.removeObserver(m_addObserver);
   Mantid::API::AnalysisDataService::Instance().notificationCenter.removeObserver(m_replaceObserver);
   Mantid::API::AnalysisDataService::Instance().notificationCenter.removeObserver(m_deleteObserver);
   Mantid::API::AnalysisDataService::Instance().notificationCenter.removeObserver(m_clearADSObserver);
   Mantid::API::AnalysisDataService::Instance().notificationCenter.removeObserver(m_algUpdatesObserver);
-
 }
 
 void MantidUI::saveSettings() const
@@ -1201,20 +1201,20 @@ void MantidUI::handleRenameWorkspace(WorkspaceRenameNotification_ptr pNf)
 {
   emit workspace_renamed(QString::fromStdString(pNf->object_name()), QString::fromStdString(pNf->new_objectname()));
 }
-void MantidUI::handleGroupWorkspaces(GroupWorkspacesNotification_ptr pNf)
+void MantidUI::handleGroupWorkspaces(Mantid::API::WorkspacesGroupedNotification_ptr pNf)
 {
-	const std::vector<std::string> wsvec=pNf->inputworkspacenames();
-	QStringList wsList;
-	std::vector<std::string>::const_iterator citr;
-	for(citr=wsvec.begin();citr!=wsvec.end();++citr)
-	{
-		wsList.append(QString::fromStdString(*citr));
-	}
-	emit workspaces_grouped(wsList);
+  const std::vector<std::string> wsvec=pNf->inputworkspacenames();
+  QStringList wsList;
+  std::vector<std::string>::const_iterator citr;
+  for(citr=wsvec.begin();citr!=wsvec.end();++citr)
+    {
+      wsList.append(QString::fromStdString(*citr));
+    }
+  emit workspaces_grouped(wsList);
 }
-void MantidUI::handleUnGroupWorkspace(UnGroupWorkspaceNotification_ptr pNf)
+void MantidUI::handleUnGroupWorkspace(Mantid::API::WorkspaceUnGroupedNotification_ptr pNf)
 {
-	emit workspace_ungrouped(QString::fromStdString(pNf->object_name()));
+  emit workspace_ungrouped(QString::fromStdString(pNf->object_name()));
 }
 
 void MantidUI::logMessage(const Poco::Message& msg)
diff --git a/Code/qtiplot/qtiplot/src/Mantid/MantidUI.h b/Code/qtiplot/qtiplot/src/Mantid/MantidUI.h
index 886106484d1..e45d22e3c26 100644
--- a/Code/qtiplot/qtiplot/src/Mantid/MantidUI.h
+++ b/Code/qtiplot/qtiplot/src/Mantid/MantidUI.h
@@ -402,13 +402,13 @@ private:
    void handleRenameWorkspace(Mantid::API::WorkspaceRenameNotification_ptr pNf);
     Poco::NObserver<MantidUI, Mantid::API::WorkspaceRenameNotification> m_renameObserver;
 
-	 //handles notification send by Groupworkspaces algorithm 
-	void handleGroupWorkspaces(Mantid::API::GroupWorkspacesNotification_ptr pNf);
-	Poco::NObserver<MantidUI, Mantid::API::GroupWorkspacesNotification> m_groupworkspacesObserver;
+  //handles notification send by Groupworkspaces algorithm 
+  void handleGroupWorkspaces(Mantid::API::WorkspacesGroupedNotification_ptr pNf);
+  Poco::NObserver<MantidUI, Mantid::API::WorkspacesGroupedNotification> m_groupworkspacesObserver;
 
-	 //handles notification send by UnGroupworkspaces algorithm 
-	void handleUnGroupWorkspace(Mantid::API::UnGroupWorkspaceNotification_ptr pNf);
-	Poco::NObserver<MantidUI, Mantid::API::UnGroupWorkspaceNotification> m_ungroupworkspaceObserver;
+  //handles notification send by UnGroupworkspaces algorithm 
+  void handleUnGroupWorkspace(Mantid::API::WorkspaceUnGroupedNotification_ptr pNf);
+  Poco::NObserver<MantidUI, Mantid::API::WorkspaceUnGroupedNotification> m_ungroupworkspaceObserver;
 
  
 	//#678
-- 
GitLab