mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-17 01:34:21 +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
861022ff5f
commit
e79b06e6de
5 changed files with 108 additions and 28 deletions
|
|
@ -32,7 +32,7 @@ GNULIB_MODULES='
|
||||||
dtoastr dtotimespec dup2 environ execinfo faccessat
|
dtoastr dtotimespec dup2 environ execinfo faccessat
|
||||||
fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync
|
fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync
|
||||||
getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog
|
getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog
|
||||||
intprops largefile lstat
|
ignore-value intprops largefile lstat
|
||||||
manywarnings memrchr mkostemp mktime
|
manywarnings memrchr mkostemp mktime
|
||||||
pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat
|
pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat
|
||||||
sig2str socklen stat-time stdalign stddef stdio
|
sig2str socklen stat-time stdalign stddef stdio
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
# the same distribution terms as the rest of that program.
|
# the same distribution terms as the rest of that program.
|
||||||
#
|
#
|
||||||
# Generated by gnulib-tool.
|
# 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
|
MOSTLYCLEANFILES += core *.stackdump
|
||||||
|
|
@ -567,6 +567,13 @@ EXTRA_libgnu_a_SOURCES += group-member.c
|
||||||
|
|
||||||
## end gnulib module group-member
|
## end gnulib module group-member
|
||||||
|
|
||||||
|
## begin gnulib module ignore-value
|
||||||
|
|
||||||
|
|
||||||
|
EXTRA_DIST += ignore-value.h
|
||||||
|
|
||||||
|
## end gnulib module ignore-value
|
||||||
|
|
||||||
## begin gnulib module intprops
|
## 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 gettimeofday:
|
||||||
# Code from module gitlog-to-changelog:
|
# Code from module gitlog-to-changelog:
|
||||||
# Code from module group-member:
|
# Code from module group-member:
|
||||||
|
# Code from module ignore-value:
|
||||||
# Code from module include_next:
|
# Code from module include_next:
|
||||||
# Code from module intprops:
|
# Code from module intprops:
|
||||||
# Code from module inttypes-incomplete:
|
# Code from module inttypes-incomplete:
|
||||||
|
|
@ -905,6 +906,7 @@ AC_DEFUN([gl_FILE_LIST], [
|
||||||
lib/gettimeofday.c
|
lib/gettimeofday.c
|
||||||
lib/gl_openssl.h
|
lib/gl_openssl.h
|
||||||
lib/group-member.c
|
lib/group-member.c
|
||||||
|
lib/ignore-value.h
|
||||||
lib/intprops.h
|
lib/intprops.h
|
||||||
lib/inttypes.in.h
|
lib/inttypes.in.h
|
||||||
lib/lstat.c
|
lib/lstat.c
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include <ignore-value.h>
|
||||||
|
|
||||||
#ifdef HAVE_WINDOW_SYSTEM
|
#ifdef HAVE_WINDOW_SYSTEM
|
||||||
#include TERM_HEADER
|
#include TERM_HEADER
|
||||||
#endif /* HAVE_WINDOW_SYSTEM */
|
#endif /* HAVE_WINDOW_SYSTEM */
|
||||||
|
|
@ -10206,6 +10208,21 @@ deliver_interrupt_signal (int sig)
|
||||||
deliver_process_signal (sig, handle_interrupt_signal);
|
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
|
/* 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
|
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);
|
sigemptyset (&blocked);
|
||||||
sigaddset (&blocked, SIGINT);
|
sigaddset (&blocked, SIGINT);
|
||||||
pthread_sigmask (SIG_BLOCK, &blocked, 0);
|
pthread_sigmask (SIG_BLOCK, &blocked, 0);
|
||||||
|
fflush (stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
fflush (stdout);
|
|
||||||
reset_all_sys_modes ();
|
reset_all_sys_modes ();
|
||||||
|
|
||||||
#ifdef SIGTSTP
|
#ifdef SIGTSTP
|
||||||
|
|
@ -10260,8 +10277,9 @@ handle_interrupt (bool in_signal_handler)
|
||||||
/* Perhaps should really fork an inferior shell?
|
/* Perhaps should really fork an inferior shell?
|
||||||
But that would not provide any way to get back
|
But that would not provide any way to get back
|
||||||
to the original shell, ever. */
|
to the original shell, ever. */
|
||||||
printf ("No support for stopping a process on this operating system;\n");
|
write_stdout ("No support for stopping a process"
|
||||||
printf ("you can continue or abort.\n");
|
" on this operating system;\n"
|
||||||
|
"you can continue or abort.\n");
|
||||||
#endif /* not SIGTSTP */
|
#endif /* not SIGTSTP */
|
||||||
#ifdef MSDOS
|
#ifdef MSDOS
|
||||||
/* We must remain inside the screen area when the internal terminal
|
/* 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. */
|
the code used for auto-saving doesn't cope with the mark bit. */
|
||||||
if (!gc_in_progress)
|
if (!gc_in_progress)
|
||||||
{
|
{
|
||||||
printf ("Auto-save? (y or n) ");
|
write_stdout ("Auto-save? (y or n) ");
|
||||||
fflush (stdout);
|
c = read_stdin ();
|
||||||
if (((c = getchar ()) & ~040) == 'Y')
|
if ((c & 040) == 'Y')
|
||||||
{
|
{
|
||||||
Fdo_auto_save (Qt, Qnil);
|
Fdo_auto_save (Qt, Qnil);
|
||||||
#ifdef MSDOS
|
#ifdef MSDOS
|
||||||
printf ("\r\nAuto-save done");
|
write_stdout ("\r\nAuto-save done");
|
||||||
#else /* not MSDOS */
|
#else
|
||||||
printf ("Auto-save done\n");
|
write_stdout ("Auto-save done\n");
|
||||||
#endif /* not MSDOS */
|
#endif
|
||||||
}
|
}
|
||||||
while (c != '\n') c = getchar ();
|
while (c != '\n')
|
||||||
|
c = read_stdin ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* During GC, it must be safe to reenable quitting again. */
|
/* During GC, it must be safe to reenable quitting again. */
|
||||||
Vinhibit_quit = Qnil;
|
Vinhibit_quit = Qnil;
|
||||||
|
write_stdout
|
||||||
|
(
|
||||||
#ifdef MSDOS
|
#ifdef MSDOS
|
||||||
printf ("\r\n");
|
"\r\n"
|
||||||
#endif /* not MSDOS */
|
#endif
|
||||||
printf ("Garbage collection in progress; cannot auto-save now\r\n");
|
"Garbage collection in progress; cannot auto-save now\r\n"
|
||||||
printf ("but will instead do a real quit after garbage collection ends\r\n");
|
"but will instead do a real quit"
|
||||||
fflush (stdout);
|
" after garbage collection ends\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MSDOS
|
#ifdef MSDOS
|
||||||
printf ("\r\nAbort? (y or n) ");
|
write_stdout ("\r\nAbort? (y or n) ");
|
||||||
#else /* not MSDOS */
|
#else
|
||||||
printf ("Abort (and dump core)? (y or n) ");
|
write_stdout ("Abort (and dump core)? (y or n) ");
|
||||||
#endif /* not MSDOS */
|
#endif
|
||||||
fflush (stdout);
|
c = read_stdin ();
|
||||||
if (((c = getchar ()) & ~040) == 'Y')
|
if ((c & ~040) == 'Y')
|
||||||
emacs_abort ();
|
emacs_abort ();
|
||||||
while (c != '\n') c = getchar ();
|
while (c != '\n')
|
||||||
|
c = read_stdin ();
|
||||||
#ifdef MSDOS
|
#ifdef MSDOS
|
||||||
printf ("\r\nContinuing...\r\n");
|
write_stdout ("\r\nContinuing...\r\n");
|
||||||
#else /* not MSDOS */
|
#else /* not MSDOS */
|
||||||
printf ("Continuing...\n");
|
write_stdout ("Continuing...\n");
|
||||||
#endif /* not MSDOS */
|
#endif /* not MSDOS */
|
||||||
fflush (stdout);
|
|
||||||
init_all_sys_modes ();
|
init_all_sys_modes ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue