From 2a84b02da8b20138fad7fafdea92d7c8f0564ee0 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Fri, 8 Jul 2011 13:20:19 -0700 Subject: [PATCH] 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. --- ChangeLog | 10 +- Makefile.in | 1 - configure.in | 11 +- lib/getopt.c | 11 +- lib/gnulib.mk | 23 ++- lib/pthread_sigmask.c | 29 ++++ lib/signal.in.h | 44 +++++- lib/sigprocmask.c | 329 ++++++++++++++++++++++++++++++++++++++++++ lib/unistd.in.h | 141 +++++++++--------- m4/getopt.m4 | 83 ++++++----- m4/gl-comp.m4 | 25 +++- m4/pthread_sigmask.m4 | 77 ++++++++-- m4/signal_h.m4 | 3 +- m4/signalblocking.m4 | 25 ++++ src/Makefile.in | 4 +- 15 files changed, 677 insertions(+), 139 deletions(-) create mode 100644 lib/pthread_sigmask.c create mode 100644 lib/sigprocmask.c create mode 100644 m4/signalblocking.m4 diff --git a/ChangeLog b/ChangeLog index 6aaebbc80e9..845fce543b6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -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 diff --git a/Makefile.in b/Makefile.in index 07a2c6a017d..a3d85bad22a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -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) diff --git a/configure.in b/configure.in index 5014a793a85..3dd1f035d2b 100644 --- a/configure.in +++ b/configure.in @@ -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" ;; diff --git a/lib/getopt.c b/lib/getopt.c index 2af8352ee9c..7c9f7040612 100644 --- a/lib/getopt.c +++ b/lib/getopt.c @@ -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] == ':') { diff --git a/lib/gnulib.mk b/lib/gnulib.mk index 88a7919b7af..25647f0399c 100644 --- a/lib/gnulib.mk +++ b/lib/gnulib.mk @@ -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 diff --git a/lib/pthread_sigmask.c b/lib/pthread_sigmask.c new file mode 100644 index 00000000000..1f460f13c48 --- /dev/null +++ b/lib/pthread_sigmask.c @@ -0,0 +1,29 @@ +/* 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 . */ + +#include + +/* Specification. */ +#include + +#include + +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); +} diff --git a/lib/signal.in.h b/lib/signal.in.h index 01987a7aff1..93787f753fa 100644 --- a/lib/signal.in.h +++ b/lib/signal.in.h @@ -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 + -> -> . + 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 + -> -> -> . + 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 , but in . On Solaris 10, includes , 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 , not in . + 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 +#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 diff --git a/lib/sigprocmask.c b/lib/sigprocmask.c new file mode 100644 index 00000000000..6780a37b14f --- /dev/null +++ b/lib/sigprocmask.c @@ -0,0 +1,329 @@ +/* POSIX compatible signal blocking. + Copyright (C) 2006-2011 Free Software Foundation, Inc. + Written by Bruno Haible , 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 . */ + +#include + +/* Specification. */ +#include + +#include +#include +#include + +/* 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 diff --git a/lib/unistd.in.h b/lib/unistd.in.h index fdf0fca54e9..769ecf0d43f 100644 --- a/lib/unistd.in.h +++ b/lib/unistd.in.h @@ -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 "); - _GL_WARN_ON_USE (connect, - "connect() used without including "); - _GL_WARN_ON_USE (accept, - "accept() used without including "); - _GL_WARN_ON_USE (bind, - "bind() used without including "); - _GL_WARN_ON_USE (getpeername, - "getpeername() used without including "); - _GL_WARN_ON_USE (getsockname, - "getsockname() used without including "); - _GL_WARN_ON_USE (getsockopt, - "getsockopt() used without including "); - _GL_WARN_ON_USE (listen, - "listen() used without including "); - _GL_WARN_ON_USE (recv, - "recv() used without including "); - _GL_WARN_ON_USE (send, - "send() used without including "); - _GL_WARN_ON_USE (recvfrom, - "recvfrom() used without including "); - _GL_WARN_ON_USE (sendto, - "sendto() used without including "); - _GL_WARN_ON_USE (setsockopt, - "setsockopt() used without including "); - _GL_WARN_ON_USE (shutdown, - "shutdown() used without including "); -# endif +/* Hide some function declarations from . */ + +#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 +# 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 "); + _GL_WARN_ON_USE (connect, + "connect() used without including "); + _GL_WARN_ON_USE (accept, + "accept() used without including "); + _GL_WARN_ON_USE (bind, + "bind() used without including "); + _GL_WARN_ON_USE (getpeername, + "getpeername() used without including "); + _GL_WARN_ON_USE (getsockname, + "getsockname() used without including "); + _GL_WARN_ON_USE (getsockopt, + "getsockopt() used without including "); + _GL_WARN_ON_USE (listen, + "listen() used without including "); + _GL_WARN_ON_USE (recv, + "recv() used without including "); + _GL_WARN_ON_USE (send, + "send() used without including "); + _GL_WARN_ON_USE (recvfrom, + "recvfrom() used without including "); + _GL_WARN_ON_USE (sendto, + "sendto() used without including "); + _GL_WARN_ON_USE (setsockopt, + "setsockopt() used without including "); + _GL_WARN_ON_USE (shutdown, + "shutdown() used without including "); # endif -# if !defined _@GUARD_PREFIX@_SYS_SELECT_H -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef select -# define select select_used_without_including_sys_select_h -# else - _GL_WARN_ON_USE (select, - "select() used without including "); -# endif +# endif +# if !defined _@GUARD_PREFIX@_SYS_SELECT_H +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef select +# define select select_used_without_including_sys_select_h +# else + _GL_WARN_ON_USE (select, + "select() used without including "); # endif # endif #endif diff --git a/m4/getopt.m4 b/m4/getopt.m4 index 4d8450ff907..7e49ddde9f6 100644 --- a/m4/getopt.m4 +++ b/m4/getopt.m4 @@ -1,4 +1,4 @@ -# getopt.m4 serial 35 +# getopt.m4 serial 38 dnl Copyright (C) 2002-2006, 2008-2011 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -89,15 +89,15 @@ AC_DEFUN([gl_GETOPT_CHECK_HEADERS], AC_CACHE_CHECK([whether getopt is POSIX compatible], [gl_cv_func_getopt_posix], [ - dnl BSD getopt_long uses an incompatible method to reset - dnl option processing. Existence of the variable, in and of + dnl BSD getopt_long uses an incompatible method to reset option + dnl processing. Existence of the optreset variable, in and of dnl itself, is not a reason to replace getopt, but knowledge dnl of the variable is needed to determine how to reset and dnl whether a reset reparses the environment. Solaris dnl supports neither optreset nor optind=0, but keeps no state dnl that needs a reset beyond setting optind=1; detect Solaris dnl by getopt_clip. - AC_COMPILE_IFELSE( + AC_LINK_IFELSE( [AC_LANG_PROGRAM( [[#include ]], [[int *p = &optreset; return optreset;]])], @@ -121,22 +121,20 @@ int main () { { - int argc = 0; - char *argv[10]; + static char program[] = "program"; + static char a[] = "-a"; + static char foo[] = "foo"; + static char bar[] = "bar"; + char *argv[] = { program, a, foo, bar, NULL }; int c; - argv[argc++] = "program"; - argv[argc++] = "-a"; - argv[argc++] = "foo"; - argv[argc++] = "bar"; - argv[argc] = NULL; optind = OPTIND_MIN; opterr = 0; - c = getopt (argc, argv, "ab"); + c = getopt (4, argv, "ab"); if (!(c == 'a')) return 1; - c = getopt (argc, argv, "ab"); + c = getopt (4, argv, "ab"); if (!(c == -1)) return 2; if (!(optind == 2)) @@ -144,22 +142,20 @@ main () } /* Some internal state exists at this point. */ { - int argc = 0; - char *argv[10]; + static char program[] = "program"; + static char donald[] = "donald"; + static char p[] = "-p"; + static char billy[] = "billy"; + static char duck[] = "duck"; + static char a[] = "-a"; + static char bar[] = "bar"; + char *argv[] = { program, donald, p, billy, duck, a, bar, NULL }; int c; - argv[argc++] = "program"; - argv[argc++] = "donald"; - argv[argc++] = "-p"; - argv[argc++] = "billy"; - argv[argc++] = "duck"; - argv[argc++] = "-a"; - argv[argc++] = "bar"; - argv[argc] = NULL; optind = OPTIND_MIN; opterr = 0; - c = getopt (argc, argv, "+abp:q:"); + c = getopt (7, argv, "+abp:q:"); if (!(c == -1)) return 4; if (!(strcmp (argv[0], "program") == 0)) @@ -181,7 +177,9 @@ main () } /* Detect MacOS 10.5, AIX 7.1 bug. */ { - char *argv[3] = { "program", "-ab", NULL }; + static char program[] = "program"; + static char ab[] = "-ab"; + char *argv[3] = { program, ab, NULL }; optind = OPTIND_MIN; opterr = 0; if (getopt (2, argv, "ab:") != 'a') @@ -239,19 +237,22 @@ dnl is ambiguous with environment values that contain newlines. and fails on MacOS X 10.5, AIX 5.2, HP-UX 11, IRIX 6.5, OSF/1 5.1, Solaris 10. */ { - char *myargv[3]; - myargv[0] = "conftest"; - myargv[1] = "-+"; - myargv[2] = 0; + static char conftest[] = "conftest"; + static char plus[] = "-+"; + char *argv[3] = { conftest, plus, NULL }; opterr = 0; - if (getopt (2, myargv, "+a") != '?') + if (getopt (2, argv, "+a") != '?') result |= 1; } /* This code succeeds on glibc 2.8, mingw, and fails on MacOS X 10.5, OpenBSD 4.0, AIX 5.2, HP-UX 11, IRIX 6.5, OSF/1 5.1, Solaris 10, Cygwin 1.5.x. */ { - char *argv[] = { "program", "-p", "foo", "bar", NULL }; + static char program[] = "program"; + static char p[] = "-p"; + static char foo[] = "foo"; + static char bar[] = "bar"; + char *argv[] = { program, p, foo, bar, NULL }; optind = 1; if (getopt (4, argv, "p::") != 'p') @@ -265,7 +266,10 @@ dnl is ambiguous with environment values that contain newlines. } /* This code succeeds on glibc 2.8 and fails on Cygwin 1.7.0. */ { - char *argv[] = { "program", "foo", "-p", NULL }; + static char program[] = "program"; + static char foo[] = "foo"; + static char p[] = "-p"; + char *argv[] = { program, foo, p, NULL }; optind = 0; if (getopt (3, argv, "-p") != 1) result |= 16; @@ -274,13 +278,26 @@ dnl is ambiguous with environment values that contain newlines. } /* This code fails on glibc 2.11. */ { - char *argv[] = { "program", "-b", "-a", NULL }; + static char program[] = "program"; + static char b[] = "-b"; + static char a[] = "-a"; + char *argv[] = { program, b, a, NULL }; optind = opterr = 0; if (getopt (3, argv, "+:a:b") != 'b') result |= 64; else if (getopt (3, argv, "+:a:b") != ':') result |= 64; } + /* This code dumps core on glibc 2.14. */ + { + static char program[] = "program"; + static char w[] = "-W"; + static char dummy[] = "dummy"; + char *argv[] = { program, w, dummy, NULL }; + optind = opterr = 1; + if (getopt (3, argv, "W;") != 'W') + result |= 128; + } return result; ]])], [gl_cv_func_getopt_gnu=yes], diff --git a/m4/gl-comp.m4 b/m4/gl-comp.m4 index 004c01a10a0..6c94e373871 100644 --- a/m4/gl-comp.m4 +++ b/m4/gl-comp.m4 @@ -55,6 +55,7 @@ AC_DEFUN([gl_EARLY], # Code from module pthread_sigmask: # Code from module readlink: # Code from module signal: + # Code from module sigprocmask: # Code from module socklen: # Code from module ssize_t: # Code from module stat: @@ -142,7 +143,10 @@ if test $REPLACE_MKTIME = 1; then fi gl_TIME_MODULE_INDICATOR([mktime]) gl_MULTIARCH -gl_PTHREAD_SIGMASK +gl_FUNC_PTHREAD_SIGMASK +if test $HAVE_PTHREAD_SIGMASK = 0 || test $REPLACE_PTHREAD_SIGMASK = 1; then + AC_LIBOBJ([pthread_sigmask]) +fi gl_SIGNAL_MODULE_INDICATOR([pthread_sigmask]) gl_FUNC_READLINK if test $HAVE_READLINK = 0 || test $REPLACE_READLINK = 1; then @@ -184,6 +188,7 @@ AC_REQUIRE([AC_C_INLINE]) gl_UNISTD_H gl_gnulib_enabled_dosname=false gl_gnulib_enabled_be453cec5eecf5731a274f2de7f2db36=false + gl_gnulib_enabled_sigprocmask=false gl_gnulib_enabled_stat=false gl_gnulib_enabled_strtoull=false gl_gnulib_enabled_verify=false @@ -201,6 +206,18 @@ AC_SUBST([LTLIBINTL]) gl_gnulib_enabled_be453cec5eecf5731a274f2de7f2db36=true fi } + func_gl_gnulib_m4code_sigprocmask () + { + if ! $gl_gnulib_enabled_sigprocmask; then +gl_SIGNALBLOCKING +if test $HAVE_POSIX_SIGNALBLOCKING = 0; then + AC_LIBOBJ([sigprocmask]) + gl_PREREQ_SIGPROCMASK +fi +gl_SIGNAL_MODULE_INDICATOR([sigprocmask]) + gl_gnulib_enabled_sigprocmask=true + fi + } func_gl_gnulib_m4code_stat () { if ! $gl_gnulib_enabled_stat; then @@ -246,7 +263,7 @@ gl_STDLIB_MODULE_INDICATOR([strtoull]) if test $REPLACE_LSTAT = 1; then func_gl_gnulib_m4code_stat fi - if test $REPLACE_PTHREAD_SIGMASK = 1; then + if test $HAVE_PTHREAD_SIGMASK = 0 || test $REPLACE_PTHREAD_SIGMASK = 1; then func_gl_gnulib_m4code_sigprocmask fi if test $HAVE_READLINK = 0 || test $REPLACE_READLINK = 1; then @@ -261,6 +278,7 @@ gl_STDLIB_MODULE_INDICATOR([strtoull]) m4_pattern_allow([^gl_GNULIB_ENABLED_]) AM_CONDITIONAL([gl_GNULIB_ENABLED_dosname], [$gl_gnulib_enabled_dosname]) AM_CONDITIONAL([gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36], [$gl_gnulib_enabled_be453cec5eecf5731a274f2de7f2db36]) + AM_CONDITIONAL([gl_GNULIB_ENABLED_sigprocmask], [$gl_gnulib_enabled_sigprocmask]) AM_CONDITIONAL([gl_GNULIB_ENABLED_stat], [$gl_gnulib_enabled_stat]) AM_CONDITIONAL([gl_GNULIB_ENABLED_strtoull], [$gl_gnulib_enabled_strtoull]) AM_CONDITIONAL([gl_GNULIB_ENABLED_verify], [$gl_gnulib_enabled_verify]) @@ -434,6 +452,7 @@ AC_DEFUN([gl_FILE_LIST], [ lib/md5.h lib/mktime-internal.h lib/mktime.c + lib/pthread_sigmask.c lib/readlink.c lib/sha1.c lib/sha1.h @@ -442,6 +461,7 @@ AC_DEFUN([gl_FILE_LIST], [ lib/sha512.c lib/sha512.h lib/signal.in.h + lib/sigprocmask.c lib/stat.c lib/stdarg.in.h lib/stdbool.in.h @@ -485,6 +505,7 @@ AC_DEFUN([gl_FILE_LIST], [ m4/sha256.m4 m4/sha512.m4 m4/signal_h.m4 + m4/signalblocking.m4 m4/socklen.m4 m4/ssize_t.m4 m4/st_dm_mode.m4 diff --git a/m4/pthread_sigmask.m4 b/m4/pthread_sigmask.m4 index d25e2cc3e70..dfa0f660a75 100644 --- a/m4/pthread_sigmask.m4 +++ b/m4/pthread_sigmask.m4 @@ -1,26 +1,77 @@ -# pthread_sigmask.m4 serial 2 +# pthread_sigmask.m4 serial 7 dnl Copyright (C) 2011 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. -AC_DEFUN([gl_PTHREAD_SIGMASK], +AC_DEFUN([gl_FUNC_PTHREAD_SIGMASK], [ + AC_CHECK_FUNCS_ONCE([pthread_sigmask]) + LIB_PTHREAD_SIGMASK= m4_ifdef([gl_THREADLIB], [ AC_REQUIRE([gl_THREADLIB]) if test "$gl_threads_api" = posix; then - gl_save_LIBS="$LIBS" - LIBS="$LIBS $LIBMULTITHREAD" - AC_CHECK_FUNCS([pthread_sigmask]) - LIBS="$gl_save_LIBS" + if test $ac_cv_func_pthread_sigmask = yes; then + dnl pthread_sigmask is available without -lpthread. + : + else + if test -n "$LIBMULTITHREAD"; then + AC_CACHE_CHECK([for pthread_sigmask in $LIBMULTITHREAD], + [gl_cv_func_pthread_sigmask_in_LIBMULTITHREAD], + [gl_save_LIBS="$LIBS" + LIBS="$LIBS $LIBMULTITHREAD" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#include + #include + ]], + [[return pthread_sigmask (0, (sigset_t *) 0, (sigset_t *) 0);]]) + ], + [gl_cv_func_pthread_sigmask_in_LIBMULTITHREAD=yes], + [gl_cv_func_pthread_sigmask_in_LIBMULTITHREAD=no]) + LIBS="$gl_save_LIBS" + ]) + if test $gl_cv_func_pthread_sigmask_in_LIBMULTITHREAD = yes; then + dnl pthread_sigmask is available with -lpthread. + LIB_PTHREAD_SIGMASK="$LIBMULTITHREAD" + else + dnl pthread_sigmask is not available at all. + HAVE_PTHREAD_SIGMASK=0 + fi + else + dnl pthread_sigmask is not available at all. + HAVE_PTHREAD_SIGMASK=0 + fi + fi else - ac_cv_func_pthread_sigmask=no + dnl pthread_sigmask may exist but does not interoperate with the chosen + dnl multithreading facility. + dnl If "$gl_threads_api" = pth, we could use the function pth_sigmask, + dnl but it is equivalent to sigprocmask, so we choose to emulate + dnl pthread_sigmask with sigprocmask also in this case. This yields fewer + dnl link dependencies. + if test $ac_cv_func_pthread_sigmask = yes; then + REPLACE_PTHREAD_SIGMASK=1 + else + HAVE_PTHREAD_SIGMASK=0 + fi + fi + ] ,[ + dnl gl_THREADLIB is not in use. Assume the application wants + dnl POSIX semantics. + if test $ac_cv_func_pthread_sigmask != yes; then + gl_save_LIBS=$LIBS + AC_SEARCH_LIBS([pthread_sigmask], [pthread c_r]) + LIBS=$gl_save_LIBS + if test "$ac_cv_search_pthread_sigmask" = no; then + HAVE_PTHREAD_SIGMASK=0 + elif test "$ac_cv_search_pthread_sigmask" != 'none required'; then + LIB_PTHREAD_SIGMASK=$ac_cv_search_pthread_sigmask + fi fi - ], [ - AC_CHECK_FUNCS_ONCE([pthread_sigmask]) ]) - - if test $ac_cv_func_pthread_sigmask = no; then - REPLACE_PTHREAD_SIGMASK=1 - fi + AC_SUBST([LIB_PTHREAD_SIGMASK]) + dnl We don't need a variable LTLIB_PTHREAD_SIGMASK, because when + dnl "$gl_threads_api" = posix, $LTLIBMULTITHREAD and $LIBMULTITHREAD are the + dnl same: either both empty or both "-lpthread". ]) diff --git a/m4/signal_h.m4 b/m4/signal_h.m4 index 53972fba54f..b9536fb0e3c 100644 --- a/m4/signal_h.m4 +++ b/m4/signal_h.m4 @@ -1,4 +1,4 @@ -# signal_h.m4 serial 14 +# signal_h.m4 serial 16 dnl Copyright (C) 2007-2011 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -64,6 +64,7 @@ AC_DEFUN([gl_SIGNAL_H_DEFAULTS], GNULIB_SIGACTION=0; AC_SUBST([GNULIB_SIGACTION]) dnl Assume proper GNU behavior unless another module says otherwise. HAVE_POSIX_SIGNALBLOCKING=1; AC_SUBST([HAVE_POSIX_SIGNALBLOCKING]) + HAVE_PTHREAD_SIGMASK=1; AC_SUBST([HAVE_PTHREAD_SIGMASK]) HAVE_SIGSET_T=1; AC_SUBST([HAVE_SIGSET_T]) HAVE_SIGINFO_T=1; AC_SUBST([HAVE_SIGINFO_T]) HAVE_SIGACTION=1; AC_SUBST([HAVE_SIGACTION]) diff --git a/m4/signalblocking.m4 b/m4/signalblocking.m4 new file mode 100644 index 00000000000..15b74253ba6 --- /dev/null +++ b/m4/signalblocking.m4 @@ -0,0 +1,25 @@ +# signalblocking.m4 serial 12 +dnl Copyright (C) 2001-2002, 2006-2011 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +# Determine available signal blocking primitives. Three different APIs exist: +# 1) POSIX: sigemptyset, sigaddset, sigprocmask +# 2) SYSV: sighold, sigrelse +# 3) BSD: sigblock, sigsetmask +# For simplicity, here we check only for the POSIX signal blocking. +AC_DEFUN([gl_SIGNALBLOCKING], +[ + AC_REQUIRE([gl_SIGNAL_H_DEFAULTS]) + AC_REQUIRE([gl_CHECK_TYPE_SIGSET_T]) + if test $gl_cv_type_sigset_t = yes; then + AC_CHECK_FUNC([sigprocmask], [gl_cv_func_sigprocmask=1]) + fi + if test -z "$gl_cv_func_sigprocmask"; then + HAVE_POSIX_SIGNALBLOCKING=0 + fi +]) + +# Prerequisites of lib/sigprocmask.c. +AC_DEFUN([gl_PREREQ_SIGPROCMASK], [:]) diff --git a/src/Makefile.in b/src/Makefile.in index f628c321f70..f68fa5c2240 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -269,6 +269,8 @@ LIBSELINUX_LIBS = @LIBSELINUX_LIBS@ LIBGNUTLS_LIBS = @LIBGNUTLS_LIBS@ LIBGNUTLS_CFLAGS = @LIBGNUTLS_CFLAGS@ +LIB_PTHREAD_SIGMASK = @LIB_PTHREAD_SIGMASK@ + INTERVALS_H = dispextern.h intervals.h composite.h GETLOADAVG_LIBS = @GETLOADAVG_LIBS@ @@ -383,7 +385,7 @@ LIBES = $(LIBS) $(LIBX_BASE) $(LIBX_OTHER) $(LIBSOUND) \ $(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) \ $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \ $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \ - $(LIBGNUTLS_LIBS) \ + $(LIBGNUTLS_LIBS) $(LIB_PTHREAD_SIGMASK) \ $(LIB_GCC) $(LIB_MATH) $(LIB_STANDARD) $(LIB_GCC) all: emacs$(EXEEXT) $(OTHER_FILES)