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
