Print this page
7928 Add support for SMF_EXIT_TEMP_TRANSIENT

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/svc/startd/method.c
          +++ new/usr/src/cmd/svc/startd/method.c
↓ open down ↓ 14 lines elided ↑ open up ↑
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  24   24   * Copyright 2011 Joyent Inc.
       25 + * Copyright 2017 RackTop Systems.
  25   26   */
  26   27  
  27   28  /*
  28   29   * method.c - method execution functions
  29   30   *
  30   31   * This file contains the routines needed to run a method:  a fork(2)-exec(2)
  31   32   * invocation monitored using either the contract filesystem or waitpid(2).
  32   33   * (Plain fork1(2) support is provided in fork.c.)
  33   34   *
  34   35   * Contract Transfer
↓ open down ↓ 137 lines elided ↑ open up ↑
 172  173  static int
 173  174  method_is_transient(restarter_inst_t *inst, int type)
 174  175  {
 175  176          if (instance_is_transient_style(inst) || type != METHOD_START)
 176  177                  return (1);
 177  178          else
 178  179                  return (0);
 179  180  }
 180  181  
 181  182  /*
      183 + * int method_failed()
      184 + *   Return 1 if the exit_code indicates failure (not all non-zero
      185 + *   exit codes do) otherwise return 0.
      186 + */
      187 +static int
      188 +method_failed(int exit_code)
      189 +{
      190 +        if (exit_code != 0 && exit_code != SMF_EXIT_TEMP_TRANSIENT)
      191 +                return (1);
      192 +        else
      193 +                return (0);
      194 +}
      195 +
      196 +/*
 182  197   * void method_store_contract()
 183  198   *   Store the newly created contract id into local structures and
 184  199   *   the repository.  If the repository connection is broken it is rebound.
 185  200   */
 186  201  static void
 187  202  method_store_contract(restarter_inst_t *inst, int type, ctid_t *cid)
 188  203  {
 189  204          int r;
 190  205          boolean_t primary;
 191  206  
↓ open down ↓ 819 lines elided ↑ open up ↑
1011 1026                                      WEXITSTATUS(ret_status));
1012 1027                                  log_instance(inst, B_TRUE, "Method \"%s\" "
1013 1028                                      "failed with exit status %d.", mname,
1014 1029                                      WEXITSTATUS(ret_status));
1015 1030                          }
1016 1031                          result = EAGAIN;
1017 1032                          goto contract_out;
1018 1033                  }
1019 1034  
1020 1035                  *exit_code = WEXITSTATUS(ret_status);
1021      -                if (*exit_code != 0) {
     1036 +                if (method_failed(*exit_code) != 0) {
1022 1037                          log_error(LOG_WARNING,
1023 1038                              "%s: Method \"%s\" failed with exit status %d.\n",
1024 1039                              inst->ri_i.i_fmri, method, WEXITSTATUS(ret_status));
1025 1040                  }
1026 1041  
     1042 +                if (type == METHOD_STOP &&
     1043 +                    *exit_code == SMF_EXIT_TEMP_TRANSIENT) {
     1044 +                        log_instance(inst, B_TRUE, "Invalid use of "
     1045 +                            "\"$SMF_EXIT_TEMP_TRANSIENT\" in stop method.");
     1046 +                        result = EINVAL;
     1047 +                        goto contract_out;
     1048 +                }
     1049 +
1027 1050                  log_instance(inst, B_TRUE, "Method \"%s\" exited with status "
1028 1051                      "%d.", mname, *exit_code);
1029 1052  
1030      -                if (*exit_code != 0)
     1053 +                if (method_failed(*exit_code) != 0)
1031 1054                          goto contract_out;
1032 1055  
1033 1056                  end_time = time(NULL);
1034 1057  
1035 1058                  /* Give service contract remaining seconds to empty */
1036 1059                  if (timeout != METHOD_TIMEOUT_INFINITE)
1037 1060                          timeout -= (end_time - start_time);
1038 1061          }
1039 1062  
1040 1063  assured_kill:
↓ open down ↓ 121 lines elided ↑ open up ↑
1162 1185  
1163 1186          inst->ri_m_inst = s_inst;
1164 1187          inst->ri_mi_deleted = B_FALSE;
1165 1188  
1166 1189  retry:
1167 1190          if (info->sf_method_type == METHOD_START)
1168 1191                  log_transition(inst, START_REQUESTED);
1169 1192  
1170 1193          r = method_run(&inst, info->sf_method_type, &exit_code);
1171 1194  
1172      -        if (r == 0 && exit_code == 0) {
     1195 +        if (r == 0 && method_failed(exit_code) == 0) {
1173 1196                  /* Success! */
1174 1197                  assert(inst->ri_i.i_next_state != RESTARTER_STATE_NONE);
1175 1198  
1176 1199                  /*
1177 1200                   * When a stop method succeeds, remove the primary contract of
1178 1201                   * the service, unless we're going to offline, in which case
1179 1202                   * retain the contract so we can transfer inherited contracts to
1180 1203                   * the replacement service.
1181 1204                   */
1182 1205  
↓ open down ↓ 84 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX