pthread_sigmask.m4 9.43 KB
Newer Older
Paul Eggert's avatar
Paul Eggert committed
1
# pthread_sigmask.m4 serial 18
Paul Eggert's avatar
Paul Eggert committed
2
dnl Copyright (C) 2011-2020 Free Software Foundation, Inc.
3 4 5 6
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.

7
AC_DEFUN([gl_FUNC_PTHREAD_SIGMASK],
8
[
Paul Eggert's avatar
Paul Eggert committed
9 10
  AC_REQUIRE([gl_SIGNAL_H_DEFAULTS])

11
  AC_CHECK_FUNCS_ONCE([pthread_sigmask])
Paul Eggert's avatar
Paul Eggert committed
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

  dnl On MinGW pthread_sigmask is just a macro which always returns 0.
  dnl It does not exist as a real function, which is required by POSIX.
  AC_CACHE_CHECK([whether pthread_sigmask is a macro],
    [gl_cv_func_pthread_sigmask_macro],
    [AC_EGREP_CPP([headers_define_pthread_sigmask], [
#include <pthread.h>
#include <signal.h>
#ifdef pthread_sigmask
 headers_define_pthread_sigmask
#endif],
       [gl_cv_func_pthread_sigmask_macro=yes],
       [gl_cv_func_pthread_sigmask_macro=no])
    ])

27
  LIB_PTHREAD_SIGMASK=
28

Paul Eggert's avatar
Paul Eggert committed
29 30 31 32 33 34 35 36 37 38 39 40
  if test $gl_cv_func_pthread_sigmask_macro = yes; then
    dnl pthread_sigmask is a dummy macro.
    HAVE_PTHREAD_SIGMASK=0
    dnl Make sure to '#undef pthread_sigmask' before defining it.
    REPLACE_PTHREAD_SIGMASK=1
  else
    dnl Test whether the gnulib module 'threadlib' is in use.
    dnl Some packages like Emacs use --avoid=threadlib.
    dnl Write the symbol in such a way that it does not cause 'aclocal' to pick
    dnl the threadlib.m4 file that is installed in $PREFIX/share/aclocal/.
    m4_ifdef([gl_][THREADLIB], [
      AC_REQUIRE([gl_][THREADLIB])
41

Paul Eggert's avatar
Paul Eggert committed
42 43 44 45 46 47 48 49
      if test "$gl_threads_api" = posix; then
        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],
Paul Eggert's avatar
Paul Eggert committed
50 51 52 53 54 55 56 57 58
              [gl_save_LIBS="$LIBS"
               LIBS="$LIBS $LIBMULTITHREAD"
               AC_LINK_IFELSE(
                 [AC_LANG_PROGRAM(
                    [[#include <pthread.h>
                      #include <signal.h>
                    ]],
                    [[return pthread_sigmask (0, (sigset_t *) 0, (sigset_t *) 0);]])
                 ],
Paul Eggert's avatar
Paul Eggert committed
59 60
                 [gl_cv_func_pthread_sigmask_in_LIBMULTITHREAD=yes],
                 [gl_cv_func_pthread_sigmask_in_LIBMULTITHREAD=no])
Paul Eggert's avatar
Paul Eggert committed
61 62
               LIBS="$gl_save_LIBS"
              ])
Paul Eggert's avatar
Paul Eggert committed
63 64 65 66 67 68
            if test $gl_cv_func_pthread_sigmask_in_LIBMULTITHREAD = yes; then
              dnl pthread_sigmask is available with -pthread or -lpthread.
              LIB_PTHREAD_SIGMASK="$LIBMULTITHREAD"
            else
              dnl pthread_sigmask is not available at all.
              HAVE_PTHREAD_SIGMASK=0
Paul Eggert's avatar
Paul Eggert committed
69
            fi
70 71 72 73
          else
            dnl pthread_sigmask is not available at all.
            HAVE_PTHREAD_SIGMASK=0
          fi
Paul Eggert's avatar
Paul Eggert committed
74 75 76 77 78 79
        fi
      else
        dnl pthread_sigmask may exist but does not interoperate with the chosen
        dnl multithreading facility.
        if test $ac_cv_func_pthread_sigmask = yes; then
          REPLACE_PTHREAD_SIGMASK=1
80 81 82 83
        else
          HAVE_PTHREAD_SIGMASK=0
        fi
      fi
Paul Eggert's avatar
Paul Eggert committed
84 85 86 87 88
    ], [
      dnl The module 'threadlib' is not in use, due to --avoid=threadlib being
      dnl specified.
      dnl The package either has prepared CPPFLAGS and LIBS for use of
      dnl POSIX:2008 threads, or wants to build single-threaded programs.
89
      if test $ac_cv_func_pthread_sigmask = yes; then
Paul Eggert's avatar
Paul Eggert committed
90 91 92
        dnl pthread_sigmask exists and does not require extra libraries.
        dnl Assume that it is declared.
        :
93
      else
Paul Eggert's avatar
Paul Eggert committed
94
        dnl pthread_sigmask either does not exist or needs extra libraries.
95
        HAVE_PTHREAD_SIGMASK=0
Paul Eggert's avatar
Paul Eggert committed
96 97 98 99
        dnl Define the symbol rpl_pthread_sigmask, not pthread_sigmask,
        dnl so as to not accidentally override the system's pthread_sigmask
        dnl symbol from libpthread. This is necessary on IRIX 6.5.
        REPLACE_PTHREAD_SIGMASK=1
100
      fi
Paul Eggert's avatar
Paul Eggert committed
101 102
    ])
  fi
103

104 105 106
  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
Paul Eggert's avatar
Paul Eggert committed
107
  dnl same.
108 109 110 111 112 113 114 115 116 117

  dnl Now test for some bugs in the system function.
  if test $HAVE_PTHREAD_SIGMASK = 1; then
    AC_REQUIRE([AC_PROG_CC])
    AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles

    dnl On FreeBSD 6.4, HP-UX 11.31, Solaris 9, in programs that are not linked
    dnl with -lpthread, the pthread_sigmask() function always returns 0 and has
    dnl no effect.
    if test -z "$LIB_PTHREAD_SIGMASK"; then
118
      case " $LIBS " in
Paul Eggert's avatar
Paul Eggert committed
119
        *' -pthread '*) ;;
120
        *' -lpthread '*) ;;
Paul Eggert's avatar
Paul Eggert committed
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
        *)
          AC_CACHE_CHECK([whether pthread_sigmask works without -lpthread],
            [gl_cv_func_pthread_sigmask_in_libc_works],
            [
              AC_RUN_IFELSE(
                [AC_LANG_SOURCE([[
                   #include <pthread.h>
                   #include <signal.h>
                   #include <stddef.h>
                   int main ()
                   {
                     sigset_t set;
                     sigemptyset (&set);
                     return pthread_sigmask (1729, &set, NULL) != 0;
                   }]])],
                [gl_cv_func_pthread_sigmask_in_libc_works=no],
                [gl_cv_func_pthread_sigmask_in_libc_works=yes],
                [
                 changequote(,)dnl
                 case "$host_os" in
                   freebsd* | hpux* | solaris | solaris2.[2-9]*)
                     gl_cv_func_pthread_sigmask_in_libc_works="guessing no";;
                   *)
                     gl_cv_func_pthread_sigmask_in_libc_works="guessing yes";;
                 esac
                 changequote([,])dnl
                ])
            ])
          case "$gl_cv_func_pthread_sigmask_in_libc_works" in
            *no)
              REPLACE_PTHREAD_SIGMASK=1
              AC_DEFINE([PTHREAD_SIGMASK_INEFFECTIVE], [1],
                [Define to 1 if pthread_sigmask may return 0 and have no effect.])
              ;;
          esac;;
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
      esac
    fi

    dnl On Cygwin 1.7.5, the pthread_sigmask() has a wrong return value
    dnl convention: Upon failure, it returns -1 and sets errno.
    AC_CACHE_CHECK([whether pthread_sigmask returns error numbers],
      [gl_cv_func_pthread_sigmask_return_works],
      [
        gl_save_LIBS="$LIBS"
        LIBS="$LIBS $LIB_PTHREAD_SIGMASK"
        AC_RUN_IFELSE(
          [AC_LANG_SOURCE([[
#include <pthread.h>
#include <signal.h>
#include <stddef.h>
int main ()
{
  sigset_t set;
  sigemptyset (&set);
  if (pthread_sigmask (1729, &set, NULL) == -1)
    return 1;
  return 0;
}]])],
          [gl_cv_func_pthread_sigmask_return_works=yes],
          [gl_cv_func_pthread_sigmask_return_works=no],
          [case "$host_os" in
             cygwin*)
               gl_cv_func_pthread_sigmask_return_works="guessing no";;
             *)
               gl_cv_func_pthread_sigmask_return_works="guessing yes";;
           esac
          ])
        LIBS="$gl_save_LIBS"
      ])
    case "$gl_cv_func_pthread_sigmask_return_works" in
      *no)
        REPLACE_PTHREAD_SIGMASK=1
        AC_DEFINE([PTHREAD_SIGMASK_FAILS_WITH_ERRNO], [1],
          [Define to 1 if pthread_sigmask(), when it fails, returns -1 and sets errno.])
        ;;
    esac

    dnl On IRIX 6.5, in a single-threaded program, pending signals are not
    dnl immediately delivered when they are unblocked through pthread_sigmask,
    dnl only a little while later.
    AC_CACHE_CHECK([whether pthread_sigmask unblocks signals correctly],
      [gl_cv_func_pthread_sigmask_unblock_works],
      [
        case "$host_os" in
          irix*)
            gl_cv_func_pthread_sigmask_unblock_works="guessing no";;
          *)
            gl_cv_func_pthread_sigmask_unblock_works="guessing yes";;
        esac
