Subject: Re: bin/21658: interrupting (^C) /etc/rc.d/fsck doesn't stop auto boot
To: None <gnats-bugs@gnats.netbsd.org, netbsd-bugs@netbsd.org>
From: ITOH Yasufumi <itohy@netbsd.org>
List: netbsd-bugs
Date: 05/26/2003 21:51:28
Hm, it seems some signal handlings are needed.
When fsck is running during auto boot, the fsck process
is invoked like this:

sh /etc/rc (handle ^C) - forked sh - /sbin/fsck - /sbin/fsck_ffs (handle ^C)

The forked sh and /sbin/fsck doesn't handle/block/ignore SIGINT,
and if ^C is pressed,

sh /etc/rc (handle ^C) - forked sh - /sbin/fsck - /sbin/fsck_ffs (handle ^C)
        |                   |           |              |
        v                   v           v              v
handle ^C and ignore       die         die        handle ^C and exit 12

Here's suggested diff to add signal handings to the forked sh
and /sbin/fsck.
Do you think this is OK?
I did simple test and this seems working.
-- 
ITOH Yasufumi

Index: etc/rc.d/fsck
===================================================================
RCS file: /cvsroot/src/etc/rc.d/fsck,v
retrieving revision 1.2
diff -u -p -r1.2 fsck
--- etc/rc.d/fsck	2001/06/18 06:42:35	1.2
+++ etc/rc.d/fsck	2003/05/26 11:26:39
@@ -28,8 +28,8 @@ fsck_start()
 	if [ -e /fastboot ]; then
 		echo "Fast boot: skipping disk checks."
 	else
-					# During fsck ignore SIGQUIT
-		trap : 3
+					# During fsck ignore SIGINT and SIGQUIT
+		trap : 2 3
 
 		echo "Starting file system checks:"
 		fsck -p
Index: sbin/fsck/fsck.c
===================================================================
RCS file: /cvsroot/src/sbin/fsck/fsck.c,v
retrieving revision 1.29
diff -u -p -r1.29 fsck.c
--- sbin/fsck/fsck.c	2002/08/23 03:17:18	1.29
+++ sbin/fsck/fsck.c	2003/05/26 11:26:40
@@ -80,8 +80,11 @@ static int maxrun = 0;
 static char *options = NULL;
 static int flags = 0;
 
+int caught_sigint, caught_sigquit;
+
 int main(int, char *[]);
 
+static void sighandler(int);
 static int checkfs(const char *, const char *, const char *, void *, pid_t *);
 static int selected(const char *);
 static void addoption(char *);
@@ -98,7 +101,7 @@ int
 main(int argc, char *argv[])
 {
 	struct fstab *fs;
-	int i, rval = 0;
+	int i, r, rval = 0;
 	const char *vfstype = NULL;
 	char globopt[3];
 
@@ -157,6 +160,11 @@ main(int argc, char *argv[])
 	argc -= optind;
 	argv += optind;
 
+	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+		signal(SIGINT, sighandler);
+	if (flags & CHECK_PREEN && signal(SIGQUIT, SIG_IGN) != SIG_IGN)
+		signal(SIGQUIT, sighandler);
+
 	if (argc == 0)
 		return checkfstab(flags, maxrun, isok, checkfs);
 
@@ -189,13 +197,34 @@ main(int argc, char *argv[])
 				errx(1, "%s has unknown file system type.",
 				    spec);
 		}
+
+		r = checkfs(type, blockcheck(spec), *argv, NULL, NULL);
 
-		rval |= checkfs(type, blockcheck(spec), *argv, NULL, NULL);
+		/* if ^C was pressed, exit 12 immediately */
+		if (r == 12 || caught_sigint)
+			return 12;
+
+		rval |= r;
 	}
 
+	if (rval == 0 && caught_sigquit)
+		rval = 2;
+
 	return rval;
 }
 
+static void
+sighandler(int signo)
+{
+
+	if (signo == SIGINT) {
+		if (++caught_sigint > 2)
+			_exit(12);
+	} else {
+		caught_sigquit = 1;
+	}
+}
+
 
 static void *
 isok(struct fstab *fs)
@@ -486,7 +515,7 @@ mangle(char *opts, int *argcp, const cha
 }
 
 
-const static char *
+static const char *
 getfslab(const char *str)
 {
 	struct disklabel dl;
Index: sbin/fsck/fsutil.h
===================================================================
RCS file: /cvsroot/src/sbin/fsck/fsutil.h,v
retrieving revision 1.7
diff -u -p -r1.7 fsutil.h
--- sbin/fsck/fsutil.h	2001/06/18 06:28:59	1.7
+++ sbin/fsck/fsutil.h	2003/05/26 11:26:40
@@ -55,3 +55,5 @@ char *estrdup(const char *);
 struct fstab;
 int checkfstab(int, int, void *(*)(struct fstab *), 
     int (*) (const char *, const char *, const char *, void *, pid_t *));
+
+extern int caught_sigint, caught_sigquit;
Index: sbin/fsck/preen.c
===================================================================
RCS file: /cvsroot/src/sbin/fsck/preen.c,v
retrieving revision 1.24
diff -u -p -r1.24 preen.c
--- sbin/fsck/preen.c	2002/07/20 08:36:26	1.24
+++ sbin/fsck/preen.c	2003/05/26 11:26:40
@@ -126,6 +126,8 @@ checkfstab(int flags, int maxrun, void *
 
 				if (sumstatus)
 					return (sumstatus);
+				if (caught_sigint)
+					return 12;
 			} else if (passno == 2 && fs->fs_passno > 1) {
 				if (name == NULL) {
 					(void) fprintf(stderr,
@@ -184,7 +186,7 @@ checkfstab(int flags, int maxrun, void *
 				    "%s: %s (%s): EXITED WITH SIGNAL %d\n",
 				    p->p_type, p->p_devname, p->p_mntpt,
 				    WTERMSIG(status));
-				retcode = 8;
+				retcode = (WTERMSIG(status) == SIGINT)? 12 : 8;
 			}
 
 			TAILQ_REMOVE(&d->d_part, p, p_entries);
@@ -192,6 +194,8 @@ checkfstab(int flags, int maxrun, void *
 			if (retcode != 0) {
 				TAILQ_INSERT_TAIL(&badh, p, p_entries);
 				sumstatus |= retcode;
+				if (retcode == 12)
+					caught_sigint = 1;
 			} else {
 				free(p->p_type);
 				free(p->p_devname);
@@ -203,6 +207,11 @@ checkfstab(int flags, int maxrun, void *
 			if (TAILQ_FIRST(&d->d_part) == NULL)
 				ndisks--;
 
+			if (caught_sigint) {
+				sumstatus |= 12;
+				continue; /* interrupted -- no more new task */
+			}
+
 			if (nextdisk == NULL) {
 				if (TAILQ_FIRST(&d->d_part) != NULL) {
 					if ((ret = startdisk(d, checkit)) != 0)
@@ -222,6 +231,8 @@ checkfstab(int flags, int maxrun, void *
 					return ret;
 			}
 		}
+		if (sumstatus == 0 && caught_sigquit)
+			sumstatus = 2;
 	}
 	if (sumstatus) {
 		p = TAILQ_FIRST(&badh);