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


_______________________________________________
Bug-coreutils mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/bug-coreutils

Reply via email to