Commit 2a84b02d authored by Paul Eggert's avatar Paul Eggert

Simplify Emacs part of pthread_sigmask support.

* Makefile.in (GNULIB_TOOL_FLAGS): Do not avoid sigprocmask.
* configure.in (AC_TYPE_UID_T): New dummy macro.
Configure gnulib after adjusting LIBS,
so that gnulib can assume the libraries in LIBS.
* lib/pthread_sigmask.c, lib/sigprocmask.c, m4/signalblocking.m4:
New files, automatically imported from gnulib.
* lib/gnulib.mk, m4/gl-comp.m4: Regenerate.
* src/Makefile.in (LIB_PTHREAD_SIGMASK): New macro.
(LIBES): Use it.
parent 1692ae2d
......@@ -2,15 +2,17 @@
Add gnulib support for pthread_sigmask (Bug#9010).
* Makefile.in (GNULIB_MODULES): Add pthread_sigmask.
(GNULIB_TOOL_FLAGS): Avoid sigprocmask. Emacs does its own
implementation of 'sigprocmask' on Windows, and it assumes
'sigprocmask' on non-Windows hosts, so it doesn't need the
sigprocmask module.
* configure.in (AC_TYPE_UID_T): New dummy macro.
Configure gnulib after adjusting LIBS,
so that gnulib can assume the libraries in LIBS.
* lib/signal.in.h, m4/pthread_sigmask.m4, m4/signal_h.m4:
* lib/pthread_sigprocmask.c, lib/sigprocmask.c, m4/signalblocking.m4:
New files, automatically imported from gnulib.
* lib/gnulib.mk, m4/gl-comp.m4: Automatically-imported update
due to the above changes.
* .bzrignore: Add lib/signal.h.
* src/Makefile.in (LIB_PTHREAD_SIGMASK): New macro.
(LIBES): Use it.
2011-07-07 Andreas Schwab <schwab@linux-m68k.org>
......
......@@ -339,7 +339,6 @@ GNULIB_MODULES = \
mktime pthread_sigmask readlink \
socklen stdarg stdio strftime strtoumax symlink sys_stat
GNULIB_TOOL_FLAGS = \
--avoid=sigprocmask \
--conditional-dependencies --import --no-changelog --no-vc-files \
--makefile-name=gnulib.mk
sync-from-gnulib: $(gnulib_srcdir)
......
......@@ -984,6 +984,8 @@ fi
# Suppress obsolescent Autoconf test for size_t; Emacs assumes C89 or better.
AC_DEFUN([AC_TYPE_SIZE_T])
# Likewise for obsolescent test for uid_t, gid_t; Emacs assumes them.
AC_DEFUN([AC_TYPE_UID_T])
dnl Do this early because it can frob feature test macros for Unix-98 &c.
AC_SYS_LARGEFILE
......@@ -2725,11 +2727,6 @@ AC_FUNC_FSEEKO
AC_FUNC_GETPGRP
# Configure gnulib.
gl_ASSERT_NO_GNULIB_POSIXCHECK
gl_ASSERT_NO_GNULIB_TESTS
gl_INIT
# UNIX98 PTYs.
AC_CHECK_FUNCS(grantpt)
......@@ -3333,6 +3330,10 @@ AC_SUBST(CYGWIN_OBJ)
AC_SUBST(PRE_ALLOC_OBJ)
AC_SUBST(POST_ALLOC_OBJ)
# Configure gnulib here, now that we know LIBS.
gl_ASSERT_NO_GNULIB_POSIXCHECK
gl_ASSERT_NO_GNULIB_TESTS
gl_INIT
case "$opsys" in
aix4-2) LD_SWITCH_SYSTEM_TEMACS="-Wl,-bnodelcsect" ;;
......
......@@ -829,7 +829,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
return '?';
}
/* Convenience. Treat POSIX -W foo same as long option --foo */
if (temp[0] == 'W' && temp[1] == ';' && longopts)
if (temp[0] == 'W' && temp[1] == ';')
{
char *nameend;
const struct option *p;
......@@ -839,6 +839,9 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
int indfound = 0;
int option_index;
if (longopts == NULL)
goto no_longs;
/* This is an option that requires an argument. */
if (*d->__nextchar != '\0')
{
......@@ -1046,8 +1049,10 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
}
return pfound->val;
}
d->__nextchar = NULL;
return 'W'; /* Let the application handle it. */
no_longs:
d->__nextchar = NULL;
return 'W'; /* Let the application handle it. */
}
if (temp[1] == ':')
{
......
......@@ -9,7 +9,7 @@
# the same distribution terms as the rest of that program.
#
# Generated by gnulib-tool.
# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=. --avoid=sigprocmask --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt careadlinkat crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dup2 filemode getloadavg getopt-gnu ignore-value intprops lstat mktime pthread_sigmask readlink socklen stdarg stdio strftime strtoumax symlink sys_stat
# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=. --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt careadlinkat crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dup2 filemode getloadavg getopt-gnu ignore-value intprops lstat mktime pthread_sigmask readlink socklen stdarg stdio strftime strtoumax symlink sys_stat
MOSTLYCLEANFILES += core *.stackdump
......@@ -294,6 +294,15 @@ EXTRA_libgnu_a_SOURCES += mktime.c
## end gnulib module mktime
## begin gnulib module pthread_sigmask
EXTRA_DIST += pthread_sigmask.c
EXTRA_libgnu_a_SOURCES += pthread_sigmask.c
## end gnulib module pthread_sigmask
## begin gnulib module readlink
......@@ -322,6 +331,7 @@ signal.h: signal.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H
-e 's/@''GNULIB_SIGPROCMASK''@/$(GNULIB_SIGPROCMASK)/g' \
-e 's/@''GNULIB_SIGACTION''@/$(GNULIB_SIGACTION)/g' \
-e 's|@''HAVE_POSIX_SIGNALBLOCKING''@|$(HAVE_POSIX_SIGNALBLOCKING)|g' \
-e 's|@''HAVE_PTHREAD_SIGMASK''@|$(HAVE_PTHREAD_SIGMASK)|g' \
-e 's|@''HAVE_SIGSET_T''@|$(HAVE_SIGSET_T)|g' \
-e 's|@''HAVE_SIGINFO_T''@|$(HAVE_SIGINFO_T)|g' \
-e 's|@''HAVE_SIGACTION''@|$(HAVE_SIGACTION)|g' \
......@@ -341,6 +351,17 @@ EXTRA_DIST += signal.in.h
## end gnulib module signal
## begin gnulib module sigprocmask
if gl_GNULIB_ENABLED_sigprocmask
endif
EXTRA_DIST += sigprocmask.c
EXTRA_libgnu_a_SOURCES += sigprocmask.c
## end gnulib module sigprocmask
## begin gnulib module stat
if gl_GNULIB_ENABLED_stat
......
/* POSIX compatible signal blocking for threads.
Copyright (C) 2011 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/>. */
#include <config.h>
/* Specification. */
#include <signal.h>
#include <errno.h>
int
pthread_sigmask (int how, const sigset_t *new_mask, sigset_t *old_mask)
{
int ret = sigprocmask (how, new_mask, old_mask);
return (ret < 0 ? errno : 0);
}
......@@ -20,8 +20,17 @@
#endif
@PRAGMA_COLUMNS@
#if defined __need_sig_atomic_t || defined __need_sigset_t
/* Special invocation convention inside glibc header files. */
#if defined __need_sig_atomic_t || defined __need_sigset_t || defined _GL_ALREADY_INCLUDING_SIGNAL_H || (defined _SIGNAL_H && !defined __SIZEOF_PTHREAD_MUTEX_T)
/* Special invocation convention:
- Inside glibc header files.
- On glibc systems we have a sequence of nested includes
<signal.h> -> <ucontext.h> -> <signal.h>.
In this situation, the functions are not yet declared, therefore we cannot
provide the C++ aliases.
- On glibc systems with GCC 4.3 we have a sequence of nested includes
<csignal> -> </usr/include/signal.h> -> <sys/ucontext.h> -> <signal.h>.
In this situation, some of the functions are not yet declared, therefore
we cannot provide the C++ aliases. */
# @INCLUDE_NEXT@ @NEXT_SIGNAL_H@
......@@ -30,6 +39,8 @@
#ifndef _@GUARD_PREFIX@_SIGNAL_H
#define _GL_ALREADY_INCLUDING_SIGNAL_H
/* Define pid_t, uid_t.
Also, mingw defines sigset_t not in <signal.h>, but in <sys/types.h>.
On Solaris 10, <signal.h> includes <sys/types.h>, which eventually includes
......@@ -39,9 +50,20 @@
/* The include_next requires a split double-inclusion guard. */
#@INCLUDE_NEXT@ @NEXT_SIGNAL_H@
#undef _GL_ALREADY_INCLUDING_SIGNAL_H
#ifndef _@GUARD_PREFIX@_SIGNAL_H
#define _@GUARD_PREFIX@_SIGNAL_H
/* MacOS X 10.3, FreeBSD 6.4, OpenBSD 3.8, OSF/1 4.0, Solaris 2.6 declare
pthread_sigmask in <pthread.h>, not in <signal.h>.
But avoid namespace pollution on glibc systems.*/
#if (@GNULIB_PTHREAD_SIGMASK@ || defined GNULIB_POSIXCHECK) \
&& ((defined __APPLE__ && defined __MACH__) || defined __FreeBSD__ || defined __OpenBSD__ || defined __osf__ || defined __sun) \
&& ! defined __GLIBC__
# include <pthread.h>
#endif
/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */
/* The definition of _GL_ARG_NONNULL is copied here. */
......@@ -104,9 +126,23 @@ typedef void (*sighandler_t) (int);
#if @GNULIB_PTHREAD_SIGMASK@
# if @REPLACE_PTHREAD_SIGMASK@
# undef pthread_sigmask
# define pthread_sigmask sigprocmask
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef pthread_sigmask
# define pthread_sigmask rpl_pthread_sigmask
# endif
_GL_FUNCDECL_RPL (pthread_sigmask, int,
(int how, const sigset_t *new_mask, sigset_t *old_mask));
_GL_CXXALIAS_RPL (pthread_sigmask, int,
(int how, const sigset_t *new_mask, sigset_t *old_mask));
# else
# if !@HAVE_PTHREAD_SIGMASK@
_GL_FUNCDECL_SYS (pthread_sigmask, int,
(int how, const sigset_t *new_mask, sigset_t *old_mask));
# endif
_GL_CXXALIAS_SYS (pthread_sigmask, int,
(int how, const sigset_t *new_mask, sigset_t *old_mask));
# endif
_GL_CXXALIASWARN (pthread_sigmask);
#elif defined GNULIB_POSIXCHECK
# undef pthread_sigmask
# if HAVE_RAW_DECL_PTHREAD_SIGMASK
......
/* POSIX compatible signal blocking.
Copyright (C) 2006-2011 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2006.
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/>. */
#include <config.h>
/* Specification. */
#include <signal.h>
#include <errno.h>
#include <stdint.h>
#include <stdlib.h>
/* We assume that a platform without POSIX signal blocking functions
also does not have the POSIX sigaction() function, only the
signal() function. We also assume signal() has SysV semantics,
where any handler is uninstalled prior to being invoked. This is
true for Woe32 platforms. */
/* We use raw signal(), but also provide a wrapper rpl_signal() so
that applications can query or change a blocked signal. */
#undef signal
/* Provide invalid signal numbers as fallbacks if the uncatchable
signals are not defined. */
#ifndef SIGKILL
# define SIGKILL (-1)
#endif
#ifndef SIGSTOP
# define SIGSTOP (-1)
#endif
/* On native Windows, as of 2008, the signal SIGABRT_COMPAT is an alias
for the signal SIGABRT. Only one signal handler is stored for both
SIGABRT and SIGABRT_COMPAT. SIGABRT_COMPAT is not a signal of its own. */
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
# undef SIGABRT_COMPAT
# define SIGABRT_COMPAT 6
#endif
#ifdef SIGABRT_COMPAT
# define SIGABRT_COMPAT_MASK (1U << SIGABRT_COMPAT)
#else
# define SIGABRT_COMPAT_MASK 0
#endif
typedef void (*handler_t) (int);
/* Handling of gnulib defined signals. */
#if GNULIB_defined_SIGPIPE
static handler_t SIGPIPE_handler = SIG_DFL;
#endif
#if GNULIB_defined_SIGPIPE
static handler_t
ext_signal (int sig, handler_t handler)
{
switch (sig)
{
case SIGPIPE:
{
handler_t old_handler = SIGPIPE_handler;
SIGPIPE_handler = handler;
return old_handler;
}
default: /* System defined signal */
return signal (sig, handler);
}
}
# define signal ext_signal
#endif
int
sigismember (const sigset_t *set, int sig)
{
if (sig >= 0 && sig < NSIG)
{
#ifdef SIGABRT_COMPAT
if (sig == SIGABRT_COMPAT)
sig = SIGABRT;
#endif
return (*set >> sig) & 1;
}
else
return 0;
}
int
sigemptyset (sigset_t *set)
{
*set = 0;
return 0;
}
int
sigaddset (sigset_t *set, int sig)
{
if (sig >= 0 && sig < NSIG)
{
#ifdef SIGABRT_COMPAT
if (sig == SIGABRT_COMPAT)
sig = SIGABRT;
#endif
*set |= 1U << sig;
return 0;
}
else
{
errno = EINVAL;
return -1;
}
}
int
sigdelset (sigset_t *set, int sig)
{
if (sig >= 0 && sig < NSIG)
{
#ifdef SIGABRT_COMPAT
if (sig == SIGABRT_COMPAT)
sig = SIGABRT;
#endif
*set &= ~(1U << sig);
return 0;
}
else
{
errno = EINVAL;
return -1;
}
}
int
sigfillset (sigset_t *set)
{
*set = ((2U << (NSIG - 1)) - 1) & ~ SIGABRT_COMPAT_MASK;
return 0;
}
/* Set of currently blocked signals. */
static volatile sigset_t blocked_set /* = 0 */;
/* Set of currently blocked and pending signals. */
static volatile sig_atomic_t pending_array[NSIG] /* = { 0 } */;
/* Signal handler that is installed for blocked signals. */
static void
blocked_handler (int sig)
{
/* Reinstall the handler, in case the signal occurs multiple times
while blocked. There is an inherent race where an asynchronous
signal in between when the kernel uninstalled the handler and
when we reinstall it will trigger the default handler; oh
well. */
signal (sig, blocked_handler);
if (sig >= 0 && sig < NSIG)
pending_array[sig] = 1;
}
int
sigpending (sigset_t *set)
{
sigset_t pending = 0;
int sig;
for (sig = 0; sig < NSIG; sig++)
if (pending_array[sig])
pending |= 1U << sig;
*set = pending;
return 0;
}
/* The previous signal handlers.
Only the array elements corresponding to blocked signals are relevant. */
static volatile handler_t old_handlers[NSIG];
int
sigprocmask (int operation, const sigset_t *set, sigset_t *old_set)
{
if (old_set != NULL)
*old_set = blocked_set;
if (set != NULL)
{
sigset_t new_blocked_set;
sigset_t to_unblock;
sigset_t to_block;
switch (operation)
{
case SIG_BLOCK:
new_blocked_set = blocked_set | *set;
break;
case SIG_SETMASK:
new_blocked_set = *set;
break;
case SIG_UNBLOCK:
new_blocked_set = blocked_set & ~*set;
break;
default:
errno = EINVAL;
return -1;
}
to_unblock = blocked_set & ~new_blocked_set;
to_block = new_blocked_set & ~blocked_set;
if (to_block != 0)
{
int sig;
for (sig = 0; sig < NSIG; sig++)
if ((to_block >> sig) & 1)
{
pending_array[sig] = 0;
if ((old_handlers[sig] = signal (sig, blocked_handler)) != SIG_ERR)
blocked_set |= 1U << sig;
}
}
if (to_unblock != 0)
{
sig_atomic_t received[NSIG];
int sig;
for (sig = 0; sig < NSIG; sig++)
if ((to_unblock >> sig) & 1)
{
if (signal (sig, old_handlers[sig]) != blocked_handler)
/* The application changed a signal handler while the signal
was blocked, bypassing our rpl_signal replacement.
We don't support this. */
abort ();
received[sig] = pending_array[sig];
blocked_set &= ~(1U << sig);
pending_array[sig] = 0;
}
else
received[sig] = 0;
for (sig = 0; sig < NSIG; sig++)
if (received[sig])
raise (sig);
}
}
return 0;
}
/* Install the handler FUNC for signal SIG, and return the previous
handler. */
handler_t
rpl_signal (int sig, handler_t handler)
{
/* We must provide a wrapper, so that a user can query what handler
they installed even if that signal is currently blocked. */
if (sig >= 0 && sig < NSIG && sig != SIGKILL && sig != SIGSTOP
&& handler != SIG_ERR)
{
#ifdef SIGABRT_COMPAT
if (sig == SIGABRT_COMPAT)
sig = SIGABRT;
#endif
if (blocked_set & (1U << sig))
{
/* POSIX states that sigprocmask and signal are both
async-signal-safe. This is not true of our
implementation - there is a slight data race where an
asynchronous interrupt on signal A can occur after we
install blocked_handler but before we have updated
old_handlers for signal B, such that handler A can see
stale information if it calls signal(B). Oh well -
signal handlers really shouldn't try to manipulate the
installed handlers of unrelated signals. */
handler_t result = old_handlers[sig];
old_handlers[sig] = handler;
return result;
}
else
return signal (sig, handler);
}
else
{
errno = EINVAL;
return SIG_ERR;
}
}
#if GNULIB_defined_SIGPIPE
/* Raise the signal SIG. */
int
rpl_raise (int sig)
# undef raise
{
switch (sig)
{
case SIGPIPE:
if (blocked_set & (1U << sig))
pending_array[sig] = 1;
else
{
handler_t handler = SIGPIPE_handler;
if (handler == SIG_DFL)
exit (128 + SIGPIPE);
else if (handler != SIG_IGN)
(*handler) (sig);
}
return 0;
default: /* System defined signal */
return raise (sig);
}
}
#endif
......@@ -117,78 +117,77 @@
/* The definition of _GL_WARN_ON_USE is copied here. */
#if @GNULIB_GETHOSTNAME@
/* Get all possible declarations of gethostname(). */
# if @UNISTD_H_HAVE_WINSOCK2_H@
# if !defined _@GUARD_PREFIX@_SYS_SOCKET_H
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef socket
# define socket socket_used_without_including_sys_socket_h
# undef connect
# define connect connect_used_without_including_sys_socket_h
# undef accept
# define accept accept_used_without_including_sys_socket_h
# undef bind
# define bind bind_used_without_including_sys_socket_h
# undef getpeername
# define getpeername getpeername_used_without_including_sys_socket_h
# undef getsockname
# define getsockname getsockname_used_without_including_sys_socket_h
# undef getsockopt
# define getsockopt getsockopt_used_without_including_sys_socket_h
# undef listen
# define listen listen_used_without_including_sys_socket_h
# undef recv
# define recv recv_used_without_including_sys_socket_h
# undef send
# define send send_used_without_including_sys_socket_h
# undef recvfrom
# define recvfrom recvfrom_used_without_including_sys_socket_h
# undef sendto
# define sendto sendto_used_without_including_sys_socket_h
# undef setsockopt
# define setsockopt setsockopt_used_without_including_sys_socket_h
# undef shutdown
# define shutdown shutdown_used_without_including_sys_socket_h
# else
_GL_WARN_ON_USE (socket,
"socket() used without including <sys/socket.h>");
_GL_WARN_ON_USE (connect,
"connect() used without including <sys/socket.h>");
_GL_WARN_ON_USE (accept,
"accept() used without including <sys/socket.h>");
_GL_WARN_ON_USE (bind,
"bind() used without including <sys/socket.h>");
_GL_WARN_ON_USE (getpeername,
"getpeername() used without including <sys/socket.h>");
_GL_WARN_ON_USE (getsockname,
"getsockname() used without including <sys/socket.h>");
_GL_WARN_ON_USE (getsockopt,
"getsockopt() used without including <sys/socket.h>");
_GL_WARN_ON_USE (listen,
"listen() used without including <sys/socket.h>");
_GL_WARN_ON_USE (recv,
"recv() used without including <sys/socket.h>");
_GL_WARN_ON_USE (send,
"send() used without including <sys/socket.h>");
_GL_WARN_ON_USE (recvfrom,
"recvfrom() used without including <sys/socket.h>");
_GL_WARN_ON_USE (sendto,
"sendto() used without including <sys/socket.h>");
_GL_WARN_ON_USE (setsockopt,
"setsockopt() used without including <sys/socket.h>");
_GL_WARN_ON_USE (shutdown,
"shutdown() used without including <sys/socket.h>");
# endif
/* Hide some function declarations from <winsock2.h>. */
#if @GNULIB_GETHOSTNAME@ && @UNISTD_H_HAVE_WINSOCK2_H@
# if !defined _@GUARD_PREFIX@_SYS_SOCKET_H
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef socket
# define socket socket_used_without_including_sys_socket_h
# undef connect
# define connect connect_used_without_including_sys_socket_h
# undef accept
# define accept accept_used_without_including_sys_socket_h
# undef bind
# define bind bind_used_without_including_sys_socket_h
# undef getpeername
# define getpeername getpeername_used_without_including_sys_socket_h
# undef getsockname
# define getsockname getsockname_used_without_including_sys_socket_h
# undef getsockopt
# define getsockopt getsockopt_used_without_including_sys_socket_h
# undef listen
# define listen listen_used_without_including_sys_socket_h
# undef recv