pthread_sigmask.c 2.2 KB

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