tst-vfork-longjmp.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  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. static 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. static 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. _exit(ret);
  47. } else if (child == 1)
  48. return 1;
  49. wait(&status);
  50. return WEXITSTATUS(status);
  51. }
  52. int main(int argc, char *argv[])
  53. {
  54. const char *prog;
  55. jmp_buf env;
  56. sigjmp_buf sigenv;
  57. int max;
  58. /* values modified between setjmp/longjmp cannot be local to this func */
  59. static int cnt, ret;
  60. memset(&orig_mask, 0x00, sizeof(orig_mask));
  61. ret = sigprocmask(SIG_BLOCK, NULL, &orig_mask);
  62. if (ret != 0) {
  63. perror("could not get orig sig block mask");
  64. return 1;
  65. }
  66. prog = (argc > 1 ? argv[1] : "true");
  67. ret = 0;
  68. verbose = 0;
  69. max = 10;
  70. /* test vfork()/exec() inside of sigsetjmp/siglongjmp */
  71. cnt = 0;
  72. sigsetjmp(sigenv, 1);
  73. ++cnt;
  74. if (verbose)
  75. printf("sigsetjmp loop %i\n", cnt);
  76. ret |= check_sig_mask();
  77. ret |= execute_child(prog);
  78. if (cnt < max)
  79. siglongjmp(sigenv, 0);
  80. /* test vfork()/sigprocmask() inside of setjmp/longjmp */
  81. cnt = 0;
  82. setjmp(env);
  83. ++cnt;
  84. if (verbose)
  85. printf("setjmp loop %i\n", cnt);
  86. ret |= check_sig_mask();
  87. ret |= execute_child(prog);
  88. if (cnt < max)
  89. longjmp(env, 0);
  90. return ret;
  91. }