diff --git a/src/finiteVolume/cfdTools/general/coupling/externalFileCoupler.C b/src/finiteVolume/cfdTools/general/coupling/externalFileCoupler.C
index 59a0fde68475bdba51e672cf69a5d07839750096..bb17b4cf8a9e5b4eb8f11e0abac6c0e8bdebbe72 100644
--- a/src/finiteVolume/cfdTools/general/coupling/externalFileCoupler.C
+++ b/src/finiteVolume/cfdTools/general/coupling/externalFileCoupler.C
@@ -40,10 +40,11 @@ namespace Foam
 Foam::word Foam::externalFileCoupler::lockName = "OpenFOAM";
 
 
+// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
+
 namespace Foam
 {
 
-// file-scope
 // Read file contents and return a stop control as follows:
 // - contains "done" (should actually be status=done, but we are generous) :
 //   The master (OpenFOAM) has signalled that it is done. Report as <endTime>
@@ -86,6 +87,7 @@ static enum Time::stopAtControls getStopAction(const std::string& filename)
 
 } // End namespace Foam
 
+
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
 Foam::externalFileCoupler::externalFileCoupler()
diff --git a/src/functionObjects/utilities/abort/abort.C b/src/functionObjects/utilities/abort/abort.C
index 02d6a69112da53566204f666eefa5f4d7bfa4102..4f480388a38aed008e7245bd9de1ce8461305666 100644
--- a/src/functionObjects/utilities/abort/abort.C
+++ b/src/functionObjects/utilities/abort/abort.C
@@ -30,6 +30,7 @@ License
 #include "OSspecific.H"
 #include "PstreamReduceOps.H"
 #include "addToRunTimeSelectionTable.H"
+#include <fstream>
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
@@ -51,15 +52,54 @@ namespace functionObjects
 
 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
 
-// file-scope
-// Long description for the action name
 namespace Foam
 {
+
+// Read file contents and return a stop control as follows:
+//
+// - action=writeNow, action=nextWrite action=noWriteNow :
+//   The signalled action. Report as corresponding <action>.
+//
+// Anything else (empty file, no action=, etc) is reported as <unknown>.
+//
+static enum Time::stopAtControls getStopAction(const std::string& filename)
+{
+    // Slurp entire input file (must exist) as a single string
+    std::string fileContent;
+
+    std::ifstream is(filename);
+    std::getline(is, fileContent, '\0');
+
+    const auto equals = fileContent.find('=');
+
+    if (equals != std::string::npos)
+    {
+        const word actionName(word::validate(fileContent.substr(equals+1)));
+
+        return
+            Time::stopAtControlNames
+            (
+                actionName,
+                Time::stopAtControls::saUnknown
+            );
+    }
+
+    return Time::stopAtControls::saUnknown;
+}
+
+
+// Long description for the action name
 static std::string longDescription(const Time::stopAtControls ctrl)
 {
     switch (ctrl)
     {
-        case Foam::Time::saNoWriteNow :
+        case Time::saEndTime :
+        {
+            return "continue simulation to the endTime";
+            break;
+        }
+
+        case Time::saNoWriteNow :
         {
             return "stop without writing data";
             break;
@@ -80,12 +120,13 @@ static std::string longDescription(const Time::stopAtControls ctrl)
         default:
         {
             // Invalid choices already filtered out by Enum
-            return "abort";
+            return "unknown action";
             break;
         }
     }
 }
-}
+
+}  // End namespace Foam
 
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
@@ -99,18 +140,16 @@ Foam::functionObjects::abort::abort
 :
     functionObject(name),
     time_(runTime),
-    abortFile_(time_.globalPath()/name),
-    action_(Time::stopAtControls::saNextWrite),
+    file_(),
+    defaultAction_(Time::stopAtControls::saUnknown),
     triggered_(false)
 {
-    abortFile_.clean();
-
     read(dict);
 
     // Cleanup old files from previous runs
     if (Pstream::master())
     {
-        Foam::rm(abortFile_);
+        Foam::rm(file_);
     }
 }
 
