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 /src | |
| 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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/keyboard.c | 73 |
1 files changed, 47 insertions, 26 deletions
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 |