usr/src/cmd/svc/startd/method.c
author eschrock
Fri, 26 Oct 2007 13:47:19 -0700
changeset 5345 44060de1d838
parent 5238 37127716670e
child 6073 47f6aa7a8077
permissions -rw-r--r--
PSARC 2007/606 nvlist extensions 6608068 typo in ipmi_sdr_refresh() can cause segfault on allocation failure 6608069 libipmi should have support for user management 6608070 nvlist_lookup_nvpair() would be useful 6608094 nvlist_exists() would be useful 6608096 zprop_parse_value() should accept boolean values for boolean types 6608098 startd's fsminimal filesystem checks could be a little more explicit
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     1
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     2
 * CDDL HEADER START
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     3
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     4
 * The contents of this file are subject to the terms of the
1712
c5243b0fd703 6266365 svc.startd tried to use deadbeef
rm88369
parents: 119
diff changeset
     5
 * Common Development and Distribution License (the "License").
c5243b0fd703 6266365 svc.startd tried to use deadbeef
rm88369
parents: 119
diff changeset
     6
 * You may not use this file except in compliance with the License.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     7
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     8
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     9
 * or http://www.opensolaris.org/os/licensing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    10
 * See the License for the specific language governing permissions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    11
 * and limitations under the License.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    12
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    13
 * When distributing Covered Code, include this CDDL HEADER in each
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    14
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    15
 * If applicable, add the following below this CDDL HEADER, with the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    16
 * fields enclosed by brackets "[]" replaced with your own identifying
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    17
 * information: Portions Copyright [yyyy] [name of copyright owner]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    18
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    19
 * CDDL HEADER END
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    20
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    21
/*
4244
77e7b46e3d5e 6243574 Services can be shown online with empty contracts
jeanm
parents: 3179
diff changeset
    22
 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    23
 * Use is subject to license terms.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    24
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    25
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    26
#pragma ident	"%Z%%M%	%I%	%E% SMI"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    27
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    28
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    29
 * method.c - method execution functions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    30
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    31
 * This file contains the routines needed to run a method:  a fork(2)-exec(2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    32
 * invocation monitored using either the contract filesystem or waitpid(2).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    33
 * (Plain fork1(2) support is provided in fork.c.)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    34
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    35
 * Contract Transfer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    36
 *   When we restart a service, we want to transfer any contracts that the old
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    37
 *   service's contract inherited.  This means that (a) we must not abandon the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    38
 *   old contract when the service dies and (b) we must write the id of the old
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    39
 *   contract into the terms of the new contract.  There should be limits to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    40
 *   (a), though, since we don't want to keep the contract around forever.  To
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    41
 *   this end we'll say that services in the offline state may have a contract
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    42
 *   to be transfered and services in the disabled or maintenance states cannot.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    43
 *   This means that when a service transitions from online (or degraded) to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    44
 *   offline, the contract should be preserved, and when the service transitions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    45
 *   from offline to online (i.e., the start method), we'll transfer inherited
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    46
 *   contracts.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    47
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    48
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    49
#include <sys/contract/process.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    50
#include <sys/ctfs.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    51
#include <sys/stat.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    52
#include <sys/time.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    53
#include <sys/types.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    54
#include <sys/uio.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    55
#include <sys/wait.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    56
#include <alloca.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    57
#include <assert.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    58
#include <errno.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    59
#include <fcntl.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    60
#include <libcontract.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    61
#include <libcontract_priv.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    62
#include <libgen.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    63
#include <librestart.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    64
#include <libscf.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    65
#include <limits.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    66
#include <port.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    67
#include <sac.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    68
#include <signal.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    69
#include <stdlib.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    70
#include <string.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    71
#include <strings.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    72
#include <unistd.h>
4244
77e7b46e3d5e 6243574 Services can be shown online with empty contracts
jeanm
parents: 3179
diff changeset
    73
#include <atomic.h>
77e7b46e3d5e 6243574 Services can be shown online with empty contracts
jeanm
parents: 3179
diff changeset
    74
#include <poll.h>
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    75
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    76
#include "startd.h"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    77
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    78
#define	SBIN_SH		"/sbin/sh"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    79
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    80
/*
4244
77e7b46e3d5e 6243574 Services can be shown online with empty contracts
jeanm
parents: 3179
diff changeset
    81
 * Used to tell if contracts are in the process of being
77e7b46e3d5e 6243574 Services can be shown online with empty contracts
jeanm
parents: 3179
diff changeset
    82
 * stored into the svc.startd internal hash table.
77e7b46e3d5e 6243574 Services can be shown online with empty contracts
jeanm
parents: 3179
diff changeset
    83
 */
77e7b46e3d5e 6243574 Services can be shown online with empty contracts
jeanm
parents: 3179
diff changeset
    84
volatile uint16_t	storing_contract = 0;
77e7b46e3d5e 6243574 Services can be shown online with empty contracts
jeanm
parents: 3179
diff changeset
    85
77e7b46e3d5e 6243574 Services can be shown online with empty contracts
jeanm
parents: 3179
diff changeset
    86
