diff options
author | Wayne Davison <wayned@samba.org> | 2006-10-14 19:58:52 +0000 |
---|---|---|
committer | Wayne Davison <wayned@samba.org> | 2006-10-14 19:58:52 +0000 |
commit | 154c345db03bd0c5a93a28373352c9d9363d587b (patch) | |
tree | f8c3b122238e3b9d955f9f12757992c7ebcbad3c /cleanup.c | |
parent | 25f637a334a39448d0ffcdcf20d9917472db8d97 (diff) | |
download | rsync-154c345db03bd0c5a93a28373352c9d9363d587b.tar.gz |
Improved the _exit_cleanup() function to handle potential recursions
back to the function via the calls that it is making. The new code
treats each recursion back into the function as an opportunity to
take up where we left off (skipping whatever step just failed).
Diffstat (limited to 'cleanup.c')
-rw-r--r-- | cleanup.c | 147 |
1 files changed, 96 insertions, 51 deletions
@@ -87,8 +87,6 @@ static pid_t cleanup_pid = 0; pid_t cleanup_child_pid = -1; -int in_exit_cleanup = 0; - /** * Eventually calls exit(), passing @p code, therefore does not return. * @@ -96,69 +94,116 @@ int in_exit_cleanup = 0; **/ NORETURN void _exit_cleanup(int code, const char *file, int line) { - int ocode = code; + static int cleanup_step = 0; + static int exit_code = 0; + static int unmodified_code = 0; SIGACTION(SIGUSR1, SIG_IGN); SIGACTION(SIGUSR2, SIG_IGN); - in_exit_cleanup = 1; + if (exit_code) /* Preserve first error code when recursing. */ + code = exit_code; - if (verbose > 3) { - rprintf(FINFO,"_exit_cleanup(code=%d, file=%s, line=%d): entered\n", - code, file, line); - } + /* Some of our actions might cause a recursive call back here, so we + * keep track of where we are in the cleanup and never repeat a step. */ + switch (cleanup_step) { + case 0: + cleanup_step++; + + exit_code = unmodified_code = code; - if (cleanup_child_pid != -1) { - int status; - if (wait_process(cleanup_child_pid, &status, WNOHANG) == cleanup_child_pid) { - status = WEXITSTATUS(status); - if (status > code) - code = status; + if (verbose > 3) { + rprintf(FINFO, + "_exit_cleanup(code=%d, file=%s, line=%d): entered\n", + code, file, line); } - } - if (cleanup_got_literal && cleanup_fname && cleanup_new_fname - && keep_partial && handle_partial_dir(cleanup_new_fname, PDIR_CREATE)) { - char *fname = cleanup_fname; - cleanup_fname = NULL; - if (cleanup_fd_r != -1) - close(cleanup_fd_r); - if (cleanup_fd_w != -1) { - flush_write_file(cleanup_fd_w); - close(cleanup_fd_w); + /* FALLTHROUGH */ + case 1: + cleanup_step++; + + if (cleanup_child_pid != -1) { + int status; + int pid = wait_process(cleanup_child_pid, &status, WNOHANG); + if (pid == cleanup_child_pid) { + status = WEXITSTATUS(status); + if (status > code) + code = exit_code = status; + } } - finish_transfer(cleanup_new_fname, fname, NULL, - cleanup_file, 0, !partial_dir); - } - io_flush(FULL_FLUSH); - if (cleanup_fname) - do_unlink(cleanup_fname); - if (code) - kill_all(SIGUSR1); - if (cleanup_pid && cleanup_pid == getpid()) { - char *pidf = lp_pid_file(); - if (pidf && *pidf) - unlink(lp_pid_file()); - } - if (code == 0) { - if (io_error & IOERR_DEL_LIMIT) - code = RERR_DEL_LIMIT; - if (io_error & IOERR_VANISHED) - code = RERR_VANISHED; - if (io_error & IOERR_GENERAL || log_got_error) - code = RERR_PARTIAL; - } + /* FALLTHROUGH */ + case 2: + cleanup_step++; + + if (cleanup_got_literal && cleanup_fname && cleanup_new_fname + && keep_partial && handle_partial_dir(cleanup_new_fname, PDIR_CREATE)) { + char *fname = cleanup_fname; + cleanup_fname = NULL; + if (cleanup_fd_r != -1) + close(cleanup_fd_r); + if (cleanup_fd_w != -1) { + flush_write_file(cleanup_fd_w); + close(cleanup_fd_w); + } + finish_transfer(cleanup_new_fname, fname, NULL, + cleanup_file, 0, !partial_dir); + } + + /* FALLTHROUGH */ + case 3: + cleanup_step++; + + io_flush(FULL_FLUSH); + + /* FALLTHROUGH */ + case 4: + cleanup_step++; + + if (cleanup_fname) + do_unlink(cleanup_fname); + if (code) + kill_all(SIGUSR1); + if (cleanup_pid && cleanup_pid == getpid()) { + char *pidf = lp_pid_file(); + if (pidf && *pidf) + unlink(lp_pid_file()); + } + + if (code == 0) { + if (io_error & IOERR_DEL_LIMIT) + code = exit_code = RERR_DEL_LIMIT; + if (io_error & IOERR_VANISHED) + code = exit_code = RERR_VANISHED; + if (io_error & IOERR_GENERAL || log_got_error) + code = exit_code = RERR_PARTIAL; + } + + if (code || am_daemon || (logfile_name && (am_server || !verbose))) + log_exit(code, file, line); + + /* FALLTHROUGH */ + case 5: + cleanup_step++; + + if (verbose > 2) { + rprintf(FINFO, + "_exit_cleanup(code=%d, file=%s, line=%d): " + "about to call exit(%d)\n", + unmodified_code, file, line, code); + } + + /* FALLTHROUGH */ + case 6: + cleanup_step++; - if (code || am_daemon || (logfile_name && (am_server || !verbose))) - log_exit(code, file, line); + close_all(); - if (verbose > 2) { - rprintf(FINFO,"_exit_cleanup(code=%d, file=%s, line=%d): about to call exit(%d)\n", - ocode, file, line, code); + /* FALLTHROUGH */ + default: + break; } - close_all(); exit(code); } |