Print this page
7928 Add support for SMF_EXIT_TEMP_TRANSIENT

@@ -20,10 +20,11 @@
  */
 
 /*
  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2011 Joyent Inc.
+ * Copyright 2017 RackTop Systems.
  */
 
 /*
  * method.c - method execution functions
  *

@@ -177,10 +178,24 @@
         else
                 return (0);
 }
 
 /*
+ * int method_failed()
+ *   Return 1 if the exit_code indicates failure (not all non-zero
+ *   exit codes do) otherwise return 0.
+ */
+static int
+method_failed(int exit_code)
+{
+        if (exit_code != 0 && exit_code != SMF_EXIT_TEMP_TRANSIENT)
+                return (1);
+        else
+                return (0);
+}
+
+/*
  * void method_store_contract()
  *   Store the newly created contract id into local structures and
  *   the repository.  If the repository connection is broken it is rebound.
  */
 static void

@@ -1016,20 +1031,28 @@
                         result = EAGAIN;
                         goto contract_out;
                 }
 
                 *exit_code = WEXITSTATUS(ret_status);
-                if (*exit_code != 0) {
+                if (method_failed(*exit_code) != 0) {
                         log_error(LOG_WARNING,
                             "%s: Method \"%s\" failed with exit status %d.\n",
                             inst->ri_i.i_fmri, method, WEXITSTATUS(ret_status));
                 }
 
+                if (type == METHOD_STOP &&
+                    *exit_code == SMF_EXIT_TEMP_TRANSIENT) {
+                        log_instance(inst, B_TRUE, "Invalid use of "
+                            "\"$SMF_EXIT_TEMP_TRANSIENT\" in stop method.");
+                        result = EINVAL;
+                        goto contract_out;
+                }
+
                 log_instance(inst, B_TRUE, "Method \"%s\" exited with status "
                     "%d.", mname, *exit_code);
 
-                if (*exit_code != 0)
+                if (method_failed(*exit_code) != 0)
                         goto contract_out;
 
                 end_time = time(NULL);
 
                 /* Give service contract remaining seconds to empty */

@@ -1167,11 +1190,11 @@
         if (info->sf_method_type == METHOD_START)
                 log_transition(inst, START_REQUESTED);
 
         r = method_run(&inst, info->sf_method_type, &exit_code);
 
-        if (r == 0 && exit_code == 0) {
+        if (r == 0 && method_failed(exit_code) == 0) {
                 /* Success! */
                 assert(inst->ri_i.i_next_state != RESTARTER_STATE_NONE);
 
                 /*
                  * When a stop method succeeds, remove the primary contract of