210 211 212 213 214 215
        m4_ifdef([gl_][THREADLIB],
          [dnl Link against $LIBMULTITHREAD, not only $LIB_PTHREAD_SIGMASK.
           dnl Otherwise we get a false positive on those platforms where
           dnl $gl_cv_func_pthread_sigmask_in_libc_works is "no".
           gl_save_LIBS=$LIBS
           LIBS="$LIBS $LIBMULTITHREAD"])
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
        AC_RUN_IFELSE(
          [AC_LANG_SOURCE([[
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static volatile int sigint_occurred;
static void
sigint_handler (int sig)
{
  sigint_occurred++;
}
int main ()
{
  sigset_t set;
  int pid = getpid ();
  char command[80];
  signal (SIGINT, sigint_handler);
  sigemptyset (&set);
  sigaddset (&set, SIGINT);
  if (!(pthread_sigmask (SIG_BLOCK, &set, NULL) == 0))
    return 1;
  sprintf (command, "sh -c 'sleep 1; kill -%d %d' &", SIGINT, pid);
  if (!(system (command) == 0))
    return 2;
  sleep (2);
  if (!(sigint_occurred == 0))
    return 3;
  if (!(pthread_sigmask (SIG_UNBLOCK, &set, NULL) == 0))
    return 4;
  if (!(sigint_occurred == 1)) /* This fails on IRIX.  */
    return 5;
  return 0;
}]])],
          [:],
          [gl_cv_func_pthread_sigmask_unblock_works=no],
          [:])
254
        m4_ifdef([gl_][THREADLIB], [LIBS=$gl_save_LIBS])
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
      ])
    case "$gl_cv_func_pthread_sigmask_unblock_works" in
      *no)
        REPLACE_PTHREAD_SIGMASK=1
        AC_DEFINE([PTHREAD_SIGMASK_UNBLOCK_BUG], [1],
          [Define to 1 if pthread_sigmask() unblocks signals incorrectly.])
        ;;
    esac
  fi
])

# Prerequisite of lib/pthread_sigmask.c.
AC_DEFUN([gl_PREREQ_PTHREAD_SIGMASK],
[
  if test $HAVE_PTHREAD_SIGMASK = 1; then
    AC_DEFINE([HAVE_PTHREAD_SIGMASK], [1],
      [Define to 1 if the pthread_sigmask function can be used (despite bugs).])
  fi
273
])