diff options
| author | Paul Eggert | 2016-01-03 15:00:49 -0800 |
|---|---|---|
| committer | Paul Eggert | 2016-01-03 15:04:07 -0800 |
| commit | e79b06e6def82fab56a153085bff8223876d5908 (patch) | |
| tree | 3fa986746456718707c735b0abda48c092945479 | |
| parent | 861022ff5f7b8d6ab53c726e009208eadf4ecd41 (diff) | |
| download | emacs-e79b06e6def82fab56a153085bff8223876d5908.tar.gz emacs-e79b06e6def82fab56a153085bff8223876d5908.zip | |
Avoid stdio in SIGINT handler
* admin/merge-gnulib (GNULIB_MODULES): Add ignore-value.
* lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate.
* lib/ignore-value.h: New file, from gnulib.
* src/keyboard.c: Include it.
(write_stdout, read_stdin): New functions.
(handle_interrupt): Use them instead of printf and getchar,
and avoid fflush when handling signals.
| -rwxr-xr-x | admin/merge-gnulib | 2 | ||||
| -rw-r--r-- | lib/gnulib.mk | 9 | ||||
| -rw-r--r-- | lib/ignore-value.h | 50 | ||||
| -rw-r--r-- | m4/gnulib-comp.m4 | 2 | ||||
| -rw-r--r-- | src/keyboard.c | 73 |
5 files changed, 108 insertions, 28 deletions
diff --git a/admin/merge-gnulib b/admin/merge-gnulib index 363bb23d119..40b5b78ee8f 100755 --- a/admin/merge-gnulib +++ b/admin/merge-gnulib | |||
| @@ -32,7 +32,7 @@ GNULIB_MODULES=' | |||
| 32 | dtoastr dtotimespec dup2 environ execinfo faccessat | 32 | dtoastr dtotimespec dup2 environ execinfo faccessat |
| 33 | fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync | 33 | fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync |
| 34 | getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog | 34 | getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog |
| 35 | intprops largefile lstat | 35 | ignore-value intprops largefile lstat |
| 36 | manywarnings memrchr mkostemp mktime | 36 | manywarnings memrchr mkostemp mktime |
| 37 | pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat | 37 | pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat |
| 38 | sig2str socklen stat-time stdalign stddef stdio | 38 | sig2str socklen stat-time stdalign stddef stdio |
diff --git a/lib/gnulib.mk b/lib/gnulib.mk index 97ed5b1f40f..b920cbbc9bb 100644 --- a/lib/gnulib.mk +++ b/lib/gnulib.mk | |||
| @@ -21,7 +21,7 @@ | |||
| 21 | # the same distribution terms as the rest of that program. | 21 | # the same distribution terms as the rest of that program. |
| 22 | # | 22 | # |
| 23 | # Generated by gnulib-tool. | 23 | # Generated by gnulib-tool. |
| 24 | # Reproduce by: gnulib-tool --import --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=flexmember --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=setenv --avoid=sigprocmask --avoid=stdarg --avoid=stdbool --avoid=threadlib --avoid=unsetenv --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog intprops largefile lstat manywarnings memrchr mkostemp mktime pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat sig2str socklen stat-time stdalign stddef stdio stpcpy strftime strtoimax strtoumax symlink sys_stat sys_time time time_r time_rz timegm timer-time timespec-add timespec-sub unsetenv update-copyright utimens vla warnings | 24 | # Reproduce by: gnulib-tool --import --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=flexmember --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=setenv --avoid=sigprocmask --avoid=stdarg --avoid=stdbool --avoid=threadlib --avoid=unsetenv --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog ignore-value intprops largefile lstat manywarnings memrchr mkostemp mktime pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat sig2str socklen stat-time stdalign stddef stdio stpcpy strftime strtoimax strtoumax symlink sys_stat sys_time time time_r time_rz timegm timer-time timespec-add timespec-sub unsetenv update-copyright utimens vla warnings |
| 25 | 25 | ||
| 26 | 26 | ||
| 27 | MOSTLYCLEANFILES += core *.stackdump | 27 | MOSTLYCLEANFILES += core *.stackdump |
| @@ -567,6 +567,13 @@ EXTRA_libgnu_a_SOURCES += group-member.c | |||
| 567 | 567 | ||
| 568 | ## end gnulib module group-member | 568 | ## end gnulib module group-member |
| 569 | 569 | ||
| 570 | ## begin gnulib module ignore-value | ||
| 571 | |||
| 572 | |||
| 573 | EXTRA_DIST += ignore-value.h | ||
| 574 | |||
| 575 | ## end gnulib module ignore-value | ||
| 576 | |||
| 570 | ## begin gnulib module intprops | 577 | ## begin gnulib module intprops |
| 571 | 578 | ||
| 572 | 579 | ||
diff --git a/lib/ignore-value.h b/lib/ignore-value.h new file mode 100644 index 00000000000..6713d96f84e --- /dev/null +++ b/lib/ignore-value.h | |||
| @@ -0,0 +1,50 @@ | |||
| 1 | /* ignore a function return without a compiler warning. -*- coding: utf-8 -*- | ||
| 2 | |||
| 3 | Copyright (C) 2008-2016 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | This program is free software: you can redistribute it and/or modify | ||
| 6 | it under the terms of the GNU General Public License as published by | ||
| 7 | the Free Software Foundation; either version 3 of the License, or | ||
| 8 | (at your option) any later version. | ||
| 9 | |||
| 10 | This program is distributed in the hope that it will be useful, | ||
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | GNU General Public License for more details. | ||
| 14 | |||
| 15 | You should have received a copy of the GNU General Public License | ||
| 16 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | ||
| 17 | |||
| 18 | /* Written by Jim Meyering, Eric Blake and Pádraig Brady. */ | ||
| 19 | |||
| 20 | /* Use "ignore_value" to avoid a warning when using a function declared with | ||
| 21 | gcc's warn_unused_result attribute, but for which you really do want to | ||
| 22 | ignore the result. Traditionally, people have used a "(void)" cast to | ||
| 23 | indicate that a function's return value is deliberately unused. However, | ||
| 24 | if the function is declared with __attribute__((warn_unused_result)), | ||
| 25 | gcc issues a warning even with the cast. | ||
| 26 | |||
| 27 | Caution: most of the time, you really should heed gcc's warning, and | ||
| 28 | check the return value. However, in those exceptional cases in which | ||
| 29 | you're sure you know what you're doing, use this function. | ||
| 30 | |||
| 31 | For the record, here's one of the ignorable warnings: | ||
| 32 | "copy.c:233: warning: ignoring return value of 'fchown', | ||
| 33 | declared with attribute warn_unused_result". */ | ||
| 34 | |||
| 35 | #ifndef _GL_IGNORE_VALUE_H | ||
| 36 | #define _GL_IGNORE_VALUE_H | ||
| 37 | |||
| 38 | /* Normally casting an expression to void discards its value, but GCC | ||
| 39 | versions 3.4 and newer have __attribute__ ((__warn_unused_result__)) | ||
| 40 | which may cause unwanted diagnostics in that case. Use __typeof__ | ||
| 41 | and __extension__ to work around the problem, if the workaround is | ||
| 42 | known to be needed. */ | ||
| 43 | #if 3 < __GNUC__ + (4 <= __GNUC_MINOR__) | ||
| 44 | # define ignore_value(x) \ | ||
| 45 | (__extension__ ({ __typeof__ (x) __x = (x); (void) __x; })) | ||
| 46 | #else | ||
| 47 | # define ignore_value(x) ((void) (x)) | ||
| 48 | #endif | ||
| 49 | |||
| 50 | #endif | ||
diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4 index 69920a84afd..27ca70a0d09 100644 --- a/m4/gnulib-comp.m4 +++ b/m4/gnulib-comp.m4 | |||
| @@ -91,6 +91,7 @@ AC_DEFUN([gl_EARLY], | |||
| 91 | # Code from module gettimeofday: | 91 | # Code from module gettimeofday: |
| 92 | # Code from module gitlog-to-changelog: | 92 | # Code from module gitlog-to-changelog: |
| 93 | # Code from module group-member: | 93 | # Code from module group-member: |
| 94 | # Code from module ignore-value: | ||
| 94 | # Code from module include_next: | 95 | # Code from module include_next: |
| 95 | # Code from module intprops: | 96 | # Code from module intprops: |
| 96 | # Code from module inttypes-incomplete: | 97 | # Code from module inttypes-incomplete: |
| @@ -905,6 +906,7 @@ AC_DEFUN([gl_FILE_LIST], [ | |||
| 905 | lib/gettimeofday.c | 906 | lib/gettimeofday.c |
| 906 | lib/gl_openssl.h | 907 | lib/gl_openssl.h |
| 907 | lib/group-member.c | 908 | lib/group-member.c |
| 909 | lib/ignore-value.h | ||
| 908 | lib/intprops.h | 910 | lib/intprops.h |
| 909 | lib/inttypes.in.h | 911 | lib/inttypes.in.h |
| 910 | lib/lstat.c | 912 | lib/lstat.c |
diff --git a/src/keyboard.c b/src/keyboard.c index fcafd0bc9a1..6bdfc1aa084 100644 --- a/src/keyboard.c +++ b/src/keyboard.c | |||
| @@ -64,6 +64,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 64 | #include <unistd.h> | 64 | #include <unistd.h> |
| 65 | #include <fcntl.h> | 65 | #include <fcntl.h> |
| 66 | 66 | ||
| 67 | #include <ignore-value.h> | ||
| 68 | |||
| 67 | #ifdef HAVE_WINDOW_SYSTEM | 69 | #ifdef HAVE_WINDOW_SYSTEM |
| 68 | #include TERM_HEADER | 70 | #include TERM_HEADER |
| 69 | #endif /* HAVE_WINDOW_SYSTEM */ | 71 | #endif /* HAVE_WINDOW_SYSTEM */ |
| @@ -10206,6 +10208,21 @@ deliver_interrupt_signal (int sig) | |||
| 10206 | deliver_process_signal (sig, handle_interrupt_signal); | 10208 | deliver_process_signal (sig, handle_interrupt_signal); |
| 10207 | } | 10209 | } |
| 10208 | 10210 | ||
| 10211 | /* Output MSG directly to standard output, without buffering. Ignore | ||
| 10212 | failures. This is safe in a signal handler. */ | ||
| 10213 | static void | ||
| 10214 | write_stdout (char const *msg) | ||
| 10215 | { | ||
| 10216 | ignore_value (write (STDOUT_FILENO, msg, strlen (msg))); | ||
| 10217 | } | ||
| 10218 | |||
| 10219 | /* Read a byte from stdin, without buffering. Safe in signal handlers. */ | ||
| 10220 | static int | ||
| 10221 | read_stdin (void) | ||
| 10222 | { | ||
| 10223 | char c; | ||
| 10224 | return read (STDIN_FILENO, &c, 1) == 1 ? c : EOF; | ||
| 10225 | } | ||
| 10209 | 10226 | ||
| 10210 | /* If Emacs is stuck because `inhibit-quit' is true, then keep track | 10227 | /* If Emacs is stuck because `inhibit-quit' is true, then keep track |
| 10211 | of the number of times C-g has been requested. If C-g is pressed | 10228 | of the number of times C-g has been requested. If C-g is pressed |
| @@ -10242,9 +10259,9 @@ handle_interrupt (bool in_signal_handler) | |||
| 10242 | sigemptyset (&blocked); | 10259 | sigemptyset (&blocked); |
| 10243 | sigaddset (&blocked, SIGINT); | 10260 | sigaddset (&blocked, SIGINT); |
| 10244 | pthread_sigmask (SIG_BLOCK, &blocked, 0); | 10261 | pthread_sigmask (SIG_BLOCK, &blocked, 0); |
| 10262 | fflush (stdout); | ||
| 10245 | } | 10263 | } |
| 10246 | 10264 | ||
| 10247 | fflush (stdout); | ||
| 10248 | reset_all_sys_modes (); | 10265 | reset_all_sys_modes (); |
| 10249 | 10266 | ||
| 10250 | #ifdef SIGTSTP | 10267 | #ifdef SIGTSTP |
| @@ -10260,8 +10277,9 @@ handle_interrupt (bool in_signal_handler) | |||
| 10260 | /* Perhaps should really fork an inferior shell? | 10277 | /* Perhaps should really fork an inferior shell? |
| 10261 | But that would not provide any way to get back | 10278 | But that would not provide any way to get back |
| 10262 | to the original shell, ever. */ | 10279 | to the original shell, ever. */ |
| 10263 | printf ("No support for stopping a process on this operating system;\n"); | 10280 | write_stdout ("No support for stopping a process" |
| 10264 | printf ("you can continue or abort.\n"); | 10281 | " on this operating system;\n" |
| 10282 | "you can continue or abort.\n"); | ||
| 10265 | #endif /* not SIGTSTP */ | 10283 | #endif /* not SIGTSTP */ |
| 10266 | #ifdef MSDOS | 10284 | #ifdef MSDOS |
| 10267 | /* We must remain inside the screen area when the internal terminal | 10285 | /* We must remain inside the screen area when the internal terminal |
| @@ -10272,46 +10290,49 @@ handle_interrupt (bool in_signal_handler) | |||
| 10272 | the code used for auto-saving doesn't cope with the mark bit. */ | 10290 | the code used for auto-saving doesn't cope with the mark bit. */ |
| 10273 | if (!gc_in_progress) | 10291 | if (!gc_in_progress) |
| 10274 | { | 10292 | { |
| 10275 | printf ("Auto-save? (y or n) "); | 10293 | write_stdout ("Auto-save? (y or n) "); |
| 10276 | fflush (stdout); | 10294 | c = read_stdin (); |
| 10277 | if (((c = getchar ()) & ~040) == 'Y') | 10295 | if ((c & 040) == 'Y') |
| 10278 | { | 10296 | { |
| 10279 | Fdo_auto_save (Qt, Qnil); | 10297 | Fdo_auto_save (Qt, Qnil); |
| 10280 | #ifdef MSDOS | 10298 | #ifdef MSDOS |
| 10281 | printf ("\r\nAuto-save done"); | 10299 | write_stdout ("\r\nAuto-save done"); |
| 10282 | #else /* not MSDOS */ | 10300 | #else |
| 10283 | printf ("Auto-save done\n"); | 10301 | write_stdout ("Auto-save done\n"); |
| 10284 | #endif /* not MSDOS */ | 10302 | #endif |
| 10285 | } | 10303 | } |
| 10286 | while (c != '\n') c = getchar (); | 10304 | while (c != '\n') |
| 10305 | c = read_stdin (); | ||
| 10287 | } | 10306 | } |
| 10288 | else | 10307 | else |
| 10289 | { | 10308 | { |
| 10290 | /* During GC, it must be safe to reenable quitting again. */ | 10309 | /* During GC, it must be safe to reenable quitting again. */ |
| 10291 | Vinhibit_quit = Qnil; | 10310 | Vinhibit_quit = Qnil; |
| 10311 | write_stdout | ||
| 10312 | ( | ||
| 10292 | #ifdef MSDOS | 10313 | #ifdef MSDOS |
| 10293 | printf ("\r\n"); | 10314 | "\r\n" |
| 10294 | #endif /* not MSDOS */ | 10315 | #endif |
| 10295 | printf ("Garbage collection in progress; cannot auto-save now\r\n"); | 10316 | "Garbage collection in progress; cannot auto-save now\r\n" |
| 10296 | printf ("but will instead do a real quit after garbage collection ends\r\n"); | 10317 | "but will instead do a real quit" |
| 10297 | fflush (stdout); | 10318 | " after garbage collection ends\r\n"); |
| 10298 | } | 10319 | } |
| 10299 | 10320 | ||
| 10300 | #ifdef MSDOS | 10321 | #ifdef MSDOS |
| 10301 | printf ("\r\nAbort? (y or n) "); | 10322 | write_stdout ("\r\nAbort? (y or n) "); |
| 10302 | #else /* not MSDOS */ | 10323 | #else |
| 10303 | printf ("Abort (and dump core)? (y or n) "); | 10324 | write_stdout ("Abort (and dump core)? (y or n) "); |
| 10304 | #endif /* not MSDOS */ | 10325 | #endif |
| 10305 | fflush (stdout); | 10326 | c = read_stdin (); |
| 10306 | if (((c = getchar ()) & ~040) == 'Y') | 10327 | if ((c & ~040) == 'Y') |
| 10307 | emacs_abort (); | 10328 | emacs_abort (); |
| 10308 | while (c != '\n') c = getchar (); | 10329 | while (c != '\n') |
| 10330 | c = read_stdin (); | ||
| 10309 | #ifdef MSDOS | 10331 | #ifdef MSDOS |
| 10310 | printf ("\r\nContinuing...\r\n"); | 10332 | write_stdout ("\r\nContinuing...\r\n"); |
| 10311 | #else /* not MSDOS */ | 10333 | #else /* not MSDOS */ |
| 10312 | printf ("Continuing...\n"); | 10334 | write_stdout ("Continuing...\n"); |
| 10313 | #endif /* not MSDOS */ | 10335 | #endif /* not MSDOS */ |
| 10314 | fflush (stdout); | ||
| 10315 | init_all_sys_modes (); | 10336 | init_all_sys_modes (); |
| 10316 | } | 10337 | } |
| 10317 | else | 10338 | else |