signal.c 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. /* -*-comment-start: "//";comment-end:""-*-
  2. * GNU Mes --- Maxwell Equations of Software
  3. * Copyright © 2018,2019 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
  4. *
  5. * This file is part of GNU Mes.
  6. *
  7. * GNU Mes is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 3 of the License, or (at
  10. * your option) any later version.
  11. *
  12. * GNU Mes is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with GNU Mes. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #include <linux/syscall.h>
  21. #include <syscall.h>
  22. #include <unistd.h>
  23. #include <signal.h>
  24. #if __i386__
  25. #else
  26. void
  27. _restorer_for_siginfo (void)
  28. {
  29. _sys_call (SYS_rt_sigreturn);
  30. }
  31. #endif
  32. sighandler_t
  33. signal (int signum, sighandler_t action)
  34. {
  35. #if __i386__
  36. return _sys_call2 (SYS_signal, signum, action);
  37. #else
  38. static struct sigaction setup_action = { 0 };
  39. static struct sigaction old = { 0 };
  40. unsigned short bitindex;
  41. unsigned short itembitcount;
  42. setup_action.sa_handler = action;
  43. /* The sa_restorer is not used. Reason:
  44. * The kernel uses its own restorer anyway by pretending we gave one on
  45. our side (no, really).
  46. glibc still has a custom restorer because they want to be able to
  47. backtrace. gdb has a second part that detects a specific instruction
  48. sequence and then fixes up the backtrace. Since we don't use that
  49. specific instruction sequence and also the non-siginfo restorer
  50. is complicated (pops foreign item off the stack--so needs inline
  51. assembly) and we don't support great debuggability in other places,
  52. I've decided to take the easy way out for now. */
  53. /*setup_action.sa_restorer = _restorer_for_siginfo;*/
  54. bitindex = signum - 1;
  55. itembitcount = 8 * sizeof (setup_action.sa_mask.items[0]);
  56. setup_action.sa_mask.items[bitindex / itembitcount] = 1UL << (bitindex % itembitcount);
  57. old.sa_handler = SIG_DFL;
  58. setup_action.sa_flags = SA_RESTART;
  59. #if __x86_64__
  60. /* Tell kernel that we use a restorer, on penalty of segfault. */
  61. setup_action.sa_flags |= SA_RESTORER;
  62. #endif
  63. int r = _sys_call4 (SYS_rt_sigaction, signum, (long) &setup_action, (long) &old, sizeof (sigset_t));
  64. if (r)
  65. return 0;
  66. return old.sa_handler;
  67. #endif
  68. }