summaryrefslogtreecommitdiff
path: root/misc/fsck.c
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/fsck.c
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/fsck.c')
-rw-r--r--misc/fsck.c56
1 files changed, 56 insertions, 0 deletions
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;