/*
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    87
 * Mapping from restart_on method-type to contract events.  Must correspond to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    88
 * enum method_restart_t.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    89
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    90
static uint_t method_events[] = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    91
	/* METHOD_RESTART_ALL */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    92
	CT_PR_EV_HWERR | CT_PR_EV_SIGNAL | CT_PR_EV_CORE | CT_PR_EV_EMPTY,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    93
	/* METHOD_RESTART_EXTERNAL_FAULT */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    94
	CT_PR_EV_HWERR | CT_PR_EV_SIGNAL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    95
	/* METHOD_RESTART_ANY_FAULT */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    96
	CT_PR_EV_HWERR | CT_PR_EV_SIGNAL | CT_PR_EV_CORE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    97
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    98
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    99
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   100
 * method_record_start(restarter_inst_t *)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   101
 *   Record a service start for rate limiting.  Place the current time
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   102
 *   in the circular array of instance starts.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   103
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   104
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   105
method_record_start(restarter_inst_t *inst)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   106
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   107
	int index = inst->ri_start_index++ % RINST_START_TIMES;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   108
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   109
	inst->ri_start_time[index] = gethrtime();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   110
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   111
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   112
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   113
 * method_rate_critical(restarter_inst_t *)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   114
 *    Return true if the average start interval is less than the permitted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   115
 *    interval.  Implicit success if insufficient measurements for an
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   116
 *    average exist.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   117
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   118
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   119
method_rate_critical(restarter_inst_t *inst)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   120
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   121
	uint_t n = inst->ri_start_index;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   122
	hrtime_t avg_ns = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   123
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   124
	if (inst->ri_start_index < RINST_START_TIMES)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   125
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   126
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   127
	avg_ns =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   128
	    (inst->ri_start_time[(n - 1) % RINST_START_TIMES] -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   129
	    inst->ri_start_time[n % RINST_START_TIMES]) /
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   130
	    (RINST_START_TIMES - 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   131
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   132
	return (avg_ns < RINST_FAILURE_RATE_NS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   133
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   134
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   135
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   136
 * int method_is_transient()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   137
 *   Determine if the method for the given instance is transient,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   138
 *   from a contract perspective. Return 1 if it is, and 0 if it isn't.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   139
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   140
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   141
method_is_transient(restarter_inst_t *inst, int type)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   142
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   143
	if (instance_is_transient_style(inst) || type != METHOD_START)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   144
		return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   145
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   146
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   147
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   148
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   149
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   150
 * void method_store_contract()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   151
 *   Store the newly created contract id into local structures and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   152
 *   the repository.  If the repository connection is broken it is rebound.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   153
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   154
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   155
method_store_contract(restarter_inst_t *inst, int type, ctid_t *cid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   156
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   157
	int r;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   158
	boolean_t primary;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   159
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   160
	if (errno = contract_latest(cid))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   161
		uu_die("%s: Couldn't get new contract's id", inst->ri_i.i_fmri);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   162
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   163
	primary = !method_is_transient(inst, type);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   164
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   165
	if (!primary) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   166
		if (inst->ri_i.i_transient_ctid != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   167
			log_framework(LOG_INFO,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   168
			    "%s: transient ctid expected to be 0 but "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   169
			    "was set to %ld\n", inst->ri_i.i_fmri,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   170
			    inst->ri_i.i_transient_ctid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   171
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   172
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   173
		inst->ri_i.i_transient_ctid = *cid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   174
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   175
		if (inst->ri_i.i_primary_ctid != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   176
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   177
			 * There was an old contract that we transferred.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   178
			 * Remove it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   179
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   180
			method_remove_contract(inst, B_TRUE, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   181
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   182
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   183
		if (inst->ri_i.i_primary_ctid != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   184
			log_framework(LOG_INFO,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   185
			    "%s: primary ctid expected to be 0 but "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   186
			    "was set to %ld\n", inst->ri_i.i_fmri,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   187
			    inst->ri_i.i_primary_ctid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   188
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   189
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   190
		inst->ri_i.i_primary_ctid = *cid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   191
		inst->ri_i.i_primary_ctid_stopped = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   192
4244
77e7b46e3d5e 6243574 Services can be shown online with empty contracts
jeanm
parents: 3179
diff changeset
   193
		log_framework(LOG_DEBUG, "Storing primary contract %ld for "
77e7b46e3d5e 6243574 Services can be shown online with empty contracts
jeanm
parents: 3179
diff changeset
   194
		    "%s.\n", *cid, inst->ri_i.i_fmri);
77e7b46e3d5e 6243574 Services can be shown online with empty contracts
jeanm
parents: 3179
diff changeset
   195
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   196
		contract_hash_store(*cid, inst->ri_id);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   197
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   198
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   199
again:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   200
	if (inst->ri_mi_deleted)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   201
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   202
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   203
	r = restarter_store_contract(inst->ri_m_inst, *cid, primary ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   204
	    RESTARTER_CONTRACT_PRIMARY : RESTARTER_CONTRACT_TRANSIENT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   205
	switch (r) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   206
	case 0:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   207
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   208
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   209
	case ECANCELED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   210
		inst->ri_mi_deleted = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   211
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   212
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   213
	case ECONNABORTED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   214
		libscf_handle_rebind(scf_instance_handle(inst->ri_m_inst));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   215
		/* FALLTHROUGH */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   216
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   217
	case EBADF:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   218
		libscf_reget_instance(inst);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   219
		goto again;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   220
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   221
	case ENOMEM:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   222
	case EPERM:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   223
	case EACCES:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   224
	case EROFS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   225
		uu_die("%s: Couldn't store contract id %ld",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   226
		    inst->ri_i.i_fmri, *cid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   227
		/* NOTREACHED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   228
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   229
	case EINVAL:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   230
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   231
		bad_error("restarter_store_contract", r);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   232
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   233
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   234
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   235
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   236
 * void method_remove_contract()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   237
 *   Remove any non-permanent contracts from internal structures and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   238
 *   the repository, then abandon them.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   239
 *   Returns
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   240
 *     0 - success
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   241
 *     ECANCELED - inst was deleted from the repository
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   242
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   243
 *   If the repository connection was broken, it is rebound.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   244
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   245
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   246
method_remove_contract(restarter_inst_t *inst, boolean_t primary,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   247
    boolean_t abandon)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   248
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   249
	ctid_t * const ctidp = primary ? &inst->ri_i.i_primary_ctid :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   250
	    &inst->ri_i.i_transient_ctid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   251
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   252
	int r;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   253
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   254
	assert(*ctidp != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   255
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   256
	log_framework(LOG_DEBUG, "Removing %s contract %lu for %s.\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   257
	    primary ? "primary" : "transient", *ctidp, inst->ri_i.i_fmri);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   258
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   259
	if (abandon)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   260
		contract_abandon(*ctidp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   261
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   262
again:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   263
	if (inst->ri_mi_deleted) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   264
		r = ECANCELED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   265
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   266
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   267
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   268
	r = restarter_remove_contract(inst->ri_m_inst, *ctidp, primary ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   269
	    RESTARTER_CONTRACT_PRIMARY : RESTARTER_CONTRACT_TRANSIENT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   270
	switch (r) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   271
	case 0:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   272
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   273
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   274
	case ECANCELED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   275
		inst->ri_mi_deleted = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   276
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   277
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   278
	case ECONNABORTED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   279
		libscf_handle_rebind(scf_instance_handle(inst->ri_m_inst));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   280
		/* FALLTHROUGH */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   281
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   282
	case EBADF:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   283
		libscf_reget_instance(inst);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   284
		goto again;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   285
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   286
	case ENOMEM:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   287
	case EPERM:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   288
	case EACCES:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   289
	case EROFS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   290
		log_error(LOG_INFO, "%s: Couldn't remove contract id %ld: "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   291
		    "%s.\n", inst->ri_i.i_fmri, *ctidp, strerror(r));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   292
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   293
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   294
	case EINVAL:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   295
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   296
		bad_error("restarter_remove_contract", r);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   297
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   298
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   299
out:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   300
	if (primary)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   301
		contract_hash_remove(*ctidp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   302
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   303
	*ctidp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   304
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   305
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   306
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   307
 * int method_ready_contract(restarter_inst_t *, int, method_restart_t, int)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   308
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   309
 *   Activate a contract template for the type method of inst.  type,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   310
 *   restart_on, and cte_mask dictate the critical events term of the contract.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   311
 *   Returns
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   312
 *     0 - success
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   313
 *     ECANCELED - inst has been deleted from the repository
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   314
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   315
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   316
method_ready_contract(restarter_inst_t *inst, int type,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   317
    method_restart_t restart_on, uint_t cte_mask)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   318
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   319
	int tmpl, err, istrans, iswait, ret;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   320
	uint_t cevents, fevents;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   321
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   322
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   323
	 * Correctly supporting wait-style services is tricky without
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   324
	 * rearchitecting startd to cope with multiple event sources
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   325
	 * simultaneously trying to stop an instance.  Until a better
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   326
	 * solution is implemented, we avoid this problem for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   327
	 * wait-style services by making contract events fatal and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   328
	 * letting the wait code alone handle stopping the service.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   329
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   330
	iswait = instance_is_wait_style(inst);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   331
	istrans = method_is_transient(inst, type);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   332
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   333
	tmpl = open64(CTFS_ROOT "/process/template", O_RDWR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   334
	if (tmpl == -1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   335
		uu_die("Could not create contract template");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   336
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   337
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   338
	 * We assume non-login processes are unlikely to create
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   339
	 * multiple process groups, and set CT_PR_PGRPONLY for all
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   340
	 * wait-style services' contracts.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   341
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   342
	err = ct_pr_tmpl_set_param(tmpl, CT_PR_INHERIT | CT_PR_REGENT |
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   343
	    (iswait ? CT_PR_PGRPONLY : 0));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   344
	assert(err == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   345
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   346
	if (istrans) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   347
		cevents = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   348
		fevents = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   349
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   350
		assert(restart_on >= 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   351
		assert(restart_on <= METHOD_RESTART_ANY_FAULT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   352
		cevents = method_events[restart_on] & ~cte_mask;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   353
		fevents = iswait ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   354
		    (method_events[restart_on] & ~cte_mask & CT_PR_ALLFATAL) :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   355
		    0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   356
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   357
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   358
	err = ct_tmpl_set_critical(tmpl, cevents);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   359
	assert(err == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   360
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   361
	err = ct_tmpl_set_informative(tmpl, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   362
	assert(err == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   363
	err = ct_pr_tmpl_set_fatal(tmpl, fevents);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   364
	assert(err == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   365
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   366
	err = ct_tmpl_set_cookie(tmpl, istrans ?  METHOD_OTHER_COOKIE :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   367
	    METHOD_START_COOKIE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   368
	assert(err == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   369
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   370
	if (type == METHOD_START && inst->ri_i.i_primary_ctid != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   371
		ret = ct_pr_tmpl_set_transfer(tmpl, inst->ri_i.i_primary_ctid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   372
		switch (ret) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   373
		case 0:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   374
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   375
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   376
		case ENOTEMPTY:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   377
			/* No contracts for you! */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   378
			method_remove_contract(inst, B_TRUE, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   379
			if (inst->ri_mi_deleted) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   380
				ret = ECANCELED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   381
				goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   382
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   383
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   384
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   385
		case EINVAL:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   386
		case ESRCH:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   387
		case EACCES:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   388
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   389
			bad_error("ct_pr_tmpl_set_transfer", ret);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   390
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   391
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   392
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   393
	err = ct_tmpl_activate(tmpl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   394
	assert(err == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   395
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   396
	ret = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   397
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   398
out:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   399
	err = close(tmpl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   400
	assert(err == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   401
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   402
	return (ret);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   403
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   404
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   405
static const char *method_names[] = { "start", "stop", "refresh" };
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   406
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   407
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   408
exec_method(const restarter_inst_t *inst, int type, const char *method,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   409
    struct method_context *mcp, uint8_t need_session)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   410
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   411
	char *cmd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   412
	const char *errf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   413
	char **nenv;
4816
8f99ff23cf47 6411807 exec_method drops errno when juggling errors
acruz
parents: 4432
diff changeset
   414
	int rsmc_errno = 0;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   415
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   416
	cmd = uu_msprintf("exec %s", method);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   417
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   418
	if (inst->ri_utmpx_prefix[0] != '\0' && inst->ri_utmpx_prefix != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   419
		(void) utmpx_mark_init(getpid(), inst->ri_utmpx_prefix);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   420
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   421
	setlog(inst->ri_logstem);
5238
37127716670e Contributed by Mark Martin <[email protected]>.
lianep
parents: 5040
diff changeset
   422
	log_instance(inst, B_FALSE, "Executing %s method (\"%s\").",
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   423
	    method_names[type], method);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   424
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   425
	if (need_session)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   426
		(void) setpgrp();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   427
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   428
	/* Set credentials. */
4816
8f99ff23cf47 6411807 exec_method drops errno when juggling errors
acruz
parents: 4432
diff changeset
   429
	rsmc_errno = restarter_set_method_context(mcp, &errf);
8f99ff23cf47 6411807 exec_method drops errno when juggling errors
acruz
parents: 4432
diff changeset
   430
	if (rsmc_errno != 0) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   431
		(void) fputs("svc.startd could not set context for method: ",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   432
		    stderr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   433
4816
8f99ff23cf47 6411807 exec_method drops errno when juggling errors
acruz
parents: 4432
diff changeset
   434
		if (rsmc_errno == -1) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   435
			if (strcmp(errf, "core_set_process_path") == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   436
				(void) fputs("Could not set corefile path.\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   437
				    stderr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   438
			} else if (strcmp(errf, "setproject") == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   439
				(void) fprintf(stderr, "%s: a resource control "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   440
				    "assignment failed\n", errf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   441
			} else if (strcmp(errf, "pool_set_binding") == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   442
				(void) fprintf(stderr, "%s: a system error "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   443
				    "occurred\n", errf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   444
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   445
#ifndef NDEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   446
				uu_warn("%s:%d: Bad function name \"%s\" for "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   447
				    "error %d from "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   448
				    "restarter_set_method_context().\n",
4816
8f99ff23cf47 6411807 exec_method drops errno when juggling errors
acruz
parents: 4432
diff changeset
   449
				    __FILE__, __LINE__, errf, rsmc_errno);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   450
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   451
				abort();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   452
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   453
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   454
			exit(1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   455
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   456
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   457
		if (errf != NULL && strcmp(errf, "pool_set_binding") == 0) {
4816
8f99ff23cf47 6411807 exec_method drops errno when juggling errors
acruz
parents: 4432
diff changeset
   458
			switch (rsmc_errno) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   459
			case ENOENT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   460
				(void) fprintf(stderr, "%s: the pool could not "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   461
				    "be found\n", errf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   462
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   463
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   464
			case EBADF:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   465
				(void) fprintf(stderr, "%s: the configuration "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   466
				    "is invalid\n", errf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   467
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   468
1712
c5243b0fd703 6266365 svc.startd tried to use deadbeef
rm88369
parents: 119
diff changeset
   469
			case EINVAL:
c5243b0fd703 6266365 svc.startd tried to use deadbeef
rm88369
parents: 119
diff changeset
   470
				(void) fprintf(stderr, "%s: pool name \"%s\" "
c5243b0fd703 6266365 svc.startd tried to use deadbeef
rm88369
parents: 119
diff changeset
   471
				    "is invalid\n", errf, mcp->resource_pool);
c5243b0fd703 6266365 svc.startd tried to use deadbeef
rm88369
parents: 119
diff changeset
   472
				break;
c5243b0fd703 6266365 svc.startd tried to use deadbeef
rm88369
parents: 119
diff changeset
   473
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   474
			default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   475
#ifndef NDEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   476
				uu_warn("%s:%d: Bad error %d for function %s "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   477
				    "in restarter_set_method_context().\n",
4816
8f99ff23cf47 6411807 exec_method drops errno when juggling errors
acruz
parents: 4432
diff changeset
   478
				    __FILE__, __LINE__, rsmc_errno, errf);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   479
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   480
				abort();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   481
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   482
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   483
			exit(SMF_EXIT_ERR_CONFIG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   484
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   485
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   486
		if (errf != NULL) {
4816
8f99ff23cf47 6411807 exec_method drops errno when juggling errors
acruz
parents: 4432
diff changeset
   487
			errno = rsmc_errno;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   488
			perror(errf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   489
4816
8f99ff23cf47 6411807 exec_method drops errno when juggling errors
acruz
parents: 4432
diff changeset
   490
			switch (rsmc_errno) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   491
			case EINVAL:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   492
			case EPERM:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   493
			case ENOENT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   494
			case ENAMETOOLONG:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   495
			case ERANGE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   496
			case ESRCH:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   497
				exit(SMF_EXIT_ERR_CONFIG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   498
				/* NOTREACHED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   499
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   500
			default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   501
				exit(1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   502
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   503
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   504
4816
8f99ff23cf47 6411807 exec_method drops errno when juggling errors
acruz
parents: 4432
diff changeset
   505
		switch (rsmc_errno) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   506
		case ENOMEM:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   507
			(void) fputs("Out of memory.\n", stderr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   508
			exit(1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   509
			/* NOTREACHED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   510
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   511
		case ENOENT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   512
			(void) fputs("Missing passwd entry for user.\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   513
			    stderr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   514
			exit(SMF_EXIT_ERR_CONFIG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   515
			/* NOTREACHED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   516
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   517
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   518
#ifndef NDEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   519
			uu_warn("%s:%d: Bad miscellaneous error %d from "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   520
			    "restarter_set_method_context().\n", __FILE__,
4816
8f99ff23cf47 6411807 exec_method drops errno when juggling errors
acruz
parents: 4432
diff changeset
   521
			    __LINE__, rsmc_errno);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   522
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   523
			abort();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   524
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   525
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   526
5040
ff6ebd8761a6 PSARC 2007/177 SMF read-protected property storage
wesolows
parents: 4816
diff changeset
   527
	nenv = set_smf_env(mcp->env, mcp->env_sz, NULL, inst,
ff6ebd8761a6 PSARC 2007/177 SMF read-protected property storage
wesolows
parents: 4816
diff changeset
   528
	    method_names[type]);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   529
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   530
	log_preexec();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   531
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   532
	(void) execle(SBIN_SH, SBIN_SH, "-c", cmd, NULL, nenv);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   533
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   534
	exit(10);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   535
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   536
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   537
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   538
write_status(restarter_inst_t *inst, const char *mname, int stat)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   539
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   540
	int r;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   541
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   542
again:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   543
	if (inst->ri_mi_deleted)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   544
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   545
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   546
	r = libscf_write_method_status(inst->ri_m_inst, mname, stat);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   547
	switch (r) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   548
	case 0:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   549
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   550
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   551
	case ECONNABORTED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   552
		libscf_reget_instance(inst);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   553
		goto again;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   554
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   555
	case ECANCELED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   556
		inst->ri_mi_deleted = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   557
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   558
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   559
	case EPERM:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   560
	case EACCES:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   561
	case EROFS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   562
		log_framework(LOG_INFO, "Could not write exit status "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   563
		    "for %s method of %s: %s.\n", mname,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   564
		    inst->ri_i.i_fmri, strerror(r));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   565
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   566
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   567
	case ENAMETOOLONG:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   568
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   569
		bad_error("libscf_write_method_status", r);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   570
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   571
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   572
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   573
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   574
 * int method_run()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   575
 *   Execute the type method of instp.  If it requires a fork(), wait for it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   576
 *   to return and return its exit code in *exit_code.  Otherwise set
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   577
 *   *exit_code to 0 if the method succeeds & -1 if it fails.  If the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   578
 *   repository connection is broken, it is rebound, but inst may not be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   579
 *   reset.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   580
 *   Returns
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   581
 *     0 - success
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   582
 *     EINVAL - A correct method or method context couldn't be retrieved.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   583
 *     EIO - Contract kill failed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   584
 *     EFAULT - Method couldn't be executed successfully.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   585
 *     ELOOP - Retry threshold exceeded.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   586
 *     ECANCELED - inst was deleted from the repository before method was run
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   587
 *     ERANGE - Timeout retry threshold exceeded.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   588
 *     EAGAIN - Failed due to external cause, retry.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   589
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   590
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   591
method_run(restarter_inst_t **instp, int type, int *exit_code)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   592
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   593
	char *method;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   594
	int ret_status;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   595
	pid_t pid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   596
	method_restart_t restart_on;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   597
	uint_t cte_mask;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   598
	uint8_t need_session;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   599
	scf_handle_t *h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   600
	scf_snapshot_t *snap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   601
	const char *mname;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   602
	const char *errstr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   603
	struct method_context *mcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   604
	int result = 0, timeout_fired = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   605
	int sig, r;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   606
	boolean_t transient;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   607
	uint64_t timeout;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   608
	uint8_t timeout_retry;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   609
	ctid_t ctid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   610
	int ctfd = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   611
	restarter_inst_t *inst = *instp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   612
	int id = inst->ri_id;
119
7bdce363820e 6202359 startd needs to retry methods on fork failure
sl108498
parents: 0
diff changeset
   613
	int forkerr;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   614
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   615
	assert(PTHREAD_MUTEX_HELD(&inst->ri_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   616
	assert(instance_in_transition(inst));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   617
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   618
	if (inst->ri_mi_deleted)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   619
		return (ECANCELED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   620
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   621
	*exit_code = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   622
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   623
	assert(0 <= type && type <= 2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   624
	mname = method_names[type];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   625
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   626
	if (type == METHOD_START)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   627
		inst->ri_pre_online_hook();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   628
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   629
	h = scf_instance_handle(inst->ri_m_inst);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   630
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   631
	snap = scf_snapshot_create(h);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   632
	if (snap == NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   633
	    scf_instance_get_snapshot(inst->ri_m_inst, "running", snap) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   634
		log_framework(LOG_DEBUG,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   635
		    "Could not get running snapshot for %s.  "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   636
		    "Using editing version to run method %s.\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   637
		    inst->ri_i.i_fmri, mname);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   638
		scf_snapshot_destroy(snap);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   639
		snap = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   640
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   641
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   642
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   643
	 * After this point, we may be logging to the instance log.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   644
	 * Make sure we've noted where that log is as a property of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   645
	 * the instance.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   646
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   647
	r = libscf_note_method_log(inst->ri_m_inst, st->st_log_prefix,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   648
	    inst->ri_logstem);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   649
	if (r != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   650
		log_framework(LOG_WARNING,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   651
		    "%s: couldn't note log location: %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   652
		    inst->ri_i.i_fmri, strerror(r));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   653
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   654
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   655
	if ((method = libscf_get_method(h, type, inst, snap, &restart_on,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   656
	    &cte_mask, &need_session, &timeout, &timeout_retry)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   657
		if (errno == LIBSCF_PGROUP_ABSENT)  {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   658
			log_framework(LOG_DEBUG,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   659
			    "%s: instance has no method property group '%s'.\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   660
			    inst->ri_i.i_fmri, mname);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   661
			if (type == METHOD_REFRESH)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   662
				log_instance(inst, B_TRUE, "No '%s' method "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   663
				    "defined.  Treating as :true.", mname);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   664
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   665
				log_instance(inst, B_TRUE, "Method property "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   666
				    "group '%s' is not present.", mname);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   667
			scf_snapshot_destroy(snap);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   668
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   669
		} else if (errno == LIBSCF_PROPERTY_ABSENT)  {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   670
			log_framework(LOG_DEBUG,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   671
			    "%s: instance has no '%s/exec' method property.\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   672
			    inst->ri_i.i_fmri, mname);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   673
			log_instance(inst, B_TRUE, "Method property '%s/exec "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   674
			    "is not present.", mname);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   675
			scf_snapshot_destroy(snap);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   676
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   677
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   678
			log_error(LOG_WARNING,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   679
			    "%s: instance libscf_get_method failed\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   680
			    inst->ri_i.i_fmri);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   681
			scf_snapshot_destroy(snap);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   682
			return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   683
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   684
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   685
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   686
	/* open service contract if stopping a non-transient service */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   687
	if (type == METHOD_STOP && (!instance_is_transient_style(inst))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   688
		if (inst->ri_i.i_primary_ctid == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   689
			/* service is not running, nothing to stop */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   690
			log_framework(LOG_DEBUG, "%s: instance has no primary "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   691
			    "contract, no service to stop.\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   692
			    inst->ri_i.i_fmri);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   693
			scf_snapshot_destroy(snap);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   694
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   695
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   696
		if ((ctfd = contract_open(inst->ri_i.i_primary_ctid, "process",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   697
		    "events", O_RDONLY)) < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   698
			result = EFAULT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   699
			log_instance(inst, B_TRUE, "Could not open service "
5238
37127716670e Contributed by Mark Martin <[email protected]>.
lianep
parents: 5040
diff changeset
   700
			    "contract %ld.  Stop method not run.",
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   701
			    inst->ri_i.i_primary_ctid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   702
			goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   703
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   704
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   705
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   706
	if (restarter_is_null_method(method)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   707
		log_framework(LOG_DEBUG, "%s: null method succeeds\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   708
		    inst->ri_i.i_fmri);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   709
5238
37127716670e Contributed by Mark Martin <[email protected]>.
lianep
parents: 5040
diff changeset
   710
		log_instance(inst, B_TRUE, "Executing %s method (null).",
37127716670e Contributed by Mark Martin <[email protected]>.
lianep
parents: 5040
diff changeset
   711
		    mname);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   712
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   713
		if (type == METHOD_START)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   714
			write_status(inst, mname, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   715
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   716
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   717
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   718
	sig = restarter_is_kill_method(method);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   719
	if (sig >= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   720
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   721
		if (inst->ri_i.i_primary_ctid == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   722
			log_error(LOG_ERR, "%s: :kill with no contract\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   723
			    inst->ri_i.i_fmri);
5238
37127716670e Contributed by Mark Martin <[email protected]>.
lianep
parents: 5040
diff changeset
   724
			log_instance(inst, B_TRUE, "Invalid use of \":kill\" "
37127716670e Contributed by Mark Martin <[email protected]>.
lianep
parents: 5040
diff changeset
   725
			    "as stop method for transient service.");
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   726
			result = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   727
			goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   728
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   729
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   730
		log_framework(LOG_DEBUG,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   731
		    "%s: :killing contract with signal %d\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   732
		    inst->ri_i.i_fmri, sig);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   733
5238
37127716670e Contributed by Mark Martin <[email protected]>.
lianep
parents: 5040
diff changeset
   734
		log_instance(inst, B_TRUE, "Executing %s method (:kill).",
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   735
		    mname);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   736
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   737
		if (contract_kill(inst->ri_i.i_primary_ctid, sig,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   738
		    inst->ri_i.i_fmri) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   739
			result = EIO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   740
			goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   741
		} else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   742
			goto assured_kill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   743
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   744
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   745
	log_framework(LOG_DEBUG, "%s: forking to run method %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   746
	    inst->ri_i.i_fmri, method);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   747
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   748
	errstr = restarter_get_method_context(RESTARTER_METHOD_CONTEXT_VERSION,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   749
	    inst->ri_m_inst, snap, mname, method, &mcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   750
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   751
	if (errstr != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   752
		log_error(LOG_WARNING, "%s: %s\n", inst->ri_i.i_fmri, errstr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   753
		result = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   754
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   755
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   756
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   757
	r = method_ready_contract(inst, type, restart_on, cte_mask);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   758
	if (r != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   759
		assert(r == ECANCELED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   760
		assert(inst->ri_mi_deleted);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   761
		restarter_free_method_context(mcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   762
		result = ECANCELED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   763
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   764
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   765
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   766
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   767
	 * Validate safety of method contexts, to save children work.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   768
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   769
	if (!restarter_rm_libs_loadable())
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   770
		log_framework(LOG_DEBUG, "%s: method contexts limited "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   771
		    "to root-accessible libraries\n", inst->ri_i.i_fmri);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   772
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   773
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   774
	 * If the service is restarting too quickly, send it to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   775
	 * maintenance.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   776
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   777
	if (type == METHOD_START) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   778
		method_record_start(inst);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   779
		if (method_rate_critical(inst)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   780
			log_instance(inst, B_TRUE, "Restarting too quickly, "
5238
37127716670e Contributed by Mark Martin <[email protected]>.
lianep
parents: 5040
diff changeset
   781
			    "changing state to maintenance.");
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   782
			result = ELOOP;
3179
80729b9ca1d6 5079387 _get_auth_policy() doesn't provide corresponding free function
jeanm
parents: 1712
diff changeset
   783
			restarter_free_method_context(mcp);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   784
			goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   785
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   786
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   787
4244
77e7b46e3d5e 6243574 Services can be shown online with empty contracts
jeanm
parents: 3179
diff changeset
   788
	atomic_add_16(&storing_contract, 1);
119
7bdce363820e 6202359 startd needs to retry methods on fork failure
sl108498
parents: 0
diff changeset
   789
	pid = startd_fork1(&forkerr);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   790
	if (pid == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   791
		exec_method(inst, type, method, mcp, need_session);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   792
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   793
	if (pid == -1) {
4244
77e7b46e3d5e 6243574 Services can be shown online with empty contracts
jeanm
parents: 3179
diff changeset
   794
		atomic_add_16(&storing_contract, -1);
119
7bdce363820e 6202359 startd needs to retry methods on fork failure
sl108498
parents: 0
diff changeset
   795
		if (forkerr == EAGAIN)
7bdce363820e 6202359 startd needs to retry methods on fork failure
sl108498
parents: 0
diff changeset
   796
			result = EAGAIN;
7bdce363820e 6202359 startd needs to retry methods on fork failure
sl108498
parents: 0
diff changeset
   797
		else
7bdce363820e 6202359 startd needs to retry methods on fork failure
sl108498
parents: 0
diff changeset
   798
			result = EFAULT;
7bdce363820e 6202359 startd needs to retry methods on fork failure
sl108498
parents: 0
diff changeset
   799
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   800
		log_error(LOG_WARNING,
119
7bdce363820e 6202359 startd needs to retry methods on fork failure
sl108498
parents: 0
diff changeset
   801
		    "%s: Couldn't fork to execute method %s: %s\n",
7bdce363820e 6202359 startd needs to retry methods on fork failure
sl108498
parents: 0
diff changeset
   802
		    inst->ri_i.i_fmri, method, strerror(forkerr));
7bdce363820e 6202359 startd needs to retry methods on fork failure
sl108498
parents: 0
diff changeset
   803
4244
77e7b46e3d5e 6243574 Services can be shown online with empty contracts
jeanm
parents: 3179
diff changeset
   804
		restarter_free_method_context(mcp);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   805
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   806
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   807
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   808
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   809
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   810
	 * Get the contract id, decide whether it is primary or transient, and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   811
	 * stash it in inst & the repository.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   812
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   813
	method_store_contract(inst, type, &ctid);
4244
77e7b46e3d5e 6243574 Services can be shown online with empty contracts
jeanm
parents: 3179
diff changeset
   814
	atomic_add_16(&storing_contract, -1);
77e7b46e3d5e 6243574 Services can be shown online with empty contracts
jeanm
parents: 3179
diff changeset
   815
77e7b46e3d5e 6243574 Services can be shown online with empty contracts
jeanm
parents: 3179
diff changeset
   816
	restarter_free_method_context(mcp);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   817
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   818
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   819
	 * Similarly for the start method PID.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   820
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   821
	if (type == METHOD_START && !inst->ri_mi_deleted)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   822
		(void) libscf_write_start_pid(inst->ri_m_inst, pid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   823
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   824
	if (instance_is_wait_style(inst) && type == METHOD_START) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   825
		/* Wait style instances don't get timeouts on start methods. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   826
		if (wait_register(pid, inst->ri_i.i_fmri, 1, 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   827
			log_error(LOG_WARNING,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   828
			    "%s: couldn't register %ld for wait\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   829
			    inst->ri_i.i_fmri, pid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   830
			result = EFAULT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   831
			goto contract_out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   832
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   833
		write_status(inst, mname, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   834
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   835
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   836
		int r, err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   837
		time_t start_time;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   838
		time_t end_time;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   839
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   840
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   841
		 * Because on upgrade/live-upgrade we may have no chance
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   842
		 * to override faulty timeout values on the way to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   843
		 * manifest import, all services on the path to manifest
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   844
		 * import are treated the same as INFINITE timeout services.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   845
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   846
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   847
		start_time = time(NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   848
		if (timeout != METHOD_TIMEOUT_INFINITE && !is_timeout_ovr(inst))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   849
			timeout_insert(inst, ctid, timeout);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   850
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   851
			timeout = METHOD_TIMEOUT_INFINITE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   852
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   853
		/* Unlock the instance while waiting for the method. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   854
		MUTEX_UNLOCK(&inst->ri_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   855
4816
8f99ff23cf47 6411807 exec_method drops errno when juggling errors
acruz
parents: 4432
diff changeset
   856
		do {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   857
			r = waitpid(pid, &ret_status, NULL);
4816
8f99ff23cf47 6411807 exec_method drops errno when juggling errors
acruz
parents: 4432
diff changeset
   858
		} while (r == -1 && errno == EINTR);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   859
		if (r == -1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   860
			err = errno;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   861
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   862
		/* Re-grab the lock. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   863
		inst = inst_lookup_by_id(id);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   864
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   865
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   866
		 * inst can't be removed, as the removal thread waits
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   867
		 * for completion of this one.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   868
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   869
		assert(inst != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   870
		*instp = inst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   871
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   872
		if (inst->ri_timeout != NULL && inst->ri_timeout->te_fired)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   873
			timeout_fired = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   874
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   875
		timeout_remove(inst, ctid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   876
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   877
		log_framework(LOG_DEBUG,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   878
		    "%s method for %s exited with status %d.\n", mname,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   879
		    inst->ri_i.i_fmri, WEXITSTATUS(ret_status));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   880
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   881
		if (r == -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   882
			log_error(LOG_WARNING,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   883
			    "Couldn't waitpid() for %s method of %s (%s).\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   884
			    mname, inst->ri_i.i_fmri, strerror(err));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   885
			result = EFAULT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   886
			goto contract_out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   887
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   888
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   889
		if (type == METHOD_START)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   890
			write_status(inst, mname, ret_status);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   891
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   892
		/* return ERANGE if this service doesn't retry on timeout */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   893
		if (timeout_fired == 1 && timeout_retry == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   894
			result = ERANGE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   895
			goto contract_out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   896
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   897
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   898
		if (!WIFEXITED(ret_status)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   899
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   900
			 * If method didn't exit itself (it was killed by an
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   901
			 * external entity, etc.), consider the entire
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   902
			 * method_run as failed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   903
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   904
			if (WIFSIGNALED(ret_status)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   905
				char buf[SIG2STR_MAX];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   906
				(void) sig2str(WTERMSIG(ret_status), buf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   907
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   908
				log_error(LOG_WARNING, "%s: Method \"%s\" "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   909
				    "failed due to signal %s.\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   910
				    inst->ri_i.i_fmri, method, buf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   911
				log_instance(inst, B_TRUE, "Method \"%s\" "
5238
37127716670e Contributed by Mark Martin <[email protected]>.
lianep
parents: 5040
diff changeset
   912
				    "failed due to signal %s.", mname, buf);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   913
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   914
				log_error(LOG_WARNING, "%s: Method \"%s\" "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   915
				    "failed with exit status %d.\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   916
				    inst->ri_i.i_fmri, method,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   917
				    WEXITSTATUS(ret_status));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   918
				log_instance(inst, B_TRUE, "Method \"%s\" "
5238
37127716670e Contributed by Mark Martin <[email protected]>.
lianep
parents: 5040
diff changeset
   919
				    "failed with exit status %d.", mname,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   920
				    WEXITSTATUS(ret_status));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   921
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   922
			result = EAGAIN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   923
			goto contract_out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   924
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   925
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   926
		*exit_code = WEXITSTATUS(ret_status);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   927
		if (*exit_code != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   928
			log_error(LOG_WARNING,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   929
			    "%s: Method \"%s\" failed with exit status %d.\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   930
			    inst->ri_i.i_fmri, method, WEXITSTATUS(ret_status));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   931
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   932
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   933
		log_instance(inst, B_TRUE, "Method \"%s\" exited with status "
5238
37127716670e Contributed by Mark Martin <[email protected]>.
lianep
parents: 5040
diff changeset
   934
		    "%d.", mname, *exit_code);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   935
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   936
		if (*exit_code != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   937
			goto contract_out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   938
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   939
		end_time = time(NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   940
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   941
		/* Give service contract remaining seconds to empty */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   942
		if (timeout != METHOD_TIMEOUT_INFINITE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   943
			timeout -= (end_time - start_time);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   944
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   945
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   946
assured_kill:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   947
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   948
	 * For stop methods, assure that the service contract has emptied
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   949
	 * before returning.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   950
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   951
	if (type == METHOD_STOP && (!instance_is_transient_style(inst)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   952
	    !(contract_is_empty(inst->ri_i.i_primary_ctid))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   953
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   954
		if (timeout != METHOD_TIMEOUT_INFINITE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   955
			timeout_insert(inst, inst->ri_i.i_primary_ctid,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   956
			    timeout);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   957
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   958
		for (;;) {
4244
77e7b46e3d5e 6243574 Services can be shown online with empty contracts
jeanm
parents: 3179
diff changeset
   959
			(void) poll(NULL, 0, 100);
77e7b46e3d5e 6243574 Services can be shown online with empty contracts
jeanm
parents: 3179
diff changeset
   960
			if (contract_is_empty(inst->ri_i.i_primary_ctid))
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   961
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   962
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   963
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   964
		if (timeout != METHOD_TIMEOUT_INFINITE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   965
			if (inst->ri_timeout->te_fired)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   966
				result = EFAULT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   967
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   968
		timeout_remove(inst, inst->ri_i.i_primary_ctid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   969
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   970
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   971
contract_out:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   972
	/* Abandon contracts for transient methods & methods that fail. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   973
	transient = method_is_transient(inst, type);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   974
	if ((transient || *exit_code != 0 || result != 0) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   975
	    (restarter_is_kill_method(method) < 0))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   976
		method_remove_contract(inst, !transient, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   977
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   978
out:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   979
	if (ctfd >= 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   980
		(void) close(ctfd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   981
	scf_snapshot_destroy(snap);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   982
	free(method);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   983
	return (result);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   984
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   985
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   986
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   987
 * The method thread executes a service method to effect a state transition.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   988
 * The next_state of info->sf_id should be non-_NONE on entrance, and it will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   989
 * be _NONE on exit (state will either be what next_state was (on success), or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   990
 * it will be _MAINT (on error)).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   991
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   992
 * There are six classes of methods to consider: start & other (stop, refresh)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   993
 * for each of "normal" services, wait services, and transient services.  For
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   994
 * each, the method must be fetched from the repository & executed.  fork()ed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   995
 * methods must be waited on, except for the start method of wait services
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   996
 * (which must be registered with the wait subsystem via wait_register()).  If
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   997
 * the method succeeded (returned 0), then for start methods its contract
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   998
 * should be recorded as the primary contract for the service.  For other
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   999
 * methods, it should be abandoned.  If the method fails, then depending on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1000
 * the failure, either the method should be reexecuted or the service should
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1001
 * be put into maintenance.  Either way the contract should be abandoned.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1002
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1003
void *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1004
method_thread(void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1005
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1006
	fork_info_t *info = arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1007
	restarter_inst_t *inst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1008
	scf_handle_t	*local_handle;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1009
	scf_instance_t	*s_inst = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1010
	int r, exit_code;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1011
	boolean_t retryable;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1012
	const char *aux;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1013
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1014
	assert(0 <= info->sf_method_type && info->sf_method_type <= 2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1015
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1016
	/* Get (and lock) the restarter_inst_t. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1017
	inst = inst_lookup_by_id(info->sf_id);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1018
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1019
	assert(inst->ri_method_thread != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1020
	assert(instance_in_transition(inst) == 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1021
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1022
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1023
	 * We cannot leave this function with inst in transition, because
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1024
	 * protocol.c withholds messages for inst otherwise.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1025
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1026
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1027
	log_framework(LOG_DEBUG, "method_thread() running %s method for %s.\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1028
	    method_names[info->sf_method_type], inst->ri_i.i_fmri);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1029
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1030
	local_handle = libscf_handle_create_bound_loop();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1031
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1032
rebind_retry:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1033
	/* get scf_instance_t */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1034
	switch (r = libscf_fmri_get_instance(local_handle, inst->ri_i.i_fmri,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1035
	    &s_inst)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1036
	case 0:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1037
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1038
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1039
	case ECONNABORTED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1040
		libscf_handle_rebind(local_handle);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1041
		goto rebind_retry;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1042
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1043
	case ENOENT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1044
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1045
		 * It's not there, but we need to call this so protocol.c
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1046
		 * doesn't think it's in transition anymore.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1047
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1048
		(void) restarter_instance_update_states(local_handle, inst,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1049
		    inst->ri_i.i_state, RESTARTER_STATE_NONE, RERR_NONE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1050
		    NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1051
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1052
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1053
	case EINVAL:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1054
	case ENOTSUP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1055
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1056
		bad_error("libscf_fmri_get_instance", r);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1057
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1058
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1059
	inst->ri_m_inst = s_inst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1060
	inst->ri_mi_deleted = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1061
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1062
retry:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1063
	if (info->sf_method_type == METHOD_START)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1064
		log_transition(inst, START_REQUESTED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1065
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1066
	r = method_run(&inst, info->sf_method_type, &exit_code);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1067
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1068
	if (r == 0 && exit_code == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1069
		/* Success! */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1070
		assert(inst->ri_i.i_next_state != RESTARTER_STATE_NONE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1071
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1072
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1073
		 * When a stop method succeeds, remove the primary contract of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1074
		 * the service, unless we're going to offline, in which case
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1075
		 * retain the contract so we can transfer inherited contracts to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1076
		 * the replacement service.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1077
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1078
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1079
		if (info->sf_method_type == METHOD_STOP &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1080
		    inst->ri_i.i_primary_ctid != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1081
			if (inst->ri_i.i_next_state == RESTARTER_STATE_OFFLINE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1082
				inst->ri_i.i_primary_ctid_stopped = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1083
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1084
				method_remove_contract(inst, B_TRUE, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1085
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1086
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1087
		 * We don't care whether the handle was rebound because this is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1088
		 * the last thing we do with it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1089
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1090
		(void) restarter_instance_update_states(local_handle, inst,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1091
		    inst->ri_i.i_next_state, RESTARTER_STATE_NONE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1092
		    info->sf_event_type, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1093
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1094
		(void) update_fault_count(inst, FAULT_COUNT_RESET);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1095
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1096
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1097
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1098
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1099
	/* Failure.  Retry or go to maintenance. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1100
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1101
	if (r != 0 && r != EAGAIN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1102
		retryable = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1103
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1104
		switch (exit_code) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1105
		case SMF_EXIT_ERR_CONFIG:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1106
		case SMF_EXIT_ERR_NOSMF:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1107
		case SMF_EXIT_ERR_PERM:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1108
		case SMF_EXIT_ERR_FATAL:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1109
			retryable = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1110
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1111
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1112
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1113
			retryable = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1114
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1115
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1116
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1117
	if (retryable && update_fault_count(inst, FAULT_COUNT_INCR) != 1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1118
		goto retry;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1119
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1120
	/* maintenance */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1121
	if (r == ELOOP)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1122
		log_transition(inst, START_FAILED_REPEATEDLY);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1123
	else if (r == ERANGE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1124
		log_transition(inst, START_FAILED_TIMEOUT_FATAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1125
	else if (exit_code == SMF_EXIT_ERR_CONFIG)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1126
		log_transition(inst, START_FAILED_CONFIGURATION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1127
	else if (exit_code == SMF_EXIT_ERR_FATAL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1128
		log_transition(inst, START_FAILED_FATAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1129
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1130
		log_transition(inst, START_FAILED_OTHER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1131
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1132
	if (r == ELOOP)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1133
		aux = "restarting_too_quickly";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1134
	else if (retryable)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1135
		aux = "fault_threshold_reached";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1136
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1137
		aux = "method_failed";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1138
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1139
	(void) restarter_instance_update_states(local_handle, inst,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1140
	    RESTARTER_STATE_MAINT, RESTARTER_STATE_NONE, RERR_FAULT,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1141
	    (char *)aux);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1142
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1143
	if (!method_is_transient(inst, info->sf_method_type) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1144
	    inst->ri_i.i_primary_ctid != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1145
		method_remove_contract(inst, B_TRUE, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1146
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1147
out:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1148
	inst->ri_method_thread = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1149
	MUTEX_UNLOCK(&inst->ri_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1150
	(void) pthread_cond_broadcast(&inst->ri_method_cv);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1151
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1152
	scf_instance_destroy(s_inst);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1153
	scf_handle_destroy(local_handle);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1154
	startd_free(info, sizeof (fork_info_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1155
	return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1156
}