@@ -121,36 +160,38 @@ bool Foam::functionObjects::abort::read(const dictionary& dict)
 {
     functionObject::read(dict);
 
-    if (dict.readIfPresent("file", abortFile_))
+    file_.clear();
+
+    if (dict.readIfPresent("file", file_))
     {
-        abortFile_.expand();
+        file_.expand();
 
-        if (!abortFile_.isAbsolute())
+        if (!file_.isAbsolute() && file_.size())
         {
-            abortFile_ = time_.globalPath()/abortFile_;
-            abortFile_.clean();
-         }
+            file_ = time_.globalPath()/file_;
+            file_.clean();
+        }
     }
 
-    const auto oldAction = action_;
+    // Ensure we always have a reasonable default file
+    if (file_.empty())
+    {
+        file_ = time_.globalPath()/name();
+        file_.clean();
+    }
 
-    action_ = Time::stopAtControlNames.lookupOrDefault
+    triggered_ = false;
+
+    defaultAction_ = Time::stopAtControlNames.lookupOrDefault
     (
         "action",
         dict,
         Time::stopAtControls::saNextWrite
     );
 
-    // User can change action and re-trigger the abort.
-    // eg, they had nextWrite, but actually wanted writeNow.
-    if (oldAction != action_)
-    {
-        triggered_ = false;
-    }
-
     Info<< type() << " activated ("
-        << longDescription(action_).c_str() <<")" << nl
-        << "    File: " << abortFile_ << endl;
+        << longDescription(defaultAction_).c_str() <<")" << nl
+        << "    File: " << file_ << endl;
 
     return true;
 }
@@ -161,22 +202,35 @@ bool Foam::functionObjects::abort::execute()
     // If it has been triggered (eg, nextWrite) don't need to check it again
     if (!triggered_)
     {
-        bool hasAbort = (Pstream::master() && isFile(abortFile_));
-        Pstream::scatter(hasAbort);
+        auto action = Time::stopAtControls::saUnknown;
 
-        if (hasAbort)
+        if (Pstream::master() && Foam::isFile(file_))
         {
-            triggered_ = time_.stopAt(action_);
+            action = getStopAction(file_);
 
-            if (triggered_)
+            if (Time::stopAtControls::saUnknown == action)
             {
-                Info<< "USER REQUESTED ABORT (timeIndex="
-                    << time_.timeIndex()
-                    << "): " << longDescription(action_).c_str()
-                    << endl;
+                // An unknown action means an empty file or bad content.
+                // Treat as a request for the default action.
+
+                action = defaultAction_;
             }
+        }
 
-            Pstream::scatter(triggered_);
+        // Send to slaves. Also acts as an MPI barrier
+        label intAction(action);
+        Pstream::scatter(intAction);
+
+        action = Time::stopAtControls(intAction);
+
+        // Call stopAt() on all processes
+        triggered_ = time_.stopAt(action);
+
+        if (triggered_)
+        {
+            Info<< "USER REQUESTED ABORT (timeIndex="
+                << time_.timeIndex() << "): "
+                << longDescription(action).c_str() << endl;
         }
     }
 
