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