Bug 38854 - sysinstall(8): resetting during setup causes the target installation path to change from "/mnt" (new root partition) to "/" (the memory disk)
Summary: sysinstall(8): resetting during setup causes the target installation path to ...
Status: Closed Overcome By Events
Alias: None
Product: Base System
Classification: Unclassified
Component: bin (show other bugs)
Version: Unspecified
Hardware: Any Any
: Normal Affects Only Me
Assignee: freebsd-sysinstall (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2002-06-03 15:00 UTC by Peter Sedeffow
Modified: 2015-11-10 09:12 UTC (History)
0 users

See Also:


Attachments
bin.38854.patch (3.77 KB, patch)
2010-11-23 07:08 UTC, Garrett Cooper
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Peter Sedeffow 2002-06-03 15:00:02 UTC
After sysintall has initialized, sliced the disks and asked for mount points of the partitions, pressing Ctrl-C brings up the option to restart sysinstall. After restarting sysinstall, the target installation path changes from /mnt (the newly created "/" mount pount) to the actuall "/" which is amemory disk device, causing the setup to give errors of unsufficient disk space as the system tries to install the distributions on the memory disk.

How-To-Repeat: boot from setup media, chose standard setup, slice and partiton disks, mount, press Ctrl-C , choose restart setup program, repeat slicing and aprtitoning again, choses distributions and proceed to copying.
Comment 1 Kris Kennaway freebsd_committer freebsd_triage 2003-07-18 23:55:26 UTC
Responsible Changed
From-To: freebsd-bugs->qa

Assign to qa group
Comment 2 Bruce Cran freebsd_committer freebsd_triage 2010-03-13 11:54:37 UTC
Responsible Changed
From-To: freebsd-bugs->brucec

Take.
Comment 3 dfilter service freebsd_committer freebsd_triage 2010-08-17 10:39:21 UTC
Author: brucec
Date: Tue Aug 17 09:39:06 2010
New Revision: 211417
URL: http://svn.freebsd.org/changeset/base/211417

Log:
  To restart, sysinstall calls execl. Since it will create a new process, we
  can't check to see if sysinstall is running as init just by checking if the
  PID is 0. Introduce a new option that sets the RunningAsInit flag, and update
  the code to check RunningAsInit intstead of getpid().
  
  PR:	bin/38854
  Submitted by:	Peter Sedeffow <peter at trumanbrewery.com>
  Approved by:	rrs (mentor)
  MFC after:	1 month

Modified:
  head/usr.sbin/sysinstall/globals.c
  head/usr.sbin/sysinstall/install.c
  head/usr.sbin/sysinstall/main.c
  head/usr.sbin/sysinstall/msg.c
  head/usr.sbin/sysinstall/system.c
  head/usr.sbin/sysinstall/termcap.c

Modified: head/usr.sbin/sysinstall/globals.c
==============================================================================
--- head/usr.sbin/sysinstall/globals.c	Tue Aug 17 09:13:26 2010	(r211416)
+++ head/usr.sbin/sysinstall/globals.c	Tue Aug 17 09:39:06 2010	(r211417)
@@ -76,13 +76,10 @@ globalsInit(void)
 {
     DebugFD = -1;
     ColorDisplay = FALSE;
-    Fake = FALSE;
-    Restarting = FALSE;
     OnVTY = FALSE;
     DialogActive = FALSE;
     VarHead = NULL;
     mediaDevice = NULL;
-    RunningAsInit = FALSE;
 
     HomeChunk = NULL;
     RootChunk = NULL;

Modified: head/usr.sbin/sysinstall/install.c
==============================================================================
--- head/usr.sbin/sysinstall/install.c	Tue Aug 17 09:13:26 2010	(r211416)
+++ head/usr.sbin/sysinstall/install.c	Tue Aug 17 09:39:06 2010	(r211417)
@@ -1274,7 +1274,7 @@ installVarDefaults(dialogMenuItem *self)
 	    variable_set2(VAR_FIXIT_TTY,		"serial", 0);
     variable_set2(VAR_PKG_TMPDIR,		"/var/tmp", 0);
     variable_set2(VAR_MEDIA_TIMEOUT,		itoa(MEDIA_TIMEOUT), 0);
-    if (getpid() != 1)
+    if (!RunningAsInit)
 	variable_set2(SYSTEM_STATE,		"update", 0);
     else
 	variable_set2(SYSTEM_STATE,		"init", 0);

Modified: head/usr.sbin/sysinstall/main.c
==============================================================================
--- head/usr.sbin/sysinstall/main.c	Tue Aug 17 09:13:26 2010	(r211416)
+++ head/usr.sbin/sysinstall/main.c	Tue Aug 17 09:39:06 2010	(r211417)
@@ -56,12 +56,42 @@ main(int argc, char **argv)
     int choice, scroll, curr, max, status;
     char titlestr[80], *arch, *osrel, *ostype;
     struct rlimit rlim;
-    
+    char *arg;
+    int i;
+    int optionArgs = 0;
+
     /* Record name to be able to restart */
     StartName = argv[0];
 
+    Restarting = FALSE;
+    RunningAsInit = FALSE;
+    Fake = FALSE;
+
+    for (i = 1; i < argc; i++) {
+	arg = argv[i];
+
+	if (arg[0] != '-')
+		break;
+
+	optionArgs++;
+
+	if (!strcmp(arg, "-fake")) {
+		variable_set2(VAR_DEBUG, "YES", 0);
+		Fake = TRUE;
+	} else if (!strcmp(arg, "-restart")) {
+		Restarting = TRUE;
+	} else if (!strcmp(arg, "-fakeInit")) {
+		RunningAsInit = TRUE;
+	}
+	
+	arg = argv[optionArgs+1];
+    }
+
+    if (getpid() == 1)
+	    RunningAsInit = TRUE;
+   
     /* Catch fatal signals and complain about them if running as init */
-    if (getpid() == 1) {
+    if (RunningAsInit) {
 	signal(SIGBUS, screech);
 	signal(SIGSEGV, screech);
     }
@@ -105,13 +135,8 @@ main(int argc, char **argv)
     if (!RunningAsInit)
 	installEnvironment();
 
-    if (argc > 1 && !strcmp(argv[1], "-fake")) {
-	variable_set2(VAR_DEBUG, "YES", 0);
-	Fake = TRUE;
+    if (Fake)
 	msgConfirm("I'll be just faking it from here on out, OK?");
-    }
-    if (argc > 1 && !strcmp(argv[1], "-restart"))
-	Restarting = TRUE;
 
     /* Try to preserve our scroll-back buffer */
     if (OnVTY) {
@@ -140,19 +165,14 @@ main(int argc, char **argv)
 
     /* First, see if we have any arguments to process (and argv[0] counts if it's not "sysinstall") */
     if (!RunningAsInit) {
-	int i, start_arg;
-
-	if (!strstr(argv[0], "sysinstall"))
-	    start_arg = 0;
-	else if (Fake || Restarting)
-	    start_arg = 2;
-	else
-	    start_arg = 1;
-	for (i = start_arg; i < argc; i++) {
+	for (i = optionArgs+1; i < argc; i++) {
 	    if (DITEM_STATUS(dispatchCommand(argv[i])) != DITEM_SUCCESS)
 		systemShutdown(1);
 	}
-	if (argc > start_arg)
+
+	/* If we were given commands to process on the command line, just exit
+	 * now */
+	if (argc > optionArgs+1)
 	    systemShutdown(0);
     }
     else
@@ -187,7 +207,7 @@ main(int argc, char **argv)
     while (1) {
 	choice = scroll = curr = max = 0;
 	dmenuOpen(&MenuInitial, &choice, &scroll, &curr, &max, TRUE);
-	if (getpid() != 1
+	if (!RunningAsInit
 #if defined(__sparc64__)
 	    || !msgNoYes("Are you sure you wish to exit?  The system will halt.")
 #else

Modified: head/usr.sbin/sysinstall/msg.c
==============================================================================
--- head/usr.sbin/sysinstall/msg.c	Tue Aug 17 09:13:26 2010	(r211416)
+++ head/usr.sbin/sysinstall/msg.c	Tue Aug 17 09:39:06 2010	(r211417)
@@ -233,7 +233,7 @@ msgFatal(char *fmt, ...)
     mvaddstr(StatusLine, 0, errstr);
     addstr(" - ");
     addstr("PRESS ANY KEY TO ");
-    if (getpid() == 1)
+    if (RunningAsInit)
 	addstr("REBOOT");
     else
 	addstr("QUIT");

Modified: head/usr.sbin/sysinstall/system.c
==============================================================================
--- head/usr.sbin/sysinstall/system.c	Tue Aug 17 09:13:26 2010	(r211416)
+++ head/usr.sbin/sysinstall/system.c	Tue Aug 17 09:39:06 2010	(r211417)
@@ -59,13 +59,20 @@ static int
 intr_restart(dialogMenuItem *self)
 {
     int ret, fd, fdmax;
+    char *arg;
 
     mediaClose();
     free_variables();
     fdmax = getdtablesize();
     for (fd = 3; fd < fdmax; fd++)
 	close(fd);
-    ret = execl(StartName, StartName, "-restart", (char *)NULL);
+    
+    if (RunningAsInit)
+	    arg = "-restart -fakeInit";
+    else
+	    arg = "-restart";
+
+    ret = execl(StartName, StartName, arg, NULL);
     msgDebug("execl failed (%s)\n", strerror(errno));
     /* NOTREACHED */
     return -1;
@@ -148,11 +155,10 @@ systemInitialize(int argc, char **argv)
 	variable_set2(VAR_DEBUG, "YES", 0);
 
     /* Are we running as init? */
-    if (getpid() == 1) {
+    if (RunningAsInit) {
 	struct ufs_args ufs_args;
 	int fd;
 
-	RunningAsInit = 1;
 	setsid();
 	close(0);
 	fd = open("/dev/ttyv0", O_RDWR);

Modified: head/usr.sbin/sysinstall/termcap.c
==============================================================================
--- head/usr.sbin/sysinstall/termcap.c	Tue Aug 17 09:13:26 2010	(r211416)
+++ head/usr.sbin/sysinstall/termcap.c	Tue Aug 17 09:39:06 2010	(r211417)
@@ -105,7 +105,7 @@ set_termcap(void)
     else {
 	int i, on;
 
-	if (getpid() == 1) {
+	if (RunningAsInit) {
 	    DebugFD = open("/dev/ttyv1", O_WRONLY);
 	    if (DebugFD != -1) {
 		on = 1;
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Comment 4 Bruce Cran freebsd_committer freebsd_triage 2010-08-17 10:51:42 UTC
State Changed
From-To: open->patched

Fixed in r211417.
Comment 5 Bruce Cran freebsd_committer freebsd_triage 2010-08-17 12:50:10 UTC
State Changed
From-To: patched->open

The patch I committed was a no-op because execl doesn't change the PID.
Comment 6 Garrett Cooper 2010-11-23 07:08:10 UTC
Hi,
    I prototyped up a solution for this issue by banking on the fact
that the *fork(2) system calls actually do a copy on write of several
process variables, including the current working directory, etc.
Example:

$ ./test_forking_and_chdiring
[0] getwd = /tmp
[1] getwd = /usr/home/gcooper
[2] getwd = /tmp
[3] getwd = /usr/home/gcooper

    So at least now sysinstall is starting from a sane state
consistently, instead of just reexecuting itself via system(3) with
-fakeInit and -restart (ugh). I was concerned about sysinstall closing
file descriptors on exec, etc, but this appears to be mostly baseless.
Cleaning up these dead options should be done in later commits.
    I executed sysinstall from the command line in multiuser given the
following 4 scenarios:
    1. Exit (exit code was 0).
    2. ^C:
        a. Continue (process continued as usual).
        b. Restart (process `restarted' by continuing on in the loop
again -- it was rather amusing when I discovered that it reexecutes
itself and can essentially overload the stack eventually if it gets
into an infinite loop :/).
        c. Abort (process exited with 1 as I designed it to).
    There might be some corner cases with usage, but this focuses on
the primary areas. I was hoping to use vfork(2) (because it would have
made the logic a bit simpler, but unfortunately vfork isn't isolated
enough to do proper signal handling with SIGINT (I think that the
parent process and the child process share the same signal vectors,
but I could be wrong... I should look).
    Ideally sysinstall should be run from a custom /etc/rc script that
sets up all of these variables and ensures that the sysinstall process
is playing by the rules, but that's something else that needs to be
resolved down the line for this particular issue. This is just a quick
and dirty stopgap fix.
    Credit goes to Gavin for pointing me to this annoying problem :).
Thanks,
-Garrett

#include <sys/types.h>
#include <sys/wait.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int
main(void)
{
	int status;

	switch (fork()) {
	case -1:
		err(1, "fork");
	case 0:
		if (chdir("/tmp") == -1)
			err(1, "chroot");
		printf("[0] getwd = %s\n", getwd(NULL));
		exit(0);
	default:
		if (wait(&status) == -1)
			err(1, "wait");
		else if (status)
			errx(1, "exit status != 0");
	}
	printf("[1] getwd = %s\n", getwd(NULL));
	switch (vfork()) {
	case -1:
		err(1, "vfork");
	case 0:
		if (chdir("/tmp") == -1)
			err(1, "chroot");
		printf("[2] getwd = %s\n", getwd(NULL));
		exit(0);
	default:
		if (wait(&status) == -1)
			err(1, "wait");
		else if (status)
			errx(1, "exit status != 0");
	}
	printf("[3] getwd = %s\n", getwd(NULL));

	exit(0);
}
Comment 7 Bruce Cran freebsd_committer freebsd_triage 2011-01-23 21:07:43 UTC
Responsible Changed
From-To: brucec->freebsd-sysinstall

Back to the pool.
Comment 8 Enji Cooper freebsd_committer freebsd_triage 2015-11-10 09:07:34 UTC
sysinstall has been replaced by bsdinstall in FreeBSD 9.x. Closing.
Comment 9 Enji Cooper freebsd_committer freebsd_triage 2015-11-10 09:12:18 UTC
sysinstall has been replaced by bsdinstall in FreeBSD 9.x. Closing.