bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: dd hangs with SIGINT


From: Bruno Haible
Subject: Re: dd hangs with SIGINT
Date: Wed, 6 Apr 2005 21:24:11 +0200
User-agent: KMail/1.5

Guillaume Chazarain wrote:
> As it prints a message for the first time, it has to
> initialize gettext, and I'm not sure this qualifies for the "do as
> little as possible in a signal handler" rule.

I agree. The list of guaranteed async-safe function calls on POSIX systems
is listed at
http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html#tag_02_04_03

fprintf() is not part of it. gettext() neither, nor are the calls made
by gettext(), namely malloc(), free(), tsearch(), mmap(). So it would seem
advisable to pre-fetch the translations before the SIGINT happens. Untested
patch is appended. Unfortunately it forces to remove ngettext() calls, which
is bad for plural handling. Also you need to check the quote() call whether
it avoids calling malloc...

Bruno

*** dd.c.bak    2005-04-06 20:39:58.000000000 +0200
--- dd.c        2005-04-06 21:08:58.000000000 +0200
***************
*** 476,481 ****
--- 476,511 ----
    return (i & (i - 1)) != 0;
  }
  
+ /* Pre-translated strings, to avoid gettext() calls during signal handler.  */
+ static const char *msg_records_in;
+ static const char *msg_records_out;
+ static const char *msg_truncated;
+ static const char *msg_truncated_plural;
+ static const char *msg_copied;
+ static const char *msg_copied_plural;
+ static const char *msg_infinity;
+ static const char *msg_seconds;
+ static const char *msg_seconds_plural;
+ static const char *msg_closing_input;
+ static const char *msg_closing_output;
+ 
+ static void
+ preinit_before_signal (void)
+ {
+   msg_records_in = _("%s+%s records in\n");
+   msg_records_out = _("%s+%s records out\n");
+   msg_truncated = _("truncated record");
+   msg_truncated_plural = _("truncated records");
+   msg_copied = _("%s byte (%s) copied");
+   msg_copied_plural = _("%s bytes (%s) copied");
+   msg_infinity = _("Infinity");
+   msg_seconds = _(", %g second, %s/s\n");
+   msg_seconds_plural = _(", %g seconds, %s/s\n");
+   msg_closing_input = _("closing input file %s");
+   msg_closing_output = _("closing output file %s");
+ }
+ 
+ /* Called from signal handler.  */
  static void
  print_stats (void)
  {
***************
*** 488,504 ****
    double delta_s;
    char const *bytes_per_second;
  
!   fprintf (stderr, _("%s+%s records in\n"),
           umaxtostr (r_full, buf[0]), umaxtostr (r_partial, buf[1]));
!   fprintf (stderr, _("%s+%s records out\n"),
           umaxtostr (w_full, buf[0]), umaxtostr (w_partial, buf[1]));
    if (r_truncate > 0)
      {
        fprintf (stderr, "%s %s\n",
               umaxtostr (r_truncate, buf[0]),
               (r_truncate == 1
!               ? _("truncated record")
!               : _("truncated records")));
      }
  
    if (status_flags & STATUS_NOXFER)
--- 518,534 ----
    double delta_s;
    char const *bytes_per_second;
  
!   fprintf (stderr, msg_records_in,
           umaxtostr (r_full, buf[0]), umaxtostr (r_partial, buf[1]));
!   fprintf (stderr, msg_records_out,
           umaxtostr (w_full, buf[0]), umaxtostr (w_partial, buf[1]));
    if (r_truncate > 0)
      {
        fprintf (stderr, "%s %s\n",
               umaxtostr (r_truncate, buf[0]),
               (r_truncate == 1
!               ? msg_truncated
!               : msg_truncated_plural));
      }
  
    if (status_flags & STATUS_NOXFER)
***************
*** 508,515 ****
       since that makes it easy to use SI abbreviations.  */
  
    fprintf (stderr,
!          ngettext ("%s byte (%s) copied",
!                    "%s bytes (%s) copied", w_bytes == 1),
           umaxtostr (w_bytes, buf[0]),
           human_readable (w_bytes, buf[1], human_opts, 1, 1));
  
--- 538,544 ----
       since that makes it easy to use SI abbreviations.  */
  
    fprintf (stderr,
!          w_bytes == 1 ? msg_copied : msg_copied_plural,
           umaxtostr (w_bytes, buf[0]),
           human_readable (w_bytes, buf[1], human_opts, 1, 1));
  
***************
*** 524,548 ****
    else
      {
        delta_s = 0;
!       sprintf (buf[1], "%s B", _("Infinity"));
        bytes_per_second = buf[1];
      }
  
    fprintf (stderr,
!          ngettext (", %g second, %s/s\n",
!                    ", %g seconds, %s/s\n", delta_s == 1),
           delta_s, bytes_per_second);
  }
  
  static void
  cleanup (void)
  {
    if (close (STDIN_FILENO) < 0)
      error (EXIT_FAILURE, errno,
!          _("closing input file %s"), quote (input_file));
    if (close (STDOUT_FILENO) < 0)
      error (EXIT_FAILURE, errno,
!          _("closing output file %s"), quote (output_file));
    print_stats ();
  }
  
--- 553,577 ----
    else
      {
        delta_s = 0;
!       sprintf (buf[1], "%s B", msg_infinity);
        bytes_per_second = buf[1];
      }
  
    fprintf (stderr,
!          delta_s == 1 ? msg_seconds : msg_seconds_plural,
           delta_s, bytes_per_second);
  }
  
+ /* Called from signal handler.  */
  static void
  cleanup (void)
  {
    if (close (STDIN_FILENO) < 0)
      error (EXIT_FAILURE, errno,
!          msg_closing_input, quote (input_file));
    if (close (STDOUT_FILENO) < 0)
      error (EXIT_FAILURE, errno,
!          msg_closing_output, quote (output_file));
    print_stats ();
  }
  
***************
*** 1525,1530 ****
--- 1554,1560 ----
  #endif
      }
  
+   preinit_before_signal ();
    install_handler (SIGINT, interrupt_handler);
    install_handler (SIGQUIT, interrupt_handler);
    install_handler (SIGPIPE, interrupt_handler);




reply via email to

[Prev in Thread] Current Thread [Next in Thread]