summaryrefslogtreecommitdiff
path: root/misc
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2002-07-21 14:14:03 -0400
committerTheodore Ts'o <tytso@mit.edu>2002-07-21 14:14:03 -0400
commit4cae04529eda0e482ceaa86b48e532f9c8d35f24 (patch)
tree67e9f2fac948b282dde6b0a52138738cec03f43b /misc
parentb7a00563b22b0ea47ddc7117508c0b8e0d65df43 (diff)
downloade2fsprogs-4cae04529eda0e482ceaa86b48e532f9c8d35f24.tar.gz
Add SIGINT and SIGTERM handling to fsck and e2fsck. For e2fsck,
make sure we gracefully clean up and only exit at safe points. For fsck, we pass the SIGINT/SIGTERM signal to the child processes, so they can do their own cleanup.
Diffstat (limited to 'misc')
-rw-r--r--misc/ChangeLog7
-rw-r--r--misc/fsck.8.in2
-rw-r--r--misc/fsck.c56
3 files changed, 65 insertions, 0 deletions
diff --git a/misc/ChangeLog b/misc/ChangeLog
index 6de1398a..0469b719 100644
--- a/misc/ChangeLog
+++ b/misc/ChangeLog
@@ -1,3 +1,10 @@
+2002-07-21 Theodore Ts'o <tytso@mit.edu>
+
+ * fsck.8.in: Document new fsck exit code, FSCK_CANCELED.
+
+ * fsck.c: Trap SIGINT and SIGTERM, and relay it to all of the
+ child fsck processes.
+
2002-07-14 Theodore Ts'o <tytso@mit.edu>
* mke2fs.c (zap_sector): Clear the buffer *after* testing for the
diff --git a/misc/fsck.8.in b/misc/fsck.8.in
index fb205214..fd136ecc 100644
--- a/misc/fsck.8.in
+++ b/misc/fsck.8.in
@@ -49,6 +49,8 @@ is the sum of the following conditions:
.br
\ 16\ \-\ Usage or syntax error
.br
+\ 32\ \-\ Fsck canceled by user request
+.br
\ 128\ \-\ Shared library error
.br
The exit code returned when all file systems are checked using the
diff --git a/misc/fsck.c b/misc/fsck.c
index 8c4499ef..8503eee4 100644
--- a/misc/fsck.c
+++ b/misc/fsck.c
@@ -100,6 +100,8 @@ int progress = 0;
int force_all_parallel = 0;
int num_running = 0;
int max_running = 0;
+volatile int cancel_requested = 0;
+int kill_sent = 0;
char *progname;
char *fstype = NULL;
struct fs_info *filesys_info;
@@ -468,6 +470,23 @@ static int execute(const char *type, char *device, char *mntpt,
}
/*
+ * Send a signal to all outstanding fsck child processes
+ */
+static int kill_all(int signal)
+{
+ struct fsck_instance *inst;
+ int n = 0;
+
+ for (inst = instance_list; inst; inst = inst->next) {
+ if (inst->flags & FLAG_DONE)
+ continue;
+ kill(inst->pid, signal);
+ n++;
+ }
+ return n;
+}
+
+/*
* Wait for one child process to exit; when it does, unlink it from
* the list of executing child processes, and return it.
*/
@@ -502,6 +521,10 @@ static struct fsck_instance *wait_one(int flags)
do {
pid = waitpid(-1, &status, flags);
+ if (cancel_requested && !kill_sent) {
+ kill_all(SIGTERM);
+ kill_sent++;
+ }
if ((pid == 0) && (flags & WNOHANG))
return NULL;
if (pid < 0) {
@@ -908,6 +931,8 @@ static int check_all(NOARGS)
pass_done = 1;
for (fs = filesys_info; fs; fs = fs->next) {
+ if (cancel_requested)
+ break;
if (fs->flags & FLAG_DONE)
continue;
/*
@@ -945,6 +970,8 @@ static int check_all(NOARGS)
break;
}
}
+ if (cancel_requested)
+ break;
if (verbose > 1)
printf(_("--waiting-- (pass %d)\n"), passno);
status |= wait_all(pass_done ? 0 : WNOHANG);
@@ -955,6 +982,10 @@ static int check_all(NOARGS)
} else
not_done_yet++;
}
+ if (cancel_requested && !kill_sent) {
+ kill_all(SIGTERM);
+ kill_sent++;
+ }
status |= wait_all(0);
return status;
}
@@ -966,6 +997,13 @@ static void usage(NOARGS)
exit(EXIT_USAGE);
}
+#ifdef HAVE_SIGNAL_H
+static void signal_cancel(int sig)
+{
+ cancel_requested++;
+}
+#endif
+
static void PRS(int argc, char *argv[])
{
int i, j;
@@ -973,6 +1011,17 @@ static void PRS(int argc, char *argv[])
char options[128];
int opt = 0;
int opts_for_fsck = 0;
+#ifdef HAVE_SIGNAL_H
+ struct sigaction sa;
+
+ /*
+ * Set up signal action
+ */
+ memset(&sa, 0, sizeof(struct sigaction));
+ sa.sa_handler = signal_cancel;
+ sigaction(SIGINT, &sa, 0);
+ sigaction(SIGTERM, &sa, 0);
+#endif
num_devices = 0;
num_args = 0;
@@ -1128,6 +1177,13 @@ int main(int argc, char *argv[])
exit(EXIT_ERROR);
}
for (i = 0 ; i < num_devices; i++) {
+ if (cancel_requested) {
+ if (!kill_sent) {
+ kill_all(SIGTERM);
+ kill_sent++;
+ }
+ break;
+ }
fsck_device(devices[i], interactive);
if (serialize || (num_running >= max_running)) {
struct fsck_instance *inst;