tst-vfork-longjmp.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. /* make sure we can vfork/exec across setjmp/longjmp's
  2. * and make sure signal block masks don't get corrupted
  3. * in the process.
  4. */
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <assert.h>
  8. #include <unistd.h>
  9. #include <errno.h>
  10. #include <setjmp.h>
  11. #include <signal.h>
  12. #include <sys/types.h>
  13. #include <sys/wait.h>
  14. #include <string.h>
  15. int verbose = 0;
  16. int execute_child(const char *prog)
  17. {
  18. int status;
  19. pid_t child;
  20. child = vfork();
  21. if (child == 0) {
  22. execlp(prog, prog, NULL);
  23. perror("Could not execute specified prog");
  24. _exit(1);
  25. } else if (child == 1)
  26. return 1;
  27. wait(&status);
  28. return WEXITSTATUS(status);
  29. }
  30. sigset_t orig_mask;
  31. int check_sig_mask(void)
  32. {
  33. int status;
  34. pid_t child;
  35. child = vfork();
  36. if (child == 0) {
  37. int ret;
  38. sigset_t child_mask;
  39. memset(&child_mask, 0x00, sizeof(child_mask));
  40. ret = sigprocmask(SIG_BLOCK, NULL, &child_mask);
  41. if (ret != 0) {
  42. perror("could not get child sig block mask");
  43. _exit(1);
  44. }
  45. ret = memcmp(&orig_mask, &child_mask, sizeof(orig_mask));
  46. if (verbose) {
  47. printf("sigmsk: %08lx%08lx ", child_mask.__val[1], child_mask.__val[0]);
  48. printf("sigmsk: %08lx%08lx ", orig_mask.__val[1], orig_mask.__val[0]);
  49. printf("%i\n", ret);
  50. }
  51. _exit(ret);
  52. } else if (child == 1)
  53. return 1;
  54. wait(&status);
  55. return WEXITSTATUS(status);
  56. }
  57. int main(int argc, char *argv[])
  58. {
  59. const char *prog;
  60. jmp_buf env;
  61. sigjmp_buf sigenv;
  62. int max;
  63. /* values modified between setjmp/longjmp cannot be local to this func */
  64. static int cnt, ret;
  65. memset(&orig_mask, 0x00, sizeof(orig_mask));
  66. ret = sigprocmask(SIG_BLOCK, NULL, &orig_mask);
  67. if (ret != 0) {
  68. perror("could not get orig sig block mask");
  69. return 1;
  70. }
  71. prog = (argc > 1 ? argv[1] : "true");
  72. ret = 0;
  73. verbose = 0;
  74. max = 10;
  75. /* test vfork()/exec() inside of sigsetjmp/siglongjmp */
  76. cnt = 0;
  77. sigsetjmp(sigenv, 1);
  78. ++cnt;
  79. if (verbose)
  80. printf("sigsetjmp loop %i\n", cnt);
  81. ret |= check_sig_mask();
  82. ret |= execute_child(prog);
  83. if (cnt < max)
  84. siglongjmp(sigenv, 0);
  85. /* test vfork()/sigprocmask() inside of setjmp/longjmp */
  86. cnt = 0;
  87. setjmp(env);
  88. ++cnt;
  89. if (verbose)
  90. printf("setjmp loop %i\n", cnt);
  91. ret |= check_sig_mask();
  92. ret |= execute_child(prog);
  93. if (cnt < max)
  94. longjmp(env, 0);
  95. return ret;
  96. }