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