summaryrefslogtreecommitdiff
path: root/usr/src/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd')
-rw-r--r--usr/src/cmd/boot/scripts/boot-archive-update.xml8
-rw-r--r--usr/src/cmd/cmd-inet/etc/init.d/pppd15
-rw-r--r--usr/src/cmd/initpkg/rc0.sh11
-rw-r--r--usr/src/cmd/initpkg/shutdown.sh10
-rw-r--r--usr/src/cmd/initpkg/umountall.sh10
-rw-r--r--usr/src/cmd/svc/shell/smf_include.sh33
-rw-r--r--usr/src/cmd/svc/startd/fork.c111
-rw-r--r--usr/src/cmd/svc/startd/graph.c157
-rw-r--r--usr/src/cmd/svc/startd/method.c16
-rw-r--r--usr/src/cmd/svc/startd/startd.h1
10 files changed, 286 insertions, 86 deletions
diff --git a/usr/src/cmd/boot/scripts/boot-archive-update.xml b/usr/src/cmd/boot/scripts/boot-archive-update.xml
index 670a704d94..af20f2b748 100644
--- a/usr/src/cmd/boot/scripts/boot-archive-update.xml
+++ b/usr/src/cmd/boot/scripts/boot-archive-update.xml
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<!--
- Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ Copyright 2009 Sun Microsystems, Inc. All rights reserved.
Use is subject to license terms.
CDDL HEADER START
@@ -23,8 +23,6 @@
CDDL HEADER END
- ident "%Z%%M% %I% %E% SMI"
-
NOTE: This service manifest is not editable; its contents will
be overwritten by package or patch operations, including
operating system upgrade. Make customizations in a different
@@ -60,6 +58,10 @@
when there are many glommed kernels to wad up, a longer timeout is
needed. However if it doesn't finish eventually something up, and
an error message to trigger further investigation is appropriate.
+
+ Please note that a similar timeout exists in startd, which again
+ runs bootadm at the end of shutdown. These timeouts should be
+ adjusted in sync with each other.
-->
<exec_method
type='method'
diff --git a/usr/src/cmd/cmd-inet/etc/init.d/pppd b/usr/src/cmd/cmd-inet/etc/init.d/pppd
index cdb57e62f5..e820e6b15e 100644
--- a/usr/src/cmd/cmd-inet/etc/init.d/pppd
+++ b/usr/src/cmd/cmd-inet/etc/init.d/pppd
@@ -3,9 +3,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
@@ -21,10 +20,9 @@
# CDDL HEADER END
#
#
-# Copyright (c) 2000-2001 by Sun Microsystems, Inc.
-# All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
#
-#ident "%Z%%M% %I% %E% SMI"
PATH=/sbin:/usr/bin:/usr/sbin; export PATH
PPPDIR=/etc/ppp; export PPPDIR
@@ -58,9 +56,8 @@ case "$1" in
;;
'stop')
- /usr/bin/pkill -x pppd
- sleep 1
- /usr/bin/pkill -x pppoed
+ /usr/bin/pkill -z `/sbin/zonename` -x pppd && sleep 1
+ /usr/bin/pkill -z `/sbin/zonename` -x pppoed
# Use ifconfig to make the interfaces down just in case
if [ -f $PPPDIR/ifconfig ]; then
diff --git a/usr/src/cmd/initpkg/rc0.sh b/usr/src/cmd/initpkg/rc0.sh
index 741be2290d..8b1018ad57 100644
--- a/usr/src/cmd/initpkg/rc0.sh
+++ b/usr/src/cmd/initpkg/rc0.sh
@@ -3,9 +3,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
@@ -25,10 +24,9 @@
# All rights reserved.
#
#
-# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-#ident "%Z%%M% %I% %E% SMI"
# "Run Commands" for init states 0, 5 and 6.
@@ -86,6 +84,3 @@ fi
[ -f /etc/.dynamic_routing ] && /usr/bin/rm -f /etc/.dynamic_routing
trap "" 15
-
-[ -x /usr/lib/acct/closewtmp ] && /usr/lib/acct/closewtmp
-/sbin/sync; /sbin/sync; /sbin/sync
diff --git a/usr/src/cmd/initpkg/shutdown.sh b/usr/src/cmd/initpkg/shutdown.sh
index 187e8d679d..e65224c632 100644
--- a/usr/src/cmd/initpkg/shutdown.sh
+++ b/usr/src/cmd/initpkg/shutdown.sh
@@ -3,9 +3,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
#
# CDDL HEADER END
#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T
@@ -28,8 +27,6 @@
-#ident "%Z%%M% %I% %E% SMI"
-
# Sequence performed to change the init state of a machine. Only allows
# transitions to states 0,1,5,6,s,S (i.e.: down or administrative states).
@@ -139,7 +136,6 @@ echo
NODENAME=`uname -n`
-/sbin/sync
cd /
trap "rm $nologin >/dev/null 2>&1 ;exit 1" 1 2 15
diff --git a/usr/src/cmd/initpkg/umountall.sh b/usr/src/cmd/initpkg/umountall.sh
index 25790c2804..e589feebb9 100644
--- a/usr/src/cmd/initpkg/umountall.sh
+++ b/usr/src/cmd/initpkg/umountall.sh
@@ -20,7 +20,7 @@
# CDDL HEADER END
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T
@@ -169,14 +169,6 @@ fi
ZONENAME=`zonename`
-# Check and if needed sync the boot archive before unmounting everything.
-#
-if [ -z "${RFLAG}${NFLAG}${HFLAG}${FSType}" -a "$ZONENAME" = "global" \
- -a -x /sbin/bootadm ] ; then
- /sbin/bootadm -a update_all
-fi
-
-
#
# If we are in deferred activation patching, and the caller is
# svc.startd, then exit without unmounting any of the remaining
diff --git a/usr/src/cmd/svc/shell/smf_include.sh b/usr/src/cmd/svc/shell/smf_include.sh
index 28aa22d701..0253a61ec5 100644
--- a/usr/src/cmd/svc/shell/smf_include.sh
+++ b/usr/src/cmd/svc/shell/smf_include.sh
@@ -20,7 +20,7 @@
# CDDL HEADER END
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -160,6 +160,11 @@ smf_netstrategy () {
# every second until the contract is empty. This will catch
# races between fork(2) and pkill(1).
#
+# Note that time in this routine is tracked (after being input
+# via TIMEOUT) in 10ths of a second. This is because we want
+# to sleep for short periods of time, and expr(1) is too dumb
+# to do non-integer math.
+#
# Returns 1 if the contract is invalid.
# Returns 2 if WAIT is "1", TIMEOUT is > 0, and TIMEOUT expires.
# Returns 0 on success.
@@ -171,6 +176,9 @@ smf_kill_contract() {
[ -z "$time_to_wait" ] && time_to_wait=0
+ # convert to 10ths.
+ time_to_wait=`expr $time_to_wait * 10`
+
# Verify contract id is valid using pgrep
/usr/bin/pgrep -c $1 > /dev/null 2>&1
ret=$?
@@ -195,17 +203,26 @@ smf_kill_contract() {
# If contract does not empty, keep killing the contract to catch
# any child processes missed because they were forking
- /usr/bin/sleep 5
/usr/bin/pgrep -c $1 > /dev/null 2>&1
while [ $? -eq 0 ] ; do
-
- time_waited=`/usr/bin/expr $time_waited + 5`
-
- # Return if TIMEOUT was passed, and it has expired
+ # Return 2 if TIMEOUT was passed, and it has expired
[ "$time_to_wait" -gt 0 -a $time_waited -ge $time_to_wait ] && \
return 2
- /usr/bin/pkill -$2 -c $1
- /usr/bin/sleep 5
+
+ #
+ # At five second intervals, issue the kill again. Note that
+ # the sleep time constant (in tenths) must be a factor of 50
+ # for the remainder trick to work. i.e. sleeping 2 tenths is
+ # fine, but 27 tenths is not.
+ #
+ remainder=`/usr/bin/expr $time_waited % 50`
+ if [ $time_waited -gt 0 -a $remainder -eq 0 ]; then
+ /usr/bin/pkill -$2 -c $1
+ fi
+
+ # Wait two tenths, and go again.
+ /usr/bin/sleep 0.2
+ time_waited=`/usr/bin/expr $time_waited + 2`
/usr/bin/pgrep -c $1 > /dev/null 2>&1
done
diff --git a/usr/src/cmd/svc/startd/fork.c b/usr/src/cmd/svc/startd/fork.c
index 5acbe3f322..f53fce964b 100644
--- a/usr/src/cmd/svc/startd/fork.c
+++ b/usr/src/cmd/svc/startd/fork.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -44,6 +44,7 @@
#include <libcontract_priv.h>
#include <libscf_priv.h>
#include <limits.h>
+#include <poll.h>
#include <port.h>
#include <signal.h>
#include <stdarg.h>
@@ -52,6 +53,7 @@
#include <string.h>
#include <unistd.h>
#include <utmpx.h>
+#include <spawn.h>
#include "configd_exit.h"
#include "protocol.h"
@@ -679,3 +681,110 @@ fork_rc_script(char rl, const char *arg, boolean_t wait)
perror("exec");
exit(0);
}
+
+extern char **environ;
+
+/*
+ * A local variation on system(3c) which accepts a timeout argument. This
+ * allows us to better ensure that the system will actually shut down.
+ *
+ * gracetime specifies an amount of time in seconds which the routine must wait
+ * after the command exits, to allow for asynchronous effects (like sent
+ * signals) to take effect. This can be zero.
+ */
+void
+fork_with_timeout(const char *cmd, uint_t gracetime, uint_t timeout)
+{
+ int err = 0;
+ pid_t pid;
+ char *argv[4];
+ posix_spawnattr_t attr;
+ posix_spawn_file_actions_t factions;
+
+ sigset_t mask, savemask;
+ uint_t msec_timeout;
+ uint_t msec_spent = 0;
+ uint_t msec_gracetime;
+ int status;
+
+ msec_timeout = timeout * 1000;
+ msec_gracetime = gracetime * 1000;
+
+ /*
+ * See also system(3c) in libc. This is very similar, except
+ * that we avoid some unneeded complexity.
+ */
+ err = posix_spawnattr_init(&attr);
+ if (err == 0)
+ err = posix_spawnattr_setflags(&attr,
+ POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF |
+ POSIX_SPAWN_NOSIGCHLD_NP | POSIX_SPAWN_WAITPID_NP |
+ POSIX_SPAWN_NOEXECERR_NP);
+
+ /*
+ * We choose to close fd's above 2, a deviation from system.
+ */
+ if (err == 0)
+ err = posix_spawn_file_actions_init(&factions);
+ if (err == 0)
+ err = posix_spawn_file_actions_addclosefrom_np(&factions,
+ STDERR_FILENO + 1);
+
+ (void) sigemptyset(&mask);
+ (void) sigaddset(&mask, SIGCHLD);
+ (void) thr_sigsetmask(SIG_BLOCK, &mask, &savemask);
+
+ argv[0] = "/bin/sh";
+ argv[1] = "-c";
+ argv[2] = (char *)cmd;
+ argv[3] = NULL;
+
+ if (err == 0)
+ err = posix_spawn(&pid, "/bin/sh", &factions, &attr,
+ (char *const *)argv, (char *const *)environ);
+
+ (void) posix_spawnattr_destroy(&attr);
+ (void) posix_spawn_file_actions_destroy(&factions);
+
+ if (err) {
+ uu_warn("Failed to spawn %s: %s\n", cmd, strerror(err));
+ } else {
+ for (;;) {
+ int w;
+ w = waitpid(pid, &status, WNOHANG);
+ if (w == -1 && errno != EINTR)
+ break;
+ if (w > 0) {
+ /*
+ * Command succeeded, so give it gracetime
+ * seconds for it to have an effect.
+ */
+ if (status == 0 && msec_gracetime != 0)
+ (void) poll(NULL, 0, msec_gracetime);
+ break;
+ }
+
+ (void) poll(NULL, 0, 100);
+ msec_spent += 100;
+ /*
+ * If we timed out, kill off the process, then try to
+ * wait for it-- it's possible that we could accumulate
+ * a zombie here since we don't allow waitpid to hang,
+ * but it's better to let that happen and continue to
+ * make progress.
+ */
+ if (msec_spent >= msec_timeout) {
+ uu_warn("'%s' timed out after %d "
+ "seconds. Killing.\n", cmd,
+ timeout);
+ (void) kill(pid, SIGTERM);
+ (void) poll(NULL, 0, 100);
+ (void) kill(pid, SIGKILL);
+ (void) poll(NULL, 0, 100);
+ (void) waitpid(pid, &status, WNOHANG);
+ break;
+ }
+ }
+ }
+ (void) thr_sigsetmask(SIG_BLOCK, &savemask, NULL);
+}
diff --git a/usr/src/cmd/svc/startd/graph.c b/usr/src/cmd/svc/startd/graph.c
index fe17f6c4fc..455b14ab0c 100644
--- a/usr/src/cmd/svc/startd/graph.c
+++ b/usr/src/cmd/svc/startd/graph.c
@@ -178,6 +178,11 @@ static boolean_t go_single_user_mode = B_FALSE;
static boolean_t go_to_level1 = B_FALSE;
/*
+ * Tracks when we started halting.
+ */
+static time_t halting_time = 0;
+
+/*
* This tracks the legacy runlevel to ensure we signal init and manage
* utmpx entries correctly.
*/
@@ -3441,11 +3446,44 @@ out:
return (0);
}
+
+static void
+kill_user_procs(void)
+{
+ (void) fputs("svc.startd: Killing user processes.\n", stdout);
+
+ /*
+ * Despite its name, killall's role is to get select user processes--
+ * basically those representing terminal-based logins-- to die. Victims
+ * are located by killall in the utmp database. Since these are most
+ * often shell based logins, and many shells mask SIGTERM (but are
+ * responsive to SIGHUP) we first HUP and then shortly thereafter
+ * kill -9.
+ */
+ (void) fork_with_timeout("/usr/sbin/killall HUP", 1, 5);
+ (void) fork_with_timeout("/usr/sbin/killall KILL", 1, 5);
+
+ /*
+ * Note the selection of user id's 0, 1 and 15, subsequently
+ * inverted by -v. 15 is reserved for dladmd. Yes, this is a
+ * kludge-- a better policy is needed.
+ *
+ * Note that fork_with_timeout will only wait out the 1 second
+ * "grace time" if pkill actually returns 0. So if there are
+ * no matches, this will run to completion much more quickly.
+ */
+ (void) fork_with_timeout("/usr/bin/pkill -TERM -v -u 0,1,15", 1, 5);
+ (void) fork_with_timeout("/usr/bin/pkill -KILL -v -u 0,1,15", 1, 5);
+}
+
static void
do_uadmin(void)
{
- int fd, left;
+ int fd;
struct statvfs vfs;
+ time_t now;
+ struct tm nowtm;
+ char down_buf[256], time_buf[256];
const char * const resetting = "/etc/svc/volatile/resetting";
@@ -3458,30 +3496,87 @@ do_uadmin(void)
/* Kill dhcpagent if we're not using nfs for root */
if ((statvfs("/", &vfs) == 0) &&
(strncmp(vfs.f_basetype, "nfs", sizeof ("nfs") - 1) != 0))
- (void) system("/usr/bin/pkill -x -u 0 dhcpagent");
+ fork_with_timeout("/usr/bin/pkill -x -u 0 dhcpagent", 0, 5);
- (void) system("/usr/sbin/killall");
- left = 5;
- while (left > 0)
- left = sleep(left);
+ /*
+ * Call sync(2) now, before we kill off user processes. This takes
+ * advantage of the several seconds of pause we have before the
+ * killalls are done. Time we can make good use of to get pages
+ * moving out to disk.
+ *
+ * Inside non-global zones, we don't bother, and it's better not to
+ * anyway, since sync(2) can have system-wide impact.
+ */
+ if (getzoneid() == 0)
+ sync();
- (void) system("/usr/sbin/killall 9");
- left = 10;
- while (left > 0)
- left = sleep(left);
+ kill_user_procs();
+
+ /*
+ * Note that this must come after the killing of user procs, since
+ * killall relies on utmpx, and this command affects the contents of
+ * said file.
+ */
+ if (access("/usr/lib/acct/closewtmp", X_OK) == 0)
+ fork_with_timeout("/usr/lib/acct/closewtmp", 0, 5);
- sync();
- sync();
- sync();
+ /*
+ * For patches which may be installed as the system is shutting
+ * down, we need to ensure, one more time, that the boot archive
+ * really is up to date.
+ */
+ if (getzoneid() == 0 && access("/usr/sbin/bootadm", X_OK) == 0)
+ fork_with_timeout("/usr/sbin/bootadm -ea update_all", 0, 3600);
- (void) system("/sbin/umountall -l");
- (void) system("/sbin/umount /tmp >/dev/null 2>&1");
- (void) system("/sbin/umount /var/adm >/dev/null 2>&1");
- (void) system("/sbin/umount /var/run >/dev/null 2>&1");
- (void) system("/sbin/umount /var >/dev/null 2>&1");
- (void) system("/sbin/umount /usr >/dev/null 2>&1");
+ fork_with_timeout("/sbin/umountall -l", 0, 5);
+ fork_with_timeout("/sbin/umount /tmp /var/adm /var/run /var "
+ ">/dev/null 2>&1", 0, 5);
+
+ /*
+ * Try to get to consistency for whatever UFS filesystems are left.
+ * This is pretty expensive, so we save it for the end in the hopes of
+ * minimizing what it must do. The other option would be to start in
+ * parallel with the killall's, but lockfs tends to throw out much more
+ * than is needed, and so subsequent commands (like umountall) take a
+ * long time to get going again.
+ *
+ * Inside of zones, we don't bother, since we're not about to terminate
+ * the whole OS instance.
+ *
+ * On systems using only ZFS, this call to lockfs -fa is a no-op.
+ */
+ if (getzoneid() == 0) {
+ if (access("/usr/sbin/lockfs", X_OK) == 0)
+ fork_with_timeout("/usr/sbin/lockfs -fa", 0, 30);
- uu_warn("The system is down.\n");
+ sync(); /* once more, with feeling */
+ }
+
+ fork_with_timeout("/sbin/umount /usr >/dev/null 2>&1", 0, 5);
+
+ /*
+ * Construct and emit the last words from userland:
+ * "<timestamp> The system is down. Shutdown took <N> seconds."
+ *
+ * Normally we'd use syslog, but with /var and other things
+ * potentially gone, try to minimize the external dependencies.
+ */
+ now = time(NULL);
+ (void) localtime_r(&now, &nowtm);
+
+ if (strftime(down_buf, sizeof (down_buf),
+ "%b %e %T The system is down.", &nowtm) == 0) {
+ (void) strlcpy(down_buf, "The system is down.",
+ sizeof (down_buf));
+ }
+
+ if (halting_time != 0 && halting_time <= now) {
+ (void) snprintf(time_buf, sizeof (time_buf),
+ " Shutdown took %lu seconds.", now - halting_time);
+ } else {
+ time_buf[0] = '\0';
+ }
+ (void) printf("%s%s\n", down_buf, time_buf);
(void) uadmin(A_SHUTDOWN, halting, NULL);
uu_warn("uadmin() failed");
@@ -3681,23 +3776,8 @@ single_user_thread(void *unused)
MUTEX_LOCK(&single_user_thread_lock);
single_user_thread_count++;
- if (!booting_to_single_user) {
- /*
- * From rcS.sh: Look for ttymon, in.telnetd, in.rlogind and
- * processes in their process groups so they can be terminated.
- */
- (void) fputs("svc.startd: Killing user processes: ", stdout);
- (void) system("/usr/sbin/killall");
- (void) system("/usr/sbin/killall 9");
- (void) system("/usr/bin/pkill -TERM -v -u 0,1");
-
- left = 5;
- while (left > 0)
- left = sleep(left);
-
- (void) system("/usr/bin/pkill -KILL -v -u 0,1");
- (void) puts("done.");
- }
+ if (!booting_to_single_user)
+ kill_user_procs();
if (go_single_user_mode || booting_to_single_user) {
msg = "SINGLE USER MODE\n";
@@ -4972,16 +5052,19 @@ dgraph_set_runlevel(scf_propertygroup_t *pg, scf_property_t *prop)
break;
case '0':
+ halting_time = time(NULL);
fork_rc_script(rl, stop, B_TRUE);
halting = AD_HALT;
goto uadmin;
case '5':
+ halting_time = time(NULL);
fork_rc_script(rl, stop, B_TRUE);
halting = AD_POWEROFF;
goto uadmin;
case '6':
+ halting_time = time(NULL);
fork_rc_script(rl, stop, B_TRUE);
halting = AD_BOOT;
goto uadmin;
diff --git a/usr/src/cmd/svc/startd/method.c b/usr/src/cmd/svc/startd/method.c
index 3b83fdc418..ed538c3c3a 100644
--- a/usr/src/cmd/svc/startd/method.c
+++ b/usr/src/cmd/svc/startd/method.c
@@ -19,12 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* method.c - method execution functions
*
@@ -955,13 +953,23 @@ assured_kill:
*/
if (type == METHOD_STOP && (!instance_is_transient_style(inst)) &&
!(contract_is_empty(inst->ri_i.i_primary_ctid))) {
+ int times = 0;
if (timeout != METHOD_TIMEOUT_INFINITE)
timeout_insert(inst, inst->ri_i.i_primary_ctid,
timeout);
for (;;) {
- (void) poll(NULL, 0, 100);
+ /*
+ * Check frequently at first, then back off. This
+ * keeps startd from idling while shutting down.
+ */
+ if (times < 20) {
+ (void) poll(NULL, 0, 5);
+ times++;
+ } else {
+ (void) poll(NULL, 0, 100);
+ }
if (contract_is_empty(inst->ri_i.i_primary_ctid))
break;
}
diff --git a/usr/src/cmd/svc/startd/startd.h b/usr/src/cmd/svc/startd/startd.h
index 8cc61dd830..3bf401723a 100644
--- a/usr/src/cmd/svc/startd/startd.h
+++ b/usr/src/cmd/svc/startd/startd.h
@@ -588,6 +588,7 @@ void fork_rc_script(char, const char *, boolean_t);
void *fork_configd_thread(void *);
pid_t startd_fork1(int *);
+void fork_with_timeout(const char *, uint_t, uint_t);
/* graph.c */
void graph_init(void);