From 2db6fdb95b018b5dae9c69a6282b00337204de09 Mon Sep 17 00:00:00 2001
From: blaakmeer <sdos@astron.nl>
Date: Thu, 28 Sep 2006 14:43:22 +0000
Subject: [PATCH] BugID: 803 State of the MACScheduler is written to PVSS
 during destruction. A signal handler is installed (late enough to override
 the GCF signal handlers!) that triggers the transition to the finishing
 state. In that state, the property is written and a timer is installed
 because PVSS database writes are asynchronous. When the timer goes off (1
 second) the MACScheduler is closed.

---
 .../MainCU/src/MACScheduler/MACScheduler.cc   | 66 ++++++++++++++++++-
 .../MainCU/src/MACScheduler/MACScheduler.h    |  9 +++
 .../src/MACScheduler/MACSchedulerMain.cc      |  2 +-
 3 files changed, 75 insertions(+), 2 deletions(-)

diff --git a/MAC/APL/MainCU/src/MACScheduler/MACScheduler.cc b/MAC/APL/MainCU/src/MACScheduler/MACScheduler.cc
index 0eb9a1f5721..85bc0b7c16d 100644
--- a/MAC/APL/MainCU/src/MACScheduler/MACScheduler.cc
+++ b/MAC/APL/MainCU/src/MACScheduler/MACScheduler.cc
@@ -34,6 +34,7 @@
 #include <APL/APLCommon/StationInfo.h>
 #include <APL/APLCommon/APLCommonExceptions.h>
 #include <APL/APLCommon/Controller_Protocol.ph>
+#include <signal.h>
 
 #include "MACSchedulerDefines.h"
 #include "MACScheduler.h"
@@ -49,6 +50,9 @@ namespace LOFAR {
 	using namespace APLCommon;
 	using namespace ACC::APS;
 	namespace MainCU {
+
+// static (this) pointer used for signal handling
+static MACScheduler* pMacScheduler = 0;
 	
 //
 // MACScheduler()
@@ -114,6 +118,13 @@ MACScheduler::~MACScheduler()
 	}
 }
 
+void MACScheduler::sigintHandler(/*@unused@*/int signum)
+{
+  LOG_INFO(LOFAR::formatString("SIGINT signal detected (%d)",signum));
+  if(0 != pMacScheduler)
+    pMacScheduler->finish();
+}
+
 
 //
 // handlePropertySetAnswer(answer)
@@ -310,6 +321,12 @@ GCFEvent::TResult MACScheduler::active_state(GCFEvent& event, GCFPortInterface&
 		break;
 
 	case F_ENTRY: {
+  	    // install my own signal handler. GCFTask also installs a handler so we have to install our
+	    // handler later than the GCFTask handler.
+	    pMacScheduler = this;
+		/* install ctrl-c signal handler */
+		(void)signal(SIGINT,MACScheduler::sigintHandler);
+
 		// update PVSS
 		itsPropertySet->setValue(string(PVSSNAME_FSM_STATE),GCFPVString("active"));
 		itsPropertySet->setValue(string(PVSSNAME_FSM_ERROR),GCFPVString(""));
@@ -403,6 +420,53 @@ GCFEvent::TResult MACScheduler::active_state(GCFEvent& event, GCFPortInterface&
 	return (status);
 }
 
+//
+// finishing_state(event, port)
+//
+// Write controller state to PVSS, wait for 1 second (using a timer) to let GCF handle the property change
+// and close the controller
+//
+GCFEvent::TResult MACScheduler::finishing_state(GCFEvent& event, GCFPortInterface& port)
+{
+	LOG_DEBUG_STR ("finishing_state:" << evtstr(event) << "@" << port.getName());
+
+	GCFEvent::TResult status = GCFEvent::HANDLED;
+
+	switch (event.signal) {
+	case F_INIT:
+		break;
+
+	case F_ENTRY: {
+		// update PVSS
+		itsPropertySet->setValue(string(PVSSNAME_FSM_STATE),GCFPVString("finished"));
+		itsPropertySet->setValue(string(PVSSNAME_FSM_ERROR),GCFPVString(""));
+
+		itsTimerPort->setTimer(1L);
+		break;
+	}
+  
+    case F_TIMER:
+      GCFTask::stop();
+      break;
+    
+	default:
+		LOG_DEBUG("finishing_state, default");
+		status = GCFEvent::NOT_HANDLED;
+		break;
+	}    
+	return (status);
+}
+
+//
+// finish
+//
+// Make the transition to the finishing state
+//
+void MACScheduler::finish()
+{
+  TRAN(MACScheduler::finishing_state);
+}
+
 //
 // _doOTDBcheck
 //
@@ -564,7 +628,7 @@ void MACScheduler::_removeActiveObservation(const string& name)
 //
 // _connectedHandler(port)
 //
-void MACScheduler::_connectedHandler(GCFPortInterface& port)
+void MACScheduler::_connectedHandler(GCFPortInterface& /*port*/)
 {
 }
 
diff --git a/MAC/APL/MainCU/src/MACScheduler/MACScheduler.h b/MAC/APL/MainCU/src/MACScheduler/MACScheduler.h
index a8d0a3cb41b..aada16ab35a 100644
--- a/MAC/APL/MainCU/src/MACScheduler/MACScheduler.h
+++ b/MAC/APL/MainCU/src/MACScheduler/MACScheduler.h
@@ -94,6 +94,15 @@ public:
    	GCFEvent::TResult active_state  (GCFEvent& e, 
 									 GCFPortInterface& p);
 
+	// Cleaning up. Write state to PVSS property
+   	GCFEvent::TResult finishing_state(GCFEvent& e, 
+								 	  GCFPortInterface& p);
+
+	// Make the transition to the finishing state
+	void finish();
+
+	static void sigintHandler(int signum);
+
 private:
 	// avoid copying
 	MACScheduler(const MACScheduler&);
diff --git a/MAC/APL/MainCU/src/MACScheduler/MACSchedulerMain.cc b/MAC/APL/MainCU/src/MACScheduler/MACSchedulerMain.cc
index 1f1b70b6d7a..f24973a4776 100644
--- a/MAC/APL/MainCU/src/MACScheduler/MACSchedulerMain.cc
+++ b/MAC/APL/MainCU/src/MACScheduler/MACSchedulerMain.cc
@@ -37,7 +37,7 @@ int main(int argc, char* argv[])
 
 	MACScheduler	ms;
 	ms.start(); // make initial transition
-
+  
 	GCFTask::run();
 
 	return 0;
-- 
GitLab