svn-3716

Version:

1.7.0

Bug Link:

http://subversion.tigris.org/issues/show_bug.cgi?id=3716

Patch Link:

source code patch: http://svn.apache.org/viewvc?diff_format=h&view=revision&revision=1035792

Symptom:

‘svnrdump’ doesn’t support cancellation. That when users send a SIGINT signal (via CTL + c), SVN will quit immediately. But the correct behavior (patched version) should not abort immediately, but keep going until “svn_repos_parse_dumpstream2” is called. Within “svn_repos_parse_dumpstream2”, they will check whether a signal is received, and exit there, printing a “caught signal” at the end of the execution.

 

*background: ‘svnrdump’ is a command to produce a dumpfile or to load it of a local or remote repository.

How it is diagnosed:

source code analysis / discussion

 

Root Cause:

Brief:

svndump do not have a signal handler for SIGINT. So in the patch they simply installed signal handler for SIGINT, as well as others. Then the correct behavior (patched version) should not abort immediately, but keep going until “svn_repos_parse_dumpstream2” is called. Within “svn_repos_parse_dumpstream2”, they will check whether a signal is received, and exit there, printing a “caught signal” at the end of the execution.‘svnrdump load’ should support cancellation. Currently, it passes NULL of ‘cancel_func’ to ‘svn_repos_parse_dumpstream2()’.

 

‘svnrdump dump’ should support cancellation. Currently it has no ‘cancel_func’ to ‘access’.

Detail:

--- subversion/trunk/subversion/svnrdump/svnrdump.c        2010/11/16 20:35:09              1035791

+++ subversion/trunk/subversion/svnrdump/svnrdump.c  2010/11/16 20:39:08              1035792

@@ -39,6 +41,34 @@

 

 #include "private/svn_cmdline_private.h"

 

+

+/*** 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. */

 /* This signal handler will ignore any received signal, but set a global flag ‘cancelled’ to TRUE. */

+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;

+}

+

+

+

+

svn_error_t *

svn_repos_parse_dumpstream2(... ...)

{

      /* They will defer the termination caused by the signal here. So if svndump received a signal,

          in the signal_hanlder they will only set ‘cancelled’ and continue. Here, they will call

          cancel_func, which is a function pointer to check_cancel, to quit the execution! */

      /* Check for cancellation. */

      if (cancel_func)

        SVN_ERR(cancel_func(cancel_baton));

 static svn_opt_subcommand_t dump_cmd, load_cmd;

 

 enum svn_svnrdump__longopt_t

@@ -228,6 +258,9 @@ open_connection(svn_ra_session_t **sessi

   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 *sessi

 

   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;

Failure symptom category

Missing behavior/incomplete computation

Is there any log message?

No

Can ErrLog help?

Yes. signal handler