changeset 14129:790945ad7848

3986 svc.startd dies in getutxent_frec() 3987 svc.startd dies in utmpx_postfork() Reviewed by: Keith Wesolowski <keith.wesolowski@joyent.com> Reviewed by: Robert Mustacchi <rm@joyent.com> Reviewed by: Saso Kiselkov <skiselkov@gmail.com> Approved by: Richard Lowe <richlowe@richlowe.net>
author Bryan Cantrill <bryan@joyent.com>
date Sun, 04 Aug 2013 09:58:38 -0700
parents 615580eeb3d8
children 3159d5f5b16a
files usr/src/cmd/svc/startd/fork.c usr/src/cmd/svc/startd/startd.c usr/src/cmd/svc/startd/startd.h usr/src/cmd/svc/startd/utmpx.c
diffstat 4 files changed, 39 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/svc/startd/fork.c	Thu Aug 08 14:17:55 2013 -0700
+++ b/usr/src/cmd/svc/startd/fork.c	Sun Aug 04 09:58:38 2013 -0700
@@ -25,6 +25,10 @@
  */
 
 /*
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ */
+
+/*
  * fork.c - safe forking for svc.startd
  *
  * fork_configd() and fork_sulogin() are related, special cases that handle the
@@ -72,6 +76,7 @@
 	 * prefork stack
 	 */
 	wait_prefork();
+	utmpx_prefork();
 
 	p = fork1();
 
@@ -81,6 +86,7 @@
 	/*
 	 * postfork stack
 	 */
+	utmpx_postfork();
 	wait_postfork(p);
 
 	return (p);
@@ -169,6 +175,8 @@
 		/* NOTREACHED */
 	}
 
+	utmpx_prefork();
+
 	/*
 	 * Attempt to fork "retries" times.
 	 */
@@ -181,6 +189,7 @@
 			err = errno;
 			(void) ct_tmpl_clear(ctfd);
 			(void) close(ctfd);
+			utmpx_postfork();
 			fork_sulogin(B_TRUE, "Could not fork to start %s: %s\n",
 			    name, strerror(err));
 			/* NOTREACHED */
@@ -188,6 +197,8 @@
 		(void) sleep(tries);
 	}
 
+	utmpx_postfork();
+
 	/*
 	 * Clean up, return pid and ctid.
 	 */
--- a/usr/src/cmd/svc/startd/startd.c	Thu Aug 08 14:17:55 2013 -0700
+++ b/usr/src/cmd/svc/startd/startd.c	Sun Aug 04 09:58:38 2013 -0700
@@ -771,6 +771,11 @@
 		log_framework(LOG_DEBUG, "Existing configd contract %ld; not "
 		    "starting svc.configd\n", configd_ctid);
 
+	/*
+	 * Call utmpx_init() before creating the fork_configd() thread.
+	 */
+	utmpx_init();
+
 	(void) startd_thread_create(fork_configd_thread, (void *)configd_ctid);
 
 	/*
@@ -786,7 +791,6 @@
 	}
 	MUTEX_UNLOCK(&st->st_configd_live_lock);
 
-	utmpx_init();
 	wait_init();
 
 	if (read_startd_config())
--- a/usr/src/cmd/svc/startd/startd.h	Thu Aug 08 14:17:55 2013 -0700
+++ b/usr/src/cmd/svc/startd/startd.h	Sun Aug 04 09:58:38 2013 -0700
@@ -21,6 +21,7 @@
 
 /*
  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
  */
 
 #ifndef	_STARTD_H
@@ -768,6 +769,8 @@
 char utmpx_get_runlevel(void);
 void utmpx_set_runlevel(char, char, boolean_t);
 void utmpx_write_boottime(void);
+void utmpx_prefork(void);
+void utmpx_postfork(void);
 
 /* wait.c */
 void wait_init(void);
--- a/usr/src/cmd/svc/startd/utmpx.c	Thu Aug 08 14:17:55 2013 -0700
+++ b/usr/src/cmd/svc/startd/utmpx.c	Sun Aug 04 09:58:38 2013 -0700
@@ -24,7 +24,9 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
+/*
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ */
 
 /*
  * utmpx.c - utmpx utility routines
@@ -418,3 +420,20 @@
 {
 	(void) pthread_mutex_init(&utmpx_lock, &mutex_attrs);
 }
+
+void
+utmpx_prefork()
+{
+	/*
+	 * The libc utmpx routines are entirely MT-unsafe; we must assure
+	 * that no other thread is in these routines when we fork lest we
+	 * leave the child with inconsistent library state.
+	 */
+	MUTEX_LOCK(&utmpx_lock);
+}
+
+void
+utmpx_postfork()
+{
+	MUTEX_UNLOCK(&utmpx_lock);
+}