Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

367 lines
6.8 KiB

  1. #include <nt.h>
  2. #include <ntrtl.h>
  3. #include <signal.h>
  4. #include <errno.h>
  5. #include <sys/wait.h>
  6. #include <unistd.h>
  7. #include <fcntl.h>
  8. #include "tsttmp.h" // defines DbgPrint as printf
  9. extern int errno;
  10. VOID jc0(VOID);
  11. VOID jc1(VOID);
  12. VOID jc2(VOID);
  13. VOID jc3(VOID);
  14. int
  15. main(int argc, char *argv[])
  16. {
  17. pid_t self;
  18. PCH p,t;
  19. PTEB ThreadInfo;
  20. ThreadInfo = NtCurrentTeb();
  21. self = getpid();
  22. DbgPrint("jc: My pid is %lx Argc = %lx\n",self,argc);
  23. DbgPrint("jc: StackBase %lx\n",ThreadInfo->NtTib.StackBase);
  24. DbgPrint("jc: StackLimit %lx\n",ThreadInfo->NtTib.StackLimit);
  25. DbgPrint("jc: ClientId %lx.%lx\n",ThreadInfo->ClientId.UniqueProcess,ThreadInfo->ClientId.UniqueThread);
  26. while(argc--){
  27. p = *argv++;
  28. t = p;
  29. while(*t++);
  30. DbgPrint("Argv --> %s\n",p);
  31. }
  32. jc0();
  33. jc1();
  34. jc2();
  35. jc3();
  36. return 1;
  37. }
  38. VOID
  39. jc0()
  40. {
  41. pid_t child;
  42. int rc,stat_loc;
  43. struct sigaction act;
  44. DbgPrint("jc0:++\n");
  45. //
  46. // Ignore SIGCHLD signals
  47. //
  48. act.sa_flags = SA_NOCLDSTOP;
  49. act.sa_handler = SIG_IGN;
  50. rc = sigaction(SIGCHLD, &act, NULL);
  51. ASSERT( rc == 0 );
  52. child = fork();
  53. if ( !child) {
  54. for(;;);
  55. ASSERT(0 != 0);
  56. }
  57. rc = kill(child,SIGSTOP);
  58. ASSERT(rc==0);
  59. //
  60. // Make sure that wait is satisfied by stopped child
  61. //
  62. rc = waitpid(child,&stat_loc,WUNTRACED);
  63. ASSERT(rc == child && WIFSTOPPED(stat_loc) && WSTOPSIG(stat_loc) == SIGSTOP);
  64. //
  65. // Also make sure that it's status may only be picked up once
  66. //
  67. rc = waitpid(child,NULL,WUNTRACED | WNOHANG);
  68. ASSERT(rc == 0);
  69. //
  70. // SEGV the process. Since it is stopped, this should have no effect
  71. //
  72. rc = kill(child,SIGSEGV);
  73. ASSERT(rc==0);
  74. rc = waitpid(child,NULL,WUNTRACED | WNOHANG);
  75. ASSERT(rc == 0);
  76. //
  77. // Kill the process w/ SIGKILL. This should doit
  78. //
  79. rc = kill(child,SIGKILL);
  80. ASSERT(rc==0);
  81. rc = waitpid(child,&stat_loc,0);
  82. ASSERT(rc == child && WIFSIGNALED(stat_loc) && WTERMSIG(stat_loc) == SIGKILL);
  83. DbgPrint("jc0:--\n");
  84. }
  85. int thechild;
  86. void
  87. jc1_sigchld_handler(
  88. IN int sig
  89. )
  90. {
  91. int rc, stat_loc;
  92. struct sigaction act;
  93. ASSERT(sig == SIGCHLD);
  94. rc = waitpid(thechild,&stat_loc,0);
  95. ASSERT(rc == thechild && WIFEXITED(stat_loc) && WEXITSTATUS(stat_loc) == 100);
  96. act.sa_flags = 0;
  97. sigfillset(&act.sa_mask);
  98. act.sa_handler = SIG_IGN;
  99. rc = sigaction(SIGCHLD, &act, NULL);
  100. ASSERT( rc == 0 );
  101. }
  102. void
  103. jc1_sigcont_handler(
  104. IN int sig
  105. )
  106. {
  107. ASSERT(sig == SIGCONT);
  108. _exit(100);
  109. }
  110. VOID
  111. jc1()
  112. {
  113. int rc,stat_loc;
  114. struct sigaction act;
  115. sigset_t set,oset;
  116. DbgPrint("jc1:++\n");
  117. //
  118. // Catch SIGCHLD signals
  119. //
  120. act.sa_flags = 0;
  121. sigfillset(&act.sa_mask);
  122. act.sa_handler = jc1_sigchld_handler;
  123. rc = sigaction(SIGCHLD, &act, NULL);
  124. ASSERT( rc == 0 );
  125. //
  126. // Catch SIGCONT. This is really set up for Child
  127. //
  128. act.sa_flags = 0;
  129. sigfillset(&act.sa_mask);
  130. act.sa_handler = jc1_sigcont_handler;
  131. rc = sigaction(SIGCONT, &act, NULL);
  132. ASSERT( rc == 0 );
  133. thechild = fork();
  134. if ( !thechild) {
  135. for(;;);
  136. _exit(99);
  137. ASSERT(0 != 0);
  138. }
  139. //
  140. // Block SIGCHLD
  141. //
  142. sigfillset(&set);
  143. rc = sigprocmask(SIG_SETMASK,&set,&oset);
  144. ASSERT(rc==0);
  145. rc = kill(thechild,SIGSTOP);
  146. ASSERT(rc==0);
  147. //
  148. // Make sure that wait is satisfied by stopped child
  149. //
  150. rc = waitpid(thechild,&stat_loc,WUNTRACED);
  151. ASSERT(rc == thechild && WIFSTOPPED(stat_loc) && WSTOPSIG(stat_loc) == SIGSTOP);
  152. //
  153. // SIGCONT the process.
  154. //
  155. rc = kill(thechild,SIGCONT);
  156. ASSERT(rc==0);
  157. //
  158. // Unblock SIGCHLD
  159. //
  160. rc = sigprocmask(SIG_SETMASK,&oset,NULL);
  161. ASSERT(rc==0);
  162. rc = waitpid(thechild,&stat_loc,WUNTRACED);
  163. ASSERT( rc == -1 && errno == ECHILD);
  164. act.sa_flags = 0;
  165. sigfillset(&act.sa_mask);
  166. act.sa_handler = SIG_DFL;
  167. rc = sigaction(SIGCONT, &act, NULL);
  168. DbgPrint("jc1:--\n");
  169. }
  170. VOID
  171. jc2()
  172. {
  173. pid_t child, OrigGroup;
  174. int rc,stat_loc;
  175. DbgPrint("jc2:++\n");
  176. OrigGroup = getpgrp();
  177. //
  178. // Should be process group leader
  179. //
  180. ASSERT(getpid() == OrigGroup);
  181. //
  182. // Fork. Then have child establish its own group.
  183. // Child and parent are in then in different groups,
  184. // but in the same session.
  185. //
  186. if ( !fork() ) {
  187. rc = setpgid(0,0);
  188. ASSERT(rc==0 && getpgrp() == getpid());
  189. child = fork();
  190. if ( !child ) {
  191. rc = kill(getpid(),SIGSTOP);
  192. ASSERT(rc==0);
  193. }
  194. rc = waitpid(child,&stat_loc,WUNTRACED);
  195. ASSERT(rc == child && WIFSTOPPED(stat_loc) && WSTOPSIG(stat_loc) == SIGSTOP);
  196. //
  197. // Conditions are set. If this process exits, then its group
  198. // will zombie. Stopped process should continue w/ SIGCONT/SIGHUP
  199. //
  200. _exit(123);
  201. }
  202. rc = wait(&stat_loc);
  203. ASSERT(WIFEXITED(stat_loc) && WEXITSTATUS(stat_loc) == 123);
  204. sleep(10);
  205. DbgPrint("jc2:--\n");
  206. }
  207. VOID
  208. jc3()
  209. {
  210. pid_t child, OrigGroup;
  211. int rc,stat_loc;
  212. DbgPrint("jc3:++\n");
  213. OrigGroup = getpgrp();
  214. //
  215. // Should be process group leader
  216. //
  217. ASSERT(getpid() == OrigGroup);
  218. //
  219. // Fork. Then have child establish its own group.
  220. // Child and parent are in then in different groups,
  221. // but in the same session.
  222. //
  223. if ( !fork() ) {
  224. rc = setpgid(0,0);
  225. ASSERT(rc==0 && getpgrp() == getpid());
  226. child = fork();
  227. if ( !child ) {
  228. struct sigaction act;
  229. //
  230. // Child should ignore SIGHUP
  231. //
  232. act.sa_flags = SA_NOCLDSTOP;
  233. act.sa_handler = SIG_IGN;
  234. rc = sigaction(SIGHUP, &act, NULL);
  235. ASSERT( rc == 0 );
  236. rc = kill(getpid(),SIGSTOP);
  237. ASSERT(rc==0);
  238. //
  239. // parents exit SIGCONTs child. At this point child
  240. // is part of an orphaned process group. The process
  241. // should not stop in response to SIGTSTP, SIGTTIN,
  242. // or SIGTTOU
  243. //
  244. rc = kill(getpid(),SIGTSTP);
  245. ASSERT(rc==0);
  246. rc = kill(getpid(),SIGTTIN);
  247. ASSERT(rc==0);
  248. rc = kill(getpid(),SIGTTOU);
  249. ASSERT(rc==0);
  250. _exit(8);
  251. }
  252. rc = waitpid(child,&stat_loc,WUNTRACED);
  253. ASSERT(rc == child && WIFSTOPPED(stat_loc) && WSTOPSIG(stat_loc) == SIGSTOP);
  254. //
  255. // Conditions are set. If this process exits, then its group
  256. // will zombie. Stopped process should continue w/ SIGCONT/SIGHUP
  257. //
  258. _exit(123);
  259. }
  260. rc = wait(&stat_loc);
  261. ASSERT(WIFEXITED(stat_loc) && WEXITSTATUS(stat_loc) == 123);
  262. sleep(10);
  263. DbgPrint("jc3:--\n");
  264. }