From 5729c111b3b7380125338a3b4971514d8308b18c Mon Sep 17 00:00:00 2001
From: Elias Pipping <elias.pipping@fu-berlin.de>
Date: Mon, 30 May 2016 00:55:44 +0200
Subject: [PATCH] [Extend]  Handle SIGINT, SIGTERM, and SIGXCPU

If either signal is detected, we try to terminate gracefully. If we're
given enough time before a nastier signal like SIGKILL is sent, we'll
then be able to finish computing and writing out the current timestep.

If we do not take such precautions, chances are the HDF5 output will be
corrupted.
---
 src/one-body-problem.cc | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/src/one-body-problem.cc b/src/one-body-problem.cc
index ef5b22c7..14139f80 100644
--- a/src/one-body-problem.cc
+++ b/src/one-body-problem.cc
@@ -6,7 +6,9 @@
 #undef HAVE_IPOPT
 #endif
 
+#include <atomic>
 #include <cmath>
+#include <csignal>
 #include <exception>
 #include <fstream>
 #include <iostream>
@@ -71,6 +73,9 @@ Dune::ParameterTree getParameters(int argc, char *argv[]) {
   return parset;
 }
 
+static std::atomic<bool> terminationRequested(false);
+void handleSignal(int signum) { terminationRequested = true; }
+
 int main(int argc, char *argv[]) {
   try {
     Dune::MPIHelper::instance(argc, argv);
@@ -268,6 +273,10 @@ int main(int argc, char *argv[]) {
       return stateEnergyNorm.diff(fineAlpha, coarseAlpha) > refinementTolerance;
     };
 
+    std::signal(SIGXCPU, handleSignal);
+    std::signal(SIGINT, handleSignal);
+    std::signal(SIGTERM, handleSignal);
+
     AdaptiveTimeStepper<NonlinearFactory, MyUpdater,
                         EnergyNorm<ScalarMatrix, ScalarVector>>
         adaptiveTimeStepper(factory, parset, myGlobalFriction, current,
@@ -286,6 +295,11 @@ int main(int argc, char *argv[]) {
       current.state_->extractAlpha(programState.alpha);
 
       report();
+
+      if (terminationRequested) {
+        std::cerr << "Terminating prematurely" << std::endl;
+        break;
+      }
     }
   } catch (Dune::Exception &e) {
     Dune::derr << "Dune reported error: " << e << std::endl;
-- 
GitLab