]> code.delx.au - gnu-emacs/blob - lib/pthread_sigmask.c
Merge from trunk.
[gnu-emacs] / lib / pthread_sigmask.c
1 /* POSIX compatible signal blocking for threads.
2 Copyright (C) 2011 Free Software Foundation, Inc.
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18
19 /* Specification. */
20 #include <signal.h>
21
22 #include <errno.h>
23 #include <stddef.h>
24
25 #if PTHREAD_SIGMASK_UNBLOCK_BUG
26 # include <unistd.h>
27 #endif
28
29 int
30 pthread_sigmask (int how, const sigset_t *new_mask, sigset_t *old_mask)
31 #undef pthread_sigmask
32 {
33 #if HAVE_PTHREAD_SIGMASK
34 int ret = pthread_sigmask (how, new_mask, old_mask);
35 # if PTHREAD_SIGMASK_INEFFECTIVE
36 if (ret == 0)
37 {
38 /* Detect whether pthread_sigmask is currently ineffective.
39 Don't cache the information: libpthread.so could be dynamically
40 loaded after the program started and after pthread_sigmask was
41 called for the first time. */
42 if (pthread_sigmask (1729, NULL, NULL) == 0)
43 {
44 /* pthread_sigmask is currently ineffective. The program is not
45 linked to -lpthread. So use sigprocmask instead. */
46 return (sigprocmask (how, new_mask, old_mask) < 0 ? errno : 0);
47 }
48 }
49 # endif
50 # if PTHREAD_SIGMASK_FAILS_WITH_ERRNO
51 if (ret == -1)
52 return errno;
53 # endif
54 # if PTHREAD_SIGMASK_UNBLOCK_BUG
55 if (ret == 0
56 && new_mask != NULL
57 && (how == SIG_UNBLOCK || how == SIG_SETMASK))
58 {
59 /* Give the OS the opportunity to raise signals that were pending before
60 the pthread_sigmask call and have now been unblocked. */
61 usleep (1);
62 }
63 # endif
64 return ret;
65 #else
66 int ret = sigprocmask (how, new_mask, old_mask);
67 return (ret < 0 ? errno : 0);
68 #endif
69 }