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