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);