@@ -662,6 +662,8 @@ drive_dumpstream_loader(svn_stream_t *stream,
const svn_repos_parse_fns2_t *parser,
void *parse_baton,
svn_ra_session_t *session,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
apr_pool_t *pool)
{
struct parse_baton *pb = parse_baton;
@@ -676,7 +678,7 @@ drive_dumpstream_loader(svn_stream_t *stream,
SVN_ERR(get_lock(&lock_string, session, pool));
SVN_ERR(svn_ra_get_repos_root2(session, &(pb->root_url), pool));
SVN_ERR(svn_repos_parse_dumpstream2(stream, parser, parse_baton,
- NULL, NULL, pool));
+ cancel_func, cancel_baton, pool));
err = svn_ra_change_rev_prop2(session, 0, SVNRDUMP_PROP_LOCK,
be_atomic ? &lock_string : NULL, NULL, pool);
if (is_atomicity_error(err))
@@ -104,13 +104,17 @@ get_dumpstream_loader(const svn_repos_parse_fns2_t **parser,
* Drive the dumpstream loader described by @a parser and @a
* parse_baton to parse and commit the stream @a stream to the
* location described by @a session. Use @a pool for all memory
- * allocations.
+ * allocations. Use @a cancel_func and @a cancel_baton to check for
+ * user cancellation of the operation (for timely-but-safe
+ * termination).
*/
svn_error_t *
drive_dumpstream_loader(svn_stream_t *stream,
const svn_repos_parse_fns2_t *parser,
void *parse_baton,
svn_ra_session_t *session,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
apr_pool_t *pool);
#endif
* ====================================================================
*/
+#include <apr_signal.h>
+
#include "svn_pools.h"
#include "svn_cmdline.h"
#include "svn_client.h"
#include "private/svn_cmdline_private.h"
+
+\f
+/*** Cancellation ***/
+
+/* A flag to see if we've been cancelled by the client or not. */
+static volatile sig_atomic_t cancelled = FALSE;
+
+/* A signal handler to support cancellation. */
+static void
+signal_handler(int signum)
+{
+ apr_signal(signum, SIG_IGN);
+ cancelled = TRUE;
+}
+
+/* Our cancellation callback. */
+static svn_error_t *
+check_cancel(void *baton)
+{
+ if (cancelled)
+ return svn_error_create(SVN_ERR_CANCELLED, NULL, _("Caught signal"));
+ else
+ return SVN_NO_ERROR;
+}
+
+
+\f
+
static svn_opt_subcommand_t dump_cmd, load_cmd;
enum svn_svnrdump__longopt_t
@@ -228,6 +258,9 @@ open_connection(svn_ra_session_t **session,
cfg_config = apr_hash_get(ctx->config, SVN_CONFIG_CATEGORY_CONFIG,
APR_HASH_KEY_STRING);
+ /* Set up our cancellation support. */
+ ctx->cancel_func = check_cancel;
+
/* Default authentication providers for non-interactive use */
SVN_ERR(svn_cmdline_create_auth_baton(&(ctx->auth_baton), non_interactive,
username, password, config_dir,
@@ -260,7 +293,8 @@ replay_revisions(svn_ra_session_t *session,
SVN_ERR(svn_stream_for_stdout(&stdout_stream, pool));
- SVN_ERR(get_dump_editor(&dump_editor, &dump_baton, stdout_stream, pool));
+ SVN_ERR(get_dump_editor(&dump_editor, &dump_baton, stdout_stream,
+ check_cancel, NULL, pool));
replay_baton = apr_pcalloc(pool, sizeof(*replay_baton));
replay_baton->editor = dump_editor;
@@ -342,7 +376,7 @@ load_revisions(svn_ra_session_t *session,
SVN_ERR(get_dumpstream_loader(&parser, &parse_baton, session, pool));
SVN_ERR(drive_dumpstream_loader(stdin_stream, parser, parse_baton,
- session, pool));
+ session, check_cancel, NULL, pool));
svn_stream_close(stdin_stream);
@@ -478,6 +512,29 @@ main(int argc, const char **argv)
os->interleave = TRUE; /* Options and arguments can be interleaved */
+ /* Set up our cancellation support. */
+ apr_signal(SIGINT, signal_handler);
+#ifdef SIGBREAK
+ /* SIGBREAK is a Win32 specific signal generated by ctrl-break. */
+ apr_signal(SIGBREAK, signal_handler);
+#endif
+#ifdef SIGHUP
+ apr_signal(SIGHUP, signal_handler);
+#endif
+#ifdef SIGTERM
+ apr_signal(SIGTERM, signal_handler);
+#endif
+#ifdef SIGPIPE
+ /* Disable SIGPIPE generation for the platforms that have it. */
+ apr_signal(SIGPIPE, SIG_IGN);
+#endif
+#ifdef SIGXFSZ
+ /* Disable SIGXFSZ generation for the platforms that have it, otherwise
+ * working with large files when compiled against an APR that doesn't have
+ * large file support will crash the program, which is uncool. */
+ apr_signal(SIGXFSZ, SIG_IGN);
+#endif
+
while (1)
{
int opt;