dispatch_proc.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /*
  2. * Copyright (c) 2008-2011 Apple Inc. All rights reserved.
  3. *
  4. * @APPLE_APACHE_LICENSE_HEADER_START@
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. *
  18. * @APPLE_APACHE_LICENSE_HEADER_END@
  19. */
  20. #include <dispatch/dispatch.h>
  21. #include <stdio.h>
  22. #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
  23. #include <unistd.h>
  24. #endif
  25. #include <stdlib.h>
  26. #include <assert.h>
  27. #include <spawn.h>
  28. #include <signal.h>
  29. #ifdef __APPLE__
  30. #include <libkern/OSAtomic.h>
  31. #endif
  32. #include <bsdtests.h>
  33. #include "dispatch_test.h"
  34. #define PID_CNT 5
  35. static long event_cnt;
  36. void
  37. test_proc(pid_t bad_pid)
  38. {
  39. dispatch_source_t proc_s[PID_CNT], proc;
  40. int res;
  41. pid_t pid, monitor_pid;
  42. event_cnt = 0;
  43. // Creates a process and register multiple observers. Send a signal,
  44. // exit the process, etc., and verify all observers were notified.
  45. posix_spawnattr_t attr;
  46. res = posix_spawnattr_init(&attr);
  47. assert(res == 0);
  48. res = posix_spawnattr_setflags(&attr, POSIX_SPAWN_START_SUSPENDED);
  49. assert(res == 0);
  50. char* args[] = {
  51. "/bin/sleep", "2", NULL
  52. };
  53. res = posix_spawnp(&pid, args[0], NULL, &attr, args, NULL);
  54. if (res < 0) {
  55. perror(args[0]);
  56. exit(127);
  57. }
  58. res = posix_spawnattr_destroy(&attr);
  59. assert(res == 0);
  60. dispatch_group_t group = dispatch_group_create();
  61. assert(pid > 0);
  62. monitor_pid = bad_pid ? bad_pid : pid; // rdar://problem/8090801
  63. int i;
  64. for (i = 0; i < PID_CNT; ++i) {
  65. dispatch_group_enter(group);
  66. proc = proc_s[i] = dispatch_source_create(DISPATCH_SOURCE_TYPE_PROC,
  67. monitor_pid, DISPATCH_PROC_EXIT, dispatch_get_global_queue(0, 0));
  68. test_ptr_notnull("dispatch_source_proc_create", proc);
  69. dispatch_source_set_event_handler(proc, ^{
  70. long flags = dispatch_source_get_data(proc);
  71. test_long("DISPATCH_PROC_EXIT", flags, DISPATCH_PROC_EXIT);
  72. event_cnt++;
  73. dispatch_source_cancel(proc);
  74. });
  75. dispatch_source_set_cancel_handler(proc, ^{
  76. dispatch_group_leave(group);
  77. });
  78. dispatch_resume(proc);
  79. }
  80. kill(pid, SIGCONT);
  81. if (dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, 10*NSEC_PER_SEC))) {
  82. for (i = 0; i < PID_CNT; ++i) {
  83. dispatch_source_cancel(proc_s[i]);
  84. }
  85. dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
  86. }
  87. for (i = 0; i < PID_CNT; ++i) {
  88. dispatch_release(proc_s[i]);
  89. }
  90. dispatch_release(group);
  91. // delay 5 seconds to give a chance for any bugs that
  92. // result in too many events to be noticed
  93. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5*NSEC_PER_SEC), dispatch_get_main_queue(), ^{
  94. int status;
  95. int res2 = waitpid(pid, &status, 0);
  96. assert(res2 != -1);
  97. //int passed = (WIFEXITED(status) && WEXITSTATUS(status) == 0);
  98. test_long("Sub-process exited", WEXITSTATUS(status) | WTERMSIG(status), 0);
  99. test_long("Event count", event_cnt, PID_CNT);
  100. if (bad_pid) {
  101. test_stop();
  102. } else {
  103. dispatch_async(dispatch_get_main_queue(), ^{
  104. test_proc(pid);
  105. });
  106. }
  107. });
  108. }
  109. int
  110. main(void)
  111. {
  112. dispatch_test_start("Dispatch Proc");
  113. test_proc(0);
  114. dispatch_main();
  115. return 0;
  116. }