abort.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /* Copyright (C) 1991-2019 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. The GNU C Library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Lesser General Public
  5. License as published by the Free Software Foundation; either
  6. version 2.1 of the License, or (at your option) any later version.
  7. The GNU C Library 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 GNU
  10. Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public
  12. License along with the GNU C Library; if not, see
  13. <http://www.gnu.org/licenses/>. */
  14. #include <libc-lock.h>
  15. #include <signal.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <unistd.h>
  20. #include <sigsetops.h>
  21. /* Try to get a machine dependent instruction which will make the
  22. program crash. This is used in case everything else fails. */
  23. #include <abort-instr.h>
  24. #ifndef ABORT_INSTRUCTION
  25. /* No such instruction is available. */
  26. # define ABORT_INSTRUCTION
  27. #endif
  28. /* Exported variable to locate abort message in core files etc. */
  29. struct abort_msg_s *__abort_msg __attribute__ ((nocommon));
  30. libc_hidden_def (__abort_msg)
  31. /* We must avoid to run in circles. Therefore we remember how far we
  32. already got. */
  33. static int stage;
  34. /* We should be prepared for multiple threads trying to run abort. */
  35. __libc_lock_define_initialized_recursive (static, lock);
  36. /* Cause an abnormal program termination with core-dump. */
  37. void
  38. abort (void)
  39. {
  40. struct sigaction act;
  41. sigset_t sigs;
  42. /* First acquire the lock. */
  43. __libc_lock_lock_recursive (lock);
  44. /* Now it's for sure we are alone. But recursive calls are possible. */
  45. /* Unblock SIGABRT. */
  46. if (stage == 0)
  47. {
  48. ++stage;
  49. __sigemptyset (&sigs);
  50. __sigaddset (&sigs, SIGABRT);
  51. __sigprocmask (SIG_UNBLOCK, &sigs, 0);
  52. }
  53. /* Send signal which possibly calls a user handler. */
  54. if (stage == 1)
  55. {
  56. /* This stage is special: we must allow repeated calls of
  57. `abort' when a user defined handler for SIGABRT is installed.
  58. This is risky since the `raise' implementation might also
  59. fail but I don't see another possibility. */
  60. int save_stage = stage;
  61. stage = 0;
  62. __libc_lock_unlock_recursive (lock);
  63. raise (SIGABRT);
  64. __libc_lock_lock_recursive (lock);
  65. stage = save_stage + 1;
  66. }
  67. /* There was a handler installed. Now remove it. */
  68. if (stage == 2)
  69. {
  70. ++stage;
  71. memset (&act, '\0', sizeof (struct sigaction));
  72. act.sa_handler = SIG_DFL;
  73. __sigfillset (&act.sa_mask);
  74. act.sa_flags = 0;
  75. __sigaction (SIGABRT, &act, NULL);
  76. }
  77. /* Try again. */
  78. if (stage == 3)
  79. {
  80. ++stage;
  81. raise (SIGABRT);
  82. }
  83. /* Now try to abort using the system specific command. */
  84. if (stage == 4)
  85. {
  86. ++stage;
  87. ABORT_INSTRUCTION;
  88. }
  89. /* If we can't signal ourselves and the abort instruction failed, exit. */
  90. if (stage == 5)
  91. {
  92. ++stage;
  93. _exit (127);
  94. }
  95. /* If even this fails try to use the provided instruction to crash
  96. or otherwise make sure we never return. */
  97. while (1)
  98. /* Try for ever and ever. */
  99. ABORT_INSTRUCTION;
  100. }
  101. libc_hidden_def (abort)