mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-12-26 10:49:33 +00:00
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.
This commit is contained in:
parent
9e0fc61954
commit
564c84f4b1
@ -32,7 +32,7 @@ GNULIB_MODULES='
|
||||
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
|
||||
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
|
||||
|
@ -21,7 +21,7 @@
|
||||
# the same distribution terms as the rest of that program.
|
||||
#
|
||||
# Generated by gnulib-tool.
|
||||
# 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
|
||||
# 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
|
||||
|
||||
|
||||
MOSTLYCLEANFILES += core *.stackdump
|
||||
@ -567,6 +567,13 @@ EXTRA_libgnu_a_SOURCES += group-member.c
|
||||
|
||||
## end gnulib module group-member
|
||||
|
||||
## begin gnulib module ignore-value
|
||||
|
||||
|
||||
EXTRA_DIST += ignore-value.h
|
||||
|
||||
## end gnulib module ignore-value
|
||||
|
||||
## begin gnulib module intprops
|
||||
|
||||
|
||||
|
50
lib/ignore-value.h
Normal file
50
lib/ignore-value.h
Normal file
@ -0,0 +1,50 @@
|
||||
/* ignore a function return without a compiler warning. -*- coding: utf-8 -*-
|
||||
|
||||
Copyright (C) 2008-2016 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Written by Jim Meyering, Eric Blake and Pádraig Brady. */
|
||||
|
||||
/* Use "ignore_value" to avoid a warning when using a function declared with
|
||||
gcc's warn_unused_result attribute, but for which you really do want to
|
||||
ignore the result. Traditionally, people have used a "(void)" cast to
|
||||
indicate that a function's return value is deliberately unused. However,
|
||||
if the function is declared with __attribute__((warn_unused_result)),
|
||||
gcc issues a warning even with the cast.
|
||||
|
||||
Caution: most of the time, you really should heed gcc's warning, and
|
||||
check the return value. However, in those exceptional cases in which
|
||||
you're sure you know what you're doing, use this function.
|
||||
|
||||
For the record, here's one of the ignorable warnings:
|
||||
"copy.c:233: warning: ignoring return value of 'fchown',
|
||||
declared with attribute warn_unused_result". */
|
||||
|
||||
#ifndef _GL_IGNORE_VALUE_H
|
||||
#define _GL_IGNORE_VALUE_H
|
||||
|
||||
/* Normally casting an expression to void discards its value, but GCC
|
||||
versions 3.4 and newer have __attribute__ ((__warn_unused_result__))
|
||||
which may cause unwanted diagnostics in that case. Use __typeof__
|
||||
and __extension__ to work around the problem, if the workaround is
|
||||
known to be needed. */
|
||||
#if 3 < __GNUC__ + (4 <= __GNUC_MINOR__)
|
||||
# define ignore_value(x) \
|
||||
(__extension__ ({ __typeof__ (x) __x = (x); (void) __x; }))
|
||||
#else
|
||||
# define ignore_value(x) ((void) (x))
|
||||
#endif
|
||||
|
||||
#endif
|
@ -91,6 +91,7 @@ AC_DEFUN([gl_EARLY],
|
||||
# Code from module gettimeofday:
|
||||
# Code from module gitlog-to-changelog:
|
||||
# Code from module group-member:
|
||||
# Code from module ignore-value:
|
||||
# Code from module include_next:
|
||||
# Code from module intprops:
|
||||
# Code from module inttypes-incomplete:
|
||||
@ -905,6 +906,7 @@ AC_DEFUN([gl_FILE_LIST], [
|
||||
lib/gettimeofday.c
|
||||
lib/gl_openssl.h
|
||||
lib/group-member.c
|
||||
lib/ignore-value.h
|
||||
lib/intprops.h
|
||||
lib/inttypes.in.h
|
||||
lib/lstat.c
|
||||
|
@ -64,6 +64,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <ignore-value.h>
|
||||
|
||||
#ifdef HAVE_WINDOW_SYSTEM
|
||||
#include TERM_HEADER
|
||||
#endif /* HAVE_WINDOW_SYSTEM */
|
||||
@ -10206,6 +10208,21 @@ deliver_interrupt_signal (int sig)
|
||||
deliver_process_signal (sig, handle_interrupt_signal);
|
||||
}
|
||||
|
||||
/* Output MSG directly to standard output, without buffering. Ignore
|
||||
failures. This is safe in a signal handler. */
|
||||
static void
|
||||
write_stdout (char const *msg)
|
||||
{
|
||||
ignore_value (write (STDOUT_FILENO, msg, strlen (msg)));
|
||||
}
|
||||
|
||||
/* Read a byte from stdin, without buffering. Safe in signal handlers. */
|
||||
static int
|
||||
read_stdin (void)
|
||||
{
|
||||
char c;
|
||||
return read (STDIN_FILENO, &c, 1) == 1 ? c : EOF;
|
||||
}
|
||||
|
||||
/* If Emacs is stuck because `inhibit-quit' is true, then keep track
|
||||
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)
|
||||
sigemptyset (&blocked);
|
||||
sigaddset (&blocked, SIGINT);
|
||||
pthread_sigmask (SIG_BLOCK, &blocked, 0);
|
||||
fflush (stdout);
|
||||
}
|
||||
|
||||
fflush (stdout);
|
||||
reset_all_sys_modes ();
|
||||
|
||||
#ifdef SIGTSTP
|
||||
@ -10260,8 +10277,9 @@ handle_interrupt (bool in_signal_handler)
|
||||
/* Perhaps should really fork an inferior shell?
|
||||
But that would not provide any way to get back
|
||||
to the original shell, ever. */
|
||||
printf ("No support for stopping a process on this operating system;\n");
|
||||
printf ("you can continue or abort.\n");
|
||||
write_stdout ("No support for stopping a process"
|
||||
" on this operating system;\n"
|
||||
"you can continue or abort.\n");
|
||||
#endif /* not SIGTSTP */
|
||||
#ifdef MSDOS
|
||||
/* We must remain inside the screen area when the internal terminal
|
||||
@ -10272,46 +10290,49 @@ handle_interrupt (bool in_signal_handler)
|
||||
the code used for auto-saving doesn't cope with the mark bit. */
|
||||
if (!gc_in_progress)
|
||||
{
|
||||
printf ("Auto-save? (y or n) ");
|
||||
fflush (stdout);
|
||||
if (((c = getchar ()) & ~040) == 'Y')
|
||||
write_stdout ("Auto-save? (y or n) ");
|
||||
c = read_stdin ();
|
||||
if ((c & 040) == 'Y')
|
||||
{
|
||||
Fdo_auto_save (Qt, Qnil);
|
||||
#ifdef MSDOS
|
||||
printf ("\r\nAuto-save done");
|
||||
#else /* not MSDOS */
|
||||
printf ("Auto-save done\n");
|
||||
#endif /* not MSDOS */
|
||||
write_stdout ("\r\nAuto-save done");
|
||||
#else
|
||||
write_stdout ("Auto-save done\n");
|
||||
#endif
|
||||
}
|
||||
while (c != '\n') c = getchar ();
|
||||
while (c != '\n')
|
||||
c = read_stdin ();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* During GC, it must be safe to reenable quitting again. */
|
||||
Vinhibit_quit = Qnil;
|
||||
write_stdout
|
||||
(
|
||||
#ifdef MSDOS
|
||||
printf ("\r\n");
|
||||
#endif /* not MSDOS */
|
||||
printf ("Garbage collection in progress; cannot auto-save now\r\n");
|
||||
printf ("but will instead do a real quit after garbage collection ends\r\n");
|
||||
fflush (stdout);
|
||||
"\r\n"
|
||||
#endif
|
||||
"Garbage collection in progress; cannot auto-save now\r\n"
|
||||
"but will instead do a real quit"
|
||||
" after garbage collection ends\r\n");
|
||||
}
|
||||
|
||||
#ifdef MSDOS
|
||||
printf ("\r\nAbort? (y or n) ");
|
||||
#else /* not MSDOS */
|
||||
printf ("Abort (and dump core)? (y or n) ");
|
||||
#endif /* not MSDOS */
|
||||
fflush (stdout);
|
||||
if (((c = getchar ()) & ~040) == 'Y')
|
||||
write_stdout ("\r\nAbort? (y or n) ");
|
||||
#else
|
||||
write_stdout ("Abort (and dump core)? (y or n) ");
|
||||
#endif
|
||||
c = read_stdin ();
|
||||
if ((c & ~040) == 'Y')
|
||||
emacs_abort ();
|
||||
while (c != '\n') c = getchar ();
|
||||
while (c != '\n')
|
||||
c = read_stdin ();
|
||||
#ifdef MSDOS
|
||||
printf ("\r\nContinuing...\r\n");
|
||||
write_stdout ("\r\nContinuing...\r\n");
|
||||
#else /* not MSDOS */
|
||||
printf ("Continuing...\n");
|
||||
write_stdout ("Continuing...\n");
|
||||
#endif /* not MSDOS */
|
||||
fflush (stdout);
|
||||
init_all_sys_modes ();
|
||||
}
|
||||
else
|
||||
|
Loading…
Reference in New Issue
Block a user