From 4cae04529eda0e482ceaa86b48e532f9c8d35f24 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sun, 21 Jul 2002 14:14:03 -0400 Subject: 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. --- misc/ChangeLog | 7 +++++++ misc/fsck.8.in | 2 ++ misc/fsck.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+) (limited to 'misc') 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 + + * 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 * 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; @@ -467,6 +469,23 @@ static int execute(const char *type, char *device, char *mntpt, return 0; } +/* + * 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; -- cgit v1.2.3