changeset 2949:5581081d0989

6481326 lx zone install sometimes hangs
author nn35248
date Fri, 20 Oct 2006 07:07:59 -0700
parents c89bd1dbe6d0
children 449abdd74783
files usr/src/lib/brand/lx/lx_brand/common/clone.c usr/src/lib/brand/lx/lx_brand/common/fork.c usr/src/lib/brand/lx/lx_brand/common/lx_brand.c usr/src/lib/brand/lx/lx_brand/sys/lx_misc.h
diffstat 4 files changed, 32 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/lib/brand/lx/lx_brand/common/clone.c	Thu Oct 19 21:21:08 2006 -0700
+++ b/usr/src/lib/brand/lx/lx_brand/common/clone.c	Fri Oct 20 07:07:59 2006 -0700
@@ -395,6 +395,8 @@
 				is_vforked--;
 		} else {
 			rval = fork1();
+			if (rval == 0 && lx_is_rpm)
+				sleep(lx_rpm_delay);
 		}
 
 		if (rval > 0 && (flags & LX_CLONE_PARENT_SETTID))
--- a/usr/src/lib/brand/lx/lx_brand/common/fork.c	Thu Oct 19 21:21:08 2006 -0700
+++ b/usr/src/lib/brand/lx/lx_brand/common/fork.c	Fri Oct 20 07:07:59 2006 -0700
@@ -43,6 +43,9 @@
 {
 	int ret = fork1();
 
+	if (ret == 0 && lx_is_rpm)
+		sleep(lx_rpm_delay);
+
 	return (ret == -1 ? -errno : ret);
 }
 
--- a/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c	Thu Oct 19 21:21:08 2006 -0700
+++ b/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c	Fri Oct 20 07:07:59 2006 -0700
@@ -51,6 +51,7 @@
 #include <fcntl.h>
 #include <synch.h>
 #include <libelf.h>
+#include <libgen.h>
 #include <pthread.h>
 #include <utime.h>
 #include <dirent.h>
@@ -169,6 +170,8 @@
 static uintptr_t stack_bottom;
 
 int lx_install = 0;		/* install mode enabled if non-zero */
+boolean_t lx_is_rpm = B_FALSE;
+int lx_rpm_delay = 1;
 int lx_strict = 0;		/* "strict" mode enabled if non-zero */
 int lx_verbose = 0;		/* verbose mode enabled if non-zero */
 int lx_debug_enabled = 0;	/* debugging output enabled if non-zero */
@@ -693,6 +696,24 @@
 	lx_debug("branding myself and setting handler to 0x%p",
 	    (void *)lx_handler_table);
 
+	/*
+	 * The version of rpm that ships with CentOS/RHEL 3.x has a race
+	 * condition in it.  If it creates a child process to run a
+	 * post-install script, and that child process completes too
+	 * quickly, it will disappear before the parent notices.  This
+	 * causes the parent to hang forever waiting for the already dead
+	 * child to die.  I'm sure there's a Lazarus joke buried in here
+	 * somewhere.
+	 *
+	 * Anyway, as a workaround, we make every child of an 'rpm' process
+	 * sleep for 1 second, giving the parent a chance to enter its
+	 * wait-for-the-child-to-die loop.  Thay may be the hackiest trick
+	 * in all of our Linux emulation code - and that's saying
+	 * something.
+	 */
+	if (strcmp("rpm", basename(argv[0])) == NULL)
+		lx_is_rpm = B_TRUE;
+
 	reg.lxbr_version = LX_VERSION;
 	reg.lxbr_handler = (void *)&lx_handler_table;
 	reg.lxbr_tracehandler = (void *)&lx_handler_trace_table;
--- a/usr/src/lib/brand/lx/lx_brand/sys/lx_misc.h	Thu Oct 19 21:21:08 2006 -0700
+++ b/usr/src/lib/brand/lx/lx_brand/sys/lx_misc.h	Fri Oct 20 07:07:59 2006 -0700
@@ -45,6 +45,12 @@
 extern pid_t zoneinit_pid;
 
 /*
+ * Support for the unfortunate RPM race condition workaround.
+ */
+extern int lx_rpm_delay;
+extern boolean_t lx_is_rpm;
+
+/*
  * Values Linux expects for init
  */
 #define	LX_INIT_PGID	0