@@ -192,10 +246,10 @@ bool Foam::functionObjects::abort::write()
 
 bool Foam::functionObjects::abort::end()
 {
-    // Cleanup ABORT file
+    // Cleanup trigger file
     if (Pstream::master())
     {
-        Foam::rm(abortFile_);
+        Foam::rm(file_);
     }
 
     return true;
diff --git a/src/functionObjects/utilities/abort/abort.H b/src/functionObjects/utilities/abort/abort.H
index c2c86aa564084bb6520c7ba71d0c4cafe6b57e08..86a3958649d41cbd7c4af778a67cf67594a90410 100644
--- a/src/functionObjects/utilities/abort/abort.H
+++ b/src/functionObjects/utilities/abort/abort.H
@@ -28,24 +28,56 @@ Group
     grpUtilitiesFunctionObjects
 
 Description
-    Watches for presence of the named file in the case directory
-    and aborts the calculation if it is present.
+    Watches for presence of the named trigger file in the case directory
+    and signals a simulation stop (or other) event if found.
 
-    The presence of the abort file is only checked on the master process.
+    The presence of the trigger file is only checked on the master process.
 
     Currently the following action types are supported:
     - noWriteNow
     - writeNow
     - nextWrite
 
+    Example of function object specification:
+    \verbatim
+    abort
+    {
+        type    abort;
+        libs    ("libutilityFunctionObjects.so");
+
+        file    "<case>/GOODBYE";
+        action  writeNow
+    }
+    \endverbatim
+
     \heading Function object usage
     \table
-        Property  | Description         | Required  | Default value
-        type      | Type name: abort    | yes       |
-        file      | The abort filename  | no        | \<case\>/name
-        action    | Abort action        | no        | nextWrite
+        Property  | Description                         | Required | Default
+        type      | Type name: abort                    | yes |
+        file      | The trigger filename                | no  | \<case\>/name
+        action    | The default action to trigger       | no  | nextWrite
     \endtable
 
+    When the trigger file is found, it is checked for the following
+    content which corresponds to actions.
+
+    - \c action=noWriteNow
+       : triggers Foam::Time::saNoWriteNow (stop without writing data)
+    - \c action=writeNow
+       : triggers Foam::Time::saWriteNow (stop and write data)
+    - \c action=nextWrite
+       : triggers Foam::Time::saNextWrite (stop after next normal data write)
+    - \c action=endTime
+       : triggers Foam::Time::saEndTime (continue simulation to the end)
+    - Anything else (empty file, no action=, ...)
+       : use the default action
+    .
+
+Note
+    The trigger file is considered "sticky". This means that once detected
+    and processed, the trigger is duly noted and the file will not be
+    rechecked. It is not possible or desirable to 'untrigger' an action.
+
 SourceFiles
     abort.C
 
@@ -72,18 +104,18 @@ class abort
 :
     public functionObject
 {
-    // Private data
+    // Private Data
 
         //- Reference to the Time
         const Time& time_;
 
-        //- The fully-qualified name of the abort file
-        fileName abortFile_;
+        //- The fully-qualified name of the trigger file
+        fileName file_;
 
-        //- The type of action
-        Time::stopAtControls action_;
+        //- The default action (defined in dictionary)
+        Time::stopAtControls defaultAction_;
 
-        //- Only trigger action once
+        //- Only trigger the action once
         bool triggered_;
 
 
@@ -122,13 +154,13 @@ public:
         //- Read the dictionary settings
         virtual bool read(const dictionary& dict);
 
-        //- Check existence of abort file and take action
+        //- Check existence of the file and take action
         virtual bool execute();
 
         //- No-op
         virtual bool write();
 
-        //- Remove abort file after the final time-loop.
+        //- Remove the trigger file after the final time-loop.
         virtual bool end();
 };
 
diff --git a/tutorials/compressible/rhoSimpleFoam/squareBendLiq/system/abort b/tutorials/compressible/rhoSimpleFoam/squareBendLiq/system/abort
new file mode 100644
index 0000000000000000000000000000000000000000..7001b883ef76b737ec0eac58c73ed64f484b8973
--- /dev/null
+++ b/tutorials/compressible/rhoSimpleFoam/squareBendLiq/system/abort
@@ -0,0 +1,17 @@
+// OpenFOAM dictionary -*- C++ -*-
+
+abort
+{
+    type    abort;
+    libs    ("libutilityFunctionObjects.so");
+
+    file    "<case>/ABORT";   // Instead of default name
+
+    // action  writeNow;         // If we want to see immediate results
+
+    // Or use default (nextWrite) and force with
+    // "action=writeNow" in the trigger file
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/compressible/rhoSimpleFoam/squareBendLiq/system/controlDict b/tutorials/compressible/rhoSimpleFoam/squareBendLiq/system/controlDict
index 1ed4419d731c8ffa57b5dde169e074f121b5780e..fcef92c66784bf02d937b0200f8a9aca7e79bdde 100644
--- a/tutorials/compressible/rhoSimpleFoam/squareBendLiq/system/controlDict
+++ b/tutorials/compressible/rhoSimpleFoam/squareBendLiq/system/controlDict
@@ -47,5 +47,9 @@ graphFormat     raw;
 
 runTimeModifiable true;
 
+functions
+{
+    #include "abort"
+}
 
 // ************************************************************************* //