sigaltstack.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. #define _XOPEN_SOURCE 700
  2. #include <err.h>
  3. #include <inttypes.h>
  4. #include <signal.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <unistd.h>
  9. uint8_t* sig_stack;
  10. size_t sig_stack_size = SIGSTKSZ;
  11. _Atomic int count = 0;
  12. void handler(int signal, siginfo_t* info, void* ucontext) {
  13. int ret;
  14. count++;
  15. uint8_t a;
  16. printf("sig %d count %d goes off with sp=%p, sig_stack: [%p, %p)\n", signal, count, &a,
  17. sig_stack, sig_stack + sig_stack_size);
  18. if (sig_stack <= &a && &a < sig_stack + sig_stack_size) {
  19. printf("OK on signal stack\n");
  20. } else {
  21. printf("FAIL out of signal stack\n");
  22. }
  23. fflush(stdout);
  24. stack_t old;
  25. memset(&old, 0, sizeof(old));
  26. ret = sigaltstack(NULL, &old);
  27. if (ret < 0) {
  28. err(EXIT_FAILURE, "sigaltstack in handler");
  29. }
  30. if (old.ss_flags & SS_ONSTACK) {
  31. printf("OK on sigaltstack in handler\n");
  32. } else {
  33. printf("FAIL on sigaltstack in handler\n");
  34. }
  35. /*
  36. * raise SIGALRM during signal handling to test nested signals
  37. * (three-levels deep nesting just to be sure)
  38. */
  39. if (count <= 2) {
  40. sigset_t set;
  41. sigemptyset(&set);
  42. sigaddset(&set, SIGALRM);
  43. ret = sigprocmask(SIG_UNBLOCK, &set, NULL);
  44. if (ret) {
  45. err(EXIT_FAILURE, "sigprocmask");
  46. }
  47. raise(SIGALRM);
  48. }
  49. count--;
  50. }
  51. int main(int argc, char** argv) {
  52. int ret;
  53. sig_stack = malloc(sig_stack_size);
  54. if (sig_stack == NULL) {
  55. err(EXIT_FAILURE, "malloc");
  56. }
  57. stack_t ss = {
  58. .ss_sp = sig_stack,
  59. .ss_flags = 0,
  60. .ss_size = sig_stack_size,
  61. };
  62. stack_t old;
  63. memset(&old, 0xff, sizeof(old));
  64. ret = sigaltstack(&ss, &old);
  65. if (ret < 0) {
  66. err(EXIT_FAILURE, "sigaltstack");
  67. }
  68. if (old.ss_flags & SS_ONSTACK) {
  69. printf("FAIL on sigaltstack in main thread before alarm\n");
  70. } else {
  71. printf("OK on sigaltstack in main thread before alarm\n");
  72. }
  73. struct sigaction act;
  74. act.sa_sigaction = handler;
  75. sigemptyset(&act.sa_mask);
  76. act.sa_flags = SA_SIGINFO | SA_NODEFER | SA_ONSTACK;
  77. ret = sigaction(SIGALRM, &act, NULL);
  78. if (ret < 0) {
  79. err(EXIT_FAILURE, "sigaction");
  80. }
  81. printf("&act == %p\n", &act);
  82. fflush(stdout);
  83. alarm(1);
  84. pause();
  85. memset(&old, 0xff, sizeof(old));
  86. ret = sigaltstack(NULL, &old);
  87. if (ret < 0) {
  88. err(EXIT_FAILURE, "sigaltstack");
  89. }
  90. if (old.ss_flags & SS_ONSTACK) {
  91. printf("FAIL on sigaltstack in main thread\n");
  92. } else {
  93. printf("OK on sigaltstack in main thread\n");
  94. }
  95. printf("done exiting\n");
  96. fflush(stdout);
  97. return 0;
  98. }