Guest User

Untitled

a guest
Dec 17th, 2017
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.46 KB | None | 0 0
  1. #include <sys/types.h>
  2. #include <sys/event.h>
  3. #include <sys/time.h>
  4. #include <sys/wait.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <signal.h>
  8. #include <unistd.h>
  9.  
  10. // Program to demonstrate kqueue bug on macOS (Sierra, possibly others). The
  11. // kqueue mechanism can sometimes reports that a SIGCHLD signal has been
  12. // received, but the signal does not yet report as pending.
  13. //
  14. // Running this program will output a message similar to the following, if the
  15. // bug is present:
  16. //
  17. // Received SIGCHLD kevent but SIGCHLD is not (yet) pending; i = 273
  18. //
  19. // (The number is the number of loop iterations before the bug was hit).
  20.  
  21. void errout(const char * s)
  22. {
  23. perror(s);
  24. exit(1);
  25. }
  26.  
  27. void sighandler(int signo)
  28. {
  29.  
  30. }
  31.  
  32. int main(int argc, char **argv)
  33. {
  34. int kq = kqueue();
  35. if (kq == -1) errout("kqueue");
  36.  
  37. // Mask SIGCHLD (but establish a handler):
  38. sigset_t sigset;
  39. sigemptyset(&sigset);
  40. sigaddset(&sigset, SIGCHLD);
  41. sigprocmask(SIG_BLOCK, &sigset, NULL);
  42.  
  43. struct sigaction sa;
  44. sa.sa_handler = sighandler;
  45. sigfillset(&sa.sa_mask);
  46. sa.sa_flags = 0;
  47. if (sigaction(SIGCHLD, &sa, NULL) == -1) errout("sigaction");
  48.  
  49. struct timespec timeout;
  50. timeout.tv_nsec = 0;
  51. timeout.tv_sec = 0;
  52.  
  53. // Set up kqueue to report SIGCHLD:
  54. struct kevent kev;
  55. EV_SET(&kev, SIGCHLD, EVFILT_SIGNAL, EV_ADD, 0, 0, 0);
  56. if (kevent(kq, &kev, 1, NULL, 0, &timeout) == -1) errout("kevent");
  57.  
  58. for (int i = 0; i < 10000; i++) {
  59. // Fork a child, which immediately exits, to generate SIGCHLD:
  60. pid_t child = fork();
  61. if (child == 0) {
  62. _exit(0);
  63. }
  64.  
  65. // Retrieve event from kqueue, and make sure it refers to the SIGCHLD:
  66. int r;
  67. if ((r = kevent(kq, NULL, 0, &kev, 1, NULL)) == -1) errout("kevent");
  68. if (r != 1) {
  69. fprintf(stderr, "kevent: didn't receive one event?\n");
  70. exit(1);
  71. }
  72.  
  73. if (kev.filter != EVFILT_SIGNAL || kev.ident != SIGCHLD) {
  74. fprintf(stderr, "kevent: received wrong event?\n");
  75. exit(1);
  76. }
  77.  
  78. // Now confirm that SIGCHLD is actually pending:
  79. sigset_t pendingsigs;
  80. sigpending(&pendingsigs);
  81. if (! sigismember(&pendingsigs, SIGCHLD)) {
  82. fprintf(stderr, "Received SIGCHLD kevent but SIGCHLD is not (yet) pending; i = %d\n", i);
  83. exit(1);
  84. }
  85.  
  86. int signo;
  87. sigwait(&sigset, &signo);
  88. int status;
  89. wait(&status);
  90. }
  91.  
  92. return 0;
  93. }
Add Comment
Please, Sign In to add comment