sigtest.c 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957
  1. /*++
  2. Copyright (c) 2013 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. sigtest.c
  9. Abstract:
  10. This module implements the tests used to verify that user mode signals are
  11. functioning properly.
  12. Author:
  13. Evan Green 31-Mar-2013
  14. Environment:
  15. User Mode
  16. --*/
  17. //
  18. // ------------------------------------------------------------------- Includes
  19. //
  20. #include <minoca/lib/minocaos.h>
  21. #include <alloca.h>
  22. #include <assert.h>
  23. #include <errno.h>
  24. #include <fcntl.h>
  25. #include <getopt.h>
  26. #include <pthread.h>
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <sys/wait.h>
  30. #include <ucontext.h>
  31. #include <unistd.h>
  32. //
  33. // --------------------------------------------------------------------- Macros
  34. //
  35. #define DEBUG_PRINT(...) \
  36. if (SignalTestVerbosity >= TestVerbosityDebug) { \
  37. printf(__VA_ARGS__); \
  38. }
  39. #define PRINT(...) \
  40. if (SignalTestVerbosity >= TestVerbosityNormal) { \
  41. printf(__VA_ARGS__); \
  42. }
  43. #define PRINT_ERROR(...) fprintf(stderr, "sigtest: " __VA_ARGS__)
  44. #define DEFAULT_OPERATION_COUNT 10
  45. #define DEFAULT_CHILD_PROCESS_COUNT 3
  46. #define DEFAULT_THREAD_COUNT 1
  47. #define SIGNAL_TEST_CONTEXT_STACK_SIZE 16384
  48. //
  49. // ---------------------------------------------------------------- Definitions
  50. //
  51. #define SIGNAL_TEST_VERSION_MAJOR 1
  52. #define SIGNAL_TEST_VERSION_MINOR 0
  53. #define SIGNAL_TEST_USAGE \
  54. "Usage: sigtest [options] \n" \
  55. "This utility hammers on signals. Options are:\n" \
  56. " -c, --child-count <count> -- Set the number of child processes.\n" \
  57. " -i, --iterations <count> -- Set the number of operations to perform.\n" \
  58. " -p, --threads <count> -- Set the number of threads to spin up to \n" \
  59. " simultaneously run the test.\n" \
  60. " -t, --test -- Set the test to perform. Valid values are all, \n" \
  61. " waitpid, sigchld, quickwait, nested, and context.\n" \
  62. " --debug -- Print lots of information about what's happening.\n" \
  63. " --quiet -- Print only errors.\n" \
  64. " --help -- Print this help text and exit.\n" \
  65. " --version -- Print the test version and exit.\n" \
  66. #define SIGNAL_TEST_OPTIONS_STRING "c:i:t:p:"
  67. //
  68. // ------------------------------------------------------ Data Type Definitions
  69. //
  70. typedef enum _TEST_VERBOSITY {
  71. TestVerbosityQuiet,
  72. TestVerbosityNormal,
  73. TestVerbosityDebug
  74. } TEST_VERBOSITY, *PTEST_VERBOSITY;
  75. typedef enum _SIGNAL_TEST_TYPE {
  76. SignalTestAll,
  77. SignalTestWaitpid,
  78. SignalTestSigchld,
  79. SignalTestQuickWait,
  80. SignalTestNested,
  81. SignalTestContext,
  82. } SIGNAL_TEST_TYPE, *PSIGNAL_TEST_TYPE;
  83. typedef enum _SIGNAL_TEST_WAIT_TYPE {
  84. SignalTestWaitBusy,
  85. SignalTestWaitSigsuspend,
  86. SignalTestWaitSigwait,
  87. SignalTestWaitSigwaitinfo,
  88. SignalTestWaitSigtimedwait,
  89. SignalTestWaitTypeCount
  90. } SIGNAL_TEST_WAIT_TYPE, *PSIGNAL_TEST_WAIT_TYPE;
  91. //
  92. // ----------------------------------------------- Internal Function Prototypes
  93. //
  94. ULONG
  95. RunWaitpidTest (
  96. ULONG Iterations
  97. );
  98. ULONG
  99. RunSigchldTest (
  100. ULONG Iterations,
  101. ULONG ChildCount
  102. );
  103. ULONG
  104. RunQuickWaitTest (
  105. ULONG Iterations,
  106. ULONG ChildCount
  107. );
  108. ULONG
  109. TestWaitpid (
  110. BOOL BurnTimeInChild,
  111. BOOL BurnTimeInParent
  112. );
  113. ULONG
  114. TestSigchild (
  115. ULONG ChildCount,
  116. ULONG ChildAdditionalThreads,
  117. SIGNAL_TEST_WAIT_TYPE WaitType,
  118. BOOL ChildrenExitVoluntarily
  119. );
  120. void
  121. TestWaitpidChildSignalHandler (
  122. int Signal,
  123. siginfo_t *SignalInformation,
  124. void *Context
  125. );
  126. void
  127. TestWaitpidProcessChildSignal (
  128. int Signal,
  129. siginfo_t *SignalInformation
  130. );
  131. void
  132. TestSigchldRealtime1SignalHandler (
  133. int Signal,
  134. siginfo_t *SignalInformation,
  135. void *Context
  136. );
  137. PVOID
  138. TestThreadSpinForever (
  139. PVOID Parameter
  140. );
  141. ULONG
  142. RunNestedSignalsTest (
  143. VOID
  144. );
  145. VOID
  146. TestNestedSignalHandler (
  147. int Signal,
  148. siginfo_t *Info,
  149. void *Ignored
  150. );
  151. ULONG
  152. RunSetContextTest (
  153. VOID
  154. );
  155. ULONG
  156. TestContextSwap (
  157. BOOL Exit
  158. );
  159. VOID
  160. TestMakecontext (
  161. ucontext_t *OldContext,
  162. ucontext_t *NextContext,
  163. INT Identifier
  164. );
  165. //
  166. // -------------------------------------------------------------------- Globals
  167. //
  168. //
  169. // Higher levels here print out more stuff.
  170. //
  171. TEST_VERBOSITY SignalTestVerbosity = TestVerbosityNormal;
  172. struct option SignalTestLongOptions[] = {
  173. {"child-count", required_argument, 0, 'c'},
  174. {"iterations", required_argument, 0, 'i'},
  175. {"threads", required_argument, 0, 'p'},
  176. {"test", required_argument, 0, 't'},
  177. {"debug", no_argument, 0, 'd'},
  178. {"quiet", no_argument, 0, 'q'},
  179. {"help", no_argument, 0, 'h'},
  180. {"version", no_argument, 0, 'V'},
  181. {NULL, 0, 0, 0},
  182. };
  183. //
  184. // These variables communicate between the signal handler and main function.
  185. //
  186. volatile ULONG ChildSignalsExpected;
  187. volatile LONG ChildSignalPid;
  188. volatile ULONG ChildSignalFailures;
  189. volatile ULONG ChildProcessesReady;
  190. int SigtestWritePipe;
  191. volatile int SigtestSignalCount[2];
  192. PSTR SignalTestWaitTypeStrings[SignalTestWaitTypeCount] = {
  193. "busy spin",
  194. "sigsuspend",
  195. "sigwait",
  196. "sigwaitinfo",
  197. "sigtimedwait"
  198. };
  199. int SigtestContextHits;
  200. //
  201. // ------------------------------------------------------------------ Functions
  202. //
  203. int
  204. main (
  205. int ArgumentCount,
  206. char **Arguments
  207. )
  208. /*++
  209. Routine Description:
  210. This routine implements the signal test program.
  211. Arguments:
  212. ArgumentCount - Supplies the number of elements in the arguments array.
  213. Arguments - Supplies an array of strings. The array count is bounded by the
  214. previous parameter, and the strings are null-terminated.
  215. Return Value:
  216. 0 on success.
  217. Non-zero on failure.
  218. --*/
  219. {
  220. PSTR AfterScan;
  221. pid_t Child;
  222. INT ChildIndex;
  223. INT ChildProcessCount;
  224. pid_t *Children;
  225. INT Failures;
  226. BOOL IsParent;
  227. INT Iterations;
  228. INT Option;
  229. INT Status;
  230. SIGNAL_TEST_TYPE Test;
  231. INT Threads;
  232. Children = NULL;
  233. Failures = 0;
  234. ChildProcessCount = DEFAULT_CHILD_PROCESS_COUNT;
  235. Iterations = DEFAULT_OPERATION_COUNT;
  236. Test = SignalTestAll;
  237. Threads = DEFAULT_THREAD_COUNT;
  238. Status = 0;
  239. setvbuf(stdout, NULL, _IONBF, 0);
  240. setvbuf(stderr, NULL, _IONBF, 0);
  241. srand(time(NULL));
  242. //
  243. // Process the control arguments.
  244. //
  245. while (TRUE) {
  246. Option = getopt_long(ArgumentCount,
  247. Arguments,
  248. SIGNAL_TEST_OPTIONS_STRING,
  249. SignalTestLongOptions,
  250. NULL);
  251. if (Option == -1) {
  252. break;
  253. }
  254. if ((Option == '?') || (Option == ':')) {
  255. Status = 1;
  256. goto MainEnd;
  257. }
  258. switch (Option) {
  259. case 'c':
  260. ChildProcessCount = strtol(optarg, &AfterScan, 0);
  261. if ((ChildProcessCount <= 0) || (AfterScan == optarg)) {
  262. PRINT_ERROR("Invalid child process count %s.\n", optarg);
  263. Status = 1;
  264. goto MainEnd;
  265. }
  266. break;
  267. case 'i':
  268. Iterations = strtol(optarg, &AfterScan, 0);
  269. if ((Iterations < 0) || (AfterScan == optarg)) {
  270. PRINT_ERROR("Invalid iteration count %s.\n", optarg);
  271. Status = 1;
  272. goto MainEnd;
  273. }
  274. break;
  275. case 'p':
  276. Threads = strtol(optarg, &AfterScan, 0);
  277. if ((Threads <= 0) || (AfterScan == optarg)) {
  278. PRINT_ERROR("Invalid thread count %s.\n", optarg);
  279. Status = 1;
  280. goto MainEnd;
  281. }
  282. break;
  283. case 't':
  284. if (strcasecmp(optarg, "all") == 0) {
  285. Test = SignalTestAll;
  286. } else if (strcasecmp(optarg, "waitpid") == 0) {
  287. Test = SignalTestWaitpid;
  288. } else if (strcasecmp(optarg, "sigchld") == 0) {
  289. Test = SignalTestSigchld;
  290. } else if (strcasecmp(optarg, "quickwait") == 0) {
  291. Test = SignalTestQuickWait;
  292. } else if (strcasecmp(optarg, "nested") == 0) {
  293. Test = SignalTestNested;
  294. } else if (strcasecmp(optarg, "context") == 0) {
  295. Test = SignalTestContext;
  296. } else {
  297. PRINT_ERROR("Invalid test: %s.\n", optarg);
  298. Status = 1;
  299. goto MainEnd;
  300. }
  301. break;
  302. case 'd':
  303. SignalTestVerbosity = TestVerbosityDebug;
  304. break;
  305. case 'q':
  306. SignalTestVerbosity = TestVerbosityQuiet;
  307. break;
  308. case 'V':
  309. printf("Minoca signal test version %d.%d\n",
  310. SIGNAL_TEST_VERSION_MAJOR,
  311. SIGNAL_TEST_VERSION_MINOR);
  312. return 1;
  313. case 'h':
  314. printf(SIGNAL_TEST_USAGE);
  315. return 1;
  316. default:
  317. assert(FALSE);
  318. Status = 1;
  319. goto MainEnd;
  320. }
  321. }
  322. IsParent = TRUE;
  323. if (Threads > 1) {
  324. Children = malloc(sizeof(pid_t) * (Threads - 1));
  325. if (Children == NULL) {
  326. Status = ENOMEM;
  327. goto MainEnd;
  328. }
  329. memset(Children, 0, sizeof(pid_t) * (Threads - 1));
  330. for (ChildIndex = 0; ChildIndex < Threads - 1; ChildIndex += 1) {
  331. Child = fork();
  332. //
  333. // If this is the child, break out and run the tests.
  334. //
  335. if (Child == 0) {
  336. srand(time(NULL) + ChildIndex);
  337. IsParent = FALSE;
  338. break;
  339. }
  340. Children[ChildIndex] = Child;
  341. }
  342. }
  343. //
  344. // Run the tests.
  345. //
  346. if ((Test == SignalTestAll) || (Test == SignalTestWaitpid)) {
  347. Failures += RunWaitpidTest(Iterations);
  348. }
  349. if ((Test == SignalTestAll) || (Test == SignalTestSigchld)) {
  350. Failures += RunSigchldTest(Iterations, ChildProcessCount);
  351. }
  352. if ((Test == SignalTestAll) || (Test == SignalTestQuickWait)) {
  353. Failures += RunQuickWaitTest(Iterations, ChildProcessCount);
  354. }
  355. if ((Test == SignalTestAll) || (Test == SignalTestNested)) {
  356. Failures += RunNestedSignalsTest();
  357. }
  358. if ((Test == SignalTestAll) || (Test == SignalTestContext)) {
  359. Failures += RunSetContextTest();
  360. }
  361. //
  362. // Wait for any children.
  363. //
  364. if (IsParent != FALSE) {
  365. if (Threads > 1) {
  366. for (ChildIndex = 0; ChildIndex < Threads - 1; ChildIndex += 1) {
  367. Child = waitpid(Children[ChildIndex], &Status, 0);
  368. if (Child == -1) {
  369. PRINT_ERROR("Failed to wait for child %d: %s.\n",
  370. Children[ChildIndex],
  371. strerror(errno));
  372. Status = errno;
  373. } else {
  374. assert(Child == Children[ChildIndex]);
  375. if (!WIFEXITED(Status)) {
  376. PRINT_ERROR("Child %d returned with status %x\n",
  377. Child,
  378. Status);
  379. Failures += 1;
  380. }
  381. Failures += WEXITSTATUS(Status);
  382. Status = 0;
  383. }
  384. }
  385. }
  386. //
  387. // If this is a child, just report back the number of failures to the
  388. // parent.
  389. //
  390. } else {
  391. if (Failures > 100) {
  392. exit(100);
  393. } else {
  394. exit(Failures);
  395. }
  396. }
  397. MainEnd:
  398. if (Children != NULL) {
  399. free(Children);
  400. }
  401. if (Status != 0) {
  402. PRINT_ERROR("Error: %d.\n", Status);
  403. }
  404. if (Failures != 0) {
  405. PRINT_ERROR("\n *** %d failures in signal test ***\n", Failures);
  406. return Failures;
  407. }
  408. return 0;
  409. }
  410. //
  411. // --------------------------------------------------------- Internal Functions
  412. //
  413. ULONG
  414. RunWaitpidTest (
  415. ULONG Iterations
  416. )
  417. /*++
  418. Routine Description:
  419. This routine runs several variations of the waitpid test.
  420. Arguments:
  421. Iterations - Supplies the number of times to run the test.
  422. Return Value:
  423. Returns the number of failures in the test.
  424. --*/
  425. {
  426. ULONG Errors;
  427. ULONG Iteration;
  428. ULONG Percent;
  429. Percent = Iterations / 100;
  430. if (Percent == 0) {
  431. Percent = 1;
  432. }
  433. PRINT("Running waitpid test with %d iterations.\n", Iterations);
  434. Errors = 0;
  435. for (Iteration = 0; Iteration < Iterations; Iteration += 1) {
  436. Errors += TestWaitpid(FALSE, FALSE);
  437. Errors += TestWaitpid(TRUE, FALSE);
  438. Errors += TestWaitpid(FALSE, TRUE);
  439. Errors += TestWaitpid(TRUE, TRUE);
  440. if ((Iteration % Percent) == 0) {
  441. PRINT("w");
  442. }
  443. }
  444. PRINT("\n");
  445. return Errors;
  446. }
  447. ULONG
  448. RunSigchldTest (
  449. ULONG Iterations,
  450. ULONG ChildCount
  451. )
  452. /*++
  453. Routine Description:
  454. This routine runs several variations of the waitpid test.
  455. Arguments:
  456. Iterations - Supplies the number of times to run the test.
  457. ChildCount - Supplies the number of child processes to spin up and wait
  458. for.
  459. Return Value:
  460. Returns the number of failures in the test.
  461. --*/
  462. {
  463. ULONG Errors;
  464. ULONG Iteration;
  465. ULONG Percent;
  466. ULONG WaitType;
  467. PRINT("Running sigchld test with %d iterations and %d children.\n",
  468. Iterations,
  469. ChildCount);
  470. Percent = Iterations / 100;
  471. if (Percent == 0) {
  472. Percent = 1;
  473. }
  474. Errors = 0;
  475. for (Iteration = 0; Iteration < Iterations; Iteration += 1) {
  476. for (WaitType = 0; WaitType < SignalTestWaitTypeCount; WaitType += 1) {
  477. Errors += TestSigchild(ChildCount, 3, WaitType, FALSE);
  478. Errors += TestSigchild(ChildCount, 3, WaitType, TRUE);
  479. }
  480. if ((Iteration % Percent) == 0) {
  481. PRINT("c");
  482. }
  483. }
  484. PRINT("\n");
  485. return Errors;
  486. }
  487. ULONG
  488. RunQuickWaitTest (
  489. ULONG Iterations,
  490. ULONG ChildCount
  491. )
  492. /*++
  493. Routine Description:
  494. This routine runs the quick wait test, which just forks a process that dies
  495. and waits for it.
  496. Arguments:
  497. Iterations - Supplies the number of times to run the test.
  498. ChildCount - Supplies the number of child processes to spin up and wait
  499. for.
  500. Return Value:
  501. Returns the number of failures in the test.
  502. --*/
  503. {
  504. pid_t Child;
  505. LONG ChildIndex;
  506. pid_t *Children;
  507. ULONG Failures;
  508. ULONG Iteration;
  509. ULONG Percent;
  510. int Status;
  511. Failures = 0;
  512. PRINT("Running QuickWait test with %d iterations and %d children.\n",
  513. Iterations,
  514. ChildCount);
  515. assert(ChildCount != 0);
  516. Percent = Iterations / 100;
  517. if (Percent == 0) {
  518. Percent = 1;
  519. }
  520. Children = malloc(sizeof(pid_t) * ChildCount);
  521. if (Children == NULL) {
  522. Failures += 1;
  523. goto RunQuickWaitTestEnd;
  524. }
  525. for (Iteration = 0; Iteration < Iterations; Iteration += 1) {
  526. memset(Children, 0, sizeof(pid_t) * ChildCount);
  527. //
  528. // Loop creating all the child processes.
  529. //
  530. for (ChildIndex = 0; ChildIndex < ChildCount; ChildIndex += 1) {
  531. Child = fork();
  532. if (Child == -1) {
  533. PRINT_ERROR("Failed to fork: %s.\n", strerror(errno));
  534. Failures += 1;
  535. continue;
  536. }
  537. //
  538. // If this is the child, die immediately.
  539. //
  540. if (Child == 0) {
  541. exit(ChildIndex);
  542. }
  543. Children[ChildIndex] = Child;
  544. }
  545. //
  546. // Loop reaping all the child processes. Backwards, for added flavor.
  547. //
  548. for (ChildIndex = ChildCount - 1; ChildIndex >= 0; ChildIndex -= 1) {
  549. Child = waitpid(Children[ChildIndex], &Status, 0);
  550. if (Child == -1) {
  551. PRINT_ERROR("Failed to wait for child %d: %s.\n",
  552. Child,
  553. strerror(errno));
  554. Failures += 1;
  555. continue;
  556. }
  557. if ((!WIFEXITED(Status)) ||
  558. (WEXITSTATUS(Status) != (ChildIndex & 0x7F))) {
  559. PRINT_ERROR("Child returned with invalid status %x\n", Status);
  560. Failures += 1;
  561. }
  562. }
  563. if ((Iteration % Percent) == 0) {
  564. PRINT("q");
  565. }
  566. }
  567. PRINT("\n");
  568. RunQuickWaitTestEnd:
  569. if (Children != NULL) {
  570. free(Children);
  571. }
  572. return Failures;
  573. }
  574. ULONG
  575. TestWaitpid (
  576. BOOL BurnTimeInChild,
  577. BOOL BurnTimeInParent
  578. )
  579. /*++
  580. Routine Description:
  581. This routine tests that an application can exit, be waited on, and
  582. successfully report its status.
  583. Arguments:
  584. BurnTimeInParent - Supplies a boolean indicating if some time should be
  585. wasted in the parent process.
  586. BurnTimeInChild - Supplies a boolean indicating if some time should be
  587. wasted in the child process.
  588. Return Value:
  589. Returns the number of failures in the test.
  590. --*/
  591. {
  592. pid_t Child;
  593. struct sigaction ChildAction;
  594. sigset_t ChildSignalMask;
  595. ULONG Errors;
  596. struct sigaction OriginalChildAction;
  597. sigset_t OriginalSignalMask;
  598. int Status;
  599. pid_t WaitPid;
  600. //
  601. // Block child signals, and set up a handler.
  602. //
  603. sigemptyset(&ChildSignalMask);
  604. sigaddset(&ChildSignalMask, SIGCHLD);
  605. sigprocmask(SIG_BLOCK, &ChildSignalMask, &OriginalSignalMask);
  606. ChildAction.sa_sigaction = TestWaitpidChildSignalHandler;
  607. sigemptyset(&(ChildAction.sa_mask));
  608. ChildAction.sa_flags = SA_NODEFER | SA_SIGINFO;
  609. sigaction(SIGCHLD, &ChildAction, &OriginalChildAction);
  610. Errors = 0;
  611. Child = fork();
  612. if (Child == -1) {
  613. PRINT_ERROR("Failed to fork()!\n");
  614. return 1;
  615. }
  616. //
  617. // If this is the child process, exit with a specific status code. Only the
  618. // first 8 bits can be accessed with the macro.
  619. //
  620. if (Child == 0) {
  621. if (BurnTimeInChild != FALSE) {
  622. sleep(1);
  623. }
  624. DEBUG_PRINT("Child %d exiting with status 99.\n", getpid());
  625. exit(99);
  626. //
  627. // In the parent process, wait for the child.
  628. //
  629. } else {
  630. if (BurnTimeInParent != FALSE) {
  631. sleep(1);
  632. }
  633. DEBUG_PRINT("Parent waiting for child %d.\n", Child);
  634. Status = 0;
  635. WaitPid = waitpid(Child, &Status, WUNTRACED | WCONTINUED);
  636. if (WaitPid != Child) {
  637. PRINT_ERROR("waitpid returned %d instead of child pid %d.\n",
  638. WaitPid,
  639. Child);
  640. Errors += 1;
  641. }
  642. //
  643. // Check the flags and return value.
  644. //
  645. if ((!WIFEXITED(Status)) ||
  646. (WIFCONTINUED(Status)) ||
  647. (WIFSIGNALED(Status)) ||
  648. (WIFSTOPPED(Status))) {
  649. PRINT_ERROR("Child status was not exited as expected. Was %x\n",
  650. Status);
  651. Errors += 1;
  652. }
  653. if (WEXITSTATUS(Status) != 99) {
  654. PRINT_ERROR("Child exit status was an unexpected %d.\n",
  655. WEXITSTATUS(Status));
  656. Errors += 1;
  657. }
  658. }
  659. //
  660. // Restore the original signal mask.
  661. //
  662. sigaction(SIGCHLD, &OriginalChildAction, NULL);
  663. sigprocmask(SIG_SETMASK, &OriginalSignalMask, NULL);
  664. Errors += ChildSignalFailures;
  665. ChildSignalFailures = 0;
  666. return Errors;
  667. }
  668. ULONG
  669. TestSigchild (
  670. ULONG ChildCount,
  671. ULONG ChildAdditionalThreads,
  672. SIGNAL_TEST_WAIT_TYPE WaitType,
  673. BOOL ChildrenExitVoluntarily
  674. )
  675. /*++
  676. Routine Description:
  677. This routine tests child signals.
  678. Arguments:
  679. ChildCount - Supplies the number of simultaneous children to create.
  680. ChildAdditionalThreads - Supplies the number of additional threads each
  681. child should spin up.
  682. WaitType - Supplies the type of waiting that should be used in the main
  683. loop.
  684. ChildrenExitVoluntarily - Supplies a boolean indicating whether children
  685. exit on their own or need to be killed.
  686. Return Value:
  687. Returns the number of failures in the test.
  688. --*/
  689. {
  690. pid_t Child;
  691. struct sigaction ChildAction;
  692. ULONG ChildIndex;
  693. volatile ULONG ChildInitializing;
  694. pid_t *Children;
  695. sigset_t ChildSignalMask;
  696. time_t EndTime;
  697. ULONG Errors;
  698. struct sigaction OriginalChildAction;
  699. struct sigaction OriginalRealtimeAction;
  700. sigset_t OriginalSignalMask;
  701. siginfo_t SignalInformation;
  702. int SignalNumber;
  703. union sigval SignalValue;
  704. int Status;
  705. pthread_t Thread;
  706. ULONG ThreadIndex;
  707. struct timespec Timeout;
  708. pid_t WaitPid;
  709. if (WaitType >= SignalTestWaitTypeCount) {
  710. PRINT_ERROR("Invalid wait type %d.\n", WaitType);
  711. return 1;
  712. }
  713. //
  714. // Allocate child array.
  715. //
  716. DEBUG_PRINT("Testing SIGCHLD: %d children each with %d extra "
  717. "threads. WaitType: %s, ChildrenExitVoluntarily: "
  718. "%d.\n\n",
  719. ChildCount,
  720. ChildAdditionalThreads,
  721. SignalTestWaitTypeStrings[WaitType],
  722. ChildrenExitVoluntarily);
  723. Children = malloc(sizeof(pid_t) * ChildCount);
  724. if (Children == NULL) {
  725. PRINT_ERROR("Failed to malloc %d bytes.\n", sizeof(pid_t) * ChildCount);
  726. return 1;
  727. }
  728. RtlZeroMemory(Children, sizeof(pid_t) * ChildCount);
  729. //
  730. // Block child signals, and set up a handler.
  731. //
  732. sigemptyset(&ChildSignalMask);
  733. sigaddset(&ChildSignalMask, SIGCHLD);
  734. sigprocmask(SIG_BLOCK, &ChildSignalMask, &OriginalSignalMask);
  735. ChildAction.sa_sigaction = TestWaitpidChildSignalHandler;
  736. sigemptyset(&(ChildAction.sa_mask));
  737. ChildAction.sa_flags = SA_NODEFER | SA_SIGINFO;
  738. sigaction(SIGCHLD, &ChildAction, &OriginalChildAction);
  739. ChildAction.sa_sigaction = TestSigchldRealtime1SignalHandler;
  740. sigaction(SIGRTMIN + 0, &ChildAction, &OriginalRealtimeAction);
  741. Errors = 0;
  742. //
  743. // Create child processes.
  744. //
  745. ChildProcessesReady = 0;
  746. ChildSignalsExpected = ChildCount;
  747. Child = -1;
  748. for (ChildIndex = 0; ChildIndex < ChildCount; ChildIndex += 1) {
  749. Child = fork();
  750. if (Child == -1) {
  751. PRINT_ERROR("Failed to fork()!\n");
  752. return 1;
  753. }
  754. //
  755. // If this is the child process, spin up any additional threads
  756. // requested, send the signal once everything's up and running, and
  757. // exit.
  758. //
  759. if (Child == 0) {
  760. DEBUG_PRINT("Child %d alive.\n", getpid());
  761. for (ThreadIndex = 0;
  762. ThreadIndex < ChildAdditionalThreads;
  763. ThreadIndex += 1) {
  764. ChildInitializing = 1;
  765. Status = pthread_create(&Thread,
  766. NULL,
  767. TestThreadSpinForever,
  768. (PVOID)&ChildInitializing);
  769. if (Status != 0) {
  770. PRINT_ERROR("Child %d failed to create thread: %d.\n",
  771. getpid(),
  772. Status);
  773. }
  774. //
  775. // Wait for the thread to come to life and start doing
  776. // something.
  777. //
  778. EndTime = time(NULL) + 10;
  779. while (time(NULL) <= EndTime) {
  780. if (ChildInitializing == 0) {
  781. break;
  782. }
  783. }
  784. if (ChildInitializing != 0) {
  785. PRINT_ERROR("Thread failed to initialize!\n");
  786. }
  787. }
  788. //
  789. // Send a signal to the parent letting them know everything's
  790. // initialized.
  791. //
  792. SignalValue.sival_int = getpid();
  793. Status = sigqueue(getppid(), SIGRTMIN + 0, SignalValue);
  794. if (Status != 0) {
  795. PRINT_ERROR("Failed to sigqueue to parent: errno %d.\n",
  796. errno);
  797. }
  798. //
  799. // Exit the process or spin forever.
  800. //
  801. if (ChildrenExitVoluntarily != FALSE) {
  802. DEBUG_PRINT("Child %d exiting with status 99.\n", getpid());
  803. exit(99);
  804. } else {
  805. DEBUG_PRINT("Child %d spinning forever.\n", getpid());
  806. while (TRUE) {
  807. sleep(1);
  808. }
  809. }
  810. //
  811. // This is the parent process, save the child PID.
  812. //
  813. } else {
  814. Children[ChildIndex] = Child;
  815. }
  816. }
  817. //
  818. // This is the parent process, wait for all processes to be ready.
  819. //
  820. EndTime = time(NULL) + 30;
  821. while (time(NULL) <= EndTime) {
  822. if (ChildProcessesReady == ChildCount) {
  823. break;
  824. }
  825. }
  826. if (ChildProcessesReady != ChildCount) {
  827. PRINT_ERROR("Only %d of %d children ready.\n",
  828. ChildProcessesReady,
  829. ChildCount);
  830. Errors += 1;
  831. }
  832. //
  833. // If the children aren't going to go quietly, kill them.
  834. //
  835. if (ChildrenExitVoluntarily == FALSE) {
  836. for (ChildIndex = 0; ChildIndex < ChildCount; ChildIndex += 1) {
  837. DEBUG_PRINT("Killing child index %d PID %d.\n",
  838. ChildIndex,
  839. Children[ChildIndex]);
  840. Status = kill(Children[ChildIndex], SIGKILL);
  841. if (Status != 0) {
  842. PRINT_ERROR("Failed to kill pid %d, errno %d.\n",
  843. Children[ChildIndex],
  844. errno);
  845. Errors += 1;
  846. }
  847. }
  848. }
  849. //
  850. // In the parent process, wait for the children.
  851. //
  852. DEBUG_PRINT("Parent waiting for children via %s.\n",
  853. SignalTestWaitTypeStrings[WaitType]);
  854. EndTime = time(NULL) + 30;
  855. Status = 0;
  856. switch (WaitType) {
  857. case SignalTestWaitSigsuspend:
  858. while (time(NULL) <= EndTime) {
  859. if (ChildSignalsExpected == 0) {
  860. break;
  861. }
  862. DEBUG_PRINT("Expecting %d more child signals. "
  863. "Running sigsuspend.\n",
  864. ChildSignalsExpected);
  865. sigsuspend(&OriginalSignalMask);
  866. DEBUG_PRINT("Returned from sigsuspend.\n");
  867. }
  868. break;
  869. case SignalTestWaitSigwait:
  870. while (time(NULL) <= EndTime) {
  871. if (ChildSignalsExpected == 0) {
  872. break;
  873. }
  874. DEBUG_PRINT("Expecting %d more child signals. "
  875. "Running sigwait.\n",
  876. ChildSignalsExpected);
  877. Status = sigwait(&ChildSignalMask, &SignalNumber);
  878. DEBUG_PRINT("Returned from sigwait.\n");
  879. if (Status != 0) {
  880. PRINT_ERROR("Failed sigwait: %s.\n", strerror(Status));
  881. Errors += 1;
  882. continue;
  883. }
  884. //
  885. // The signal handler was not called and the parameters are not
  886. // available, so just process the signal without the parameters.
  887. //
  888. TestWaitpidProcessChildSignal(SignalNumber, NULL);
  889. }
  890. break;
  891. case SignalTestWaitSigwaitinfo:
  892. while (time(NULL) <= EndTime) {
  893. if (ChildSignalsExpected == 0) {
  894. break;
  895. }
  896. DEBUG_PRINT("Expecting %d more child signals. "
  897. "Running sigwaitinfo.\n",
  898. ChildSignalsExpected);
  899. SignalNumber = sigwaitinfo(&ChildSignalMask, &SignalInformation);
  900. DEBUG_PRINT("Returned from sigwaitinfo.\n");
  901. if (SignalNumber == -1) {
  902. if (errno != EINTR) {
  903. PRINT_ERROR("Failed sigwaitinfo: %s.\n", strerror(errno));
  904. Errors += 1;
  905. }
  906. continue;
  907. }
  908. //
  909. // Handle the signal in-line as the handler was not called.
  910. //
  911. TestWaitpidProcessChildSignal(SignalNumber, &SignalInformation);
  912. }
  913. break;
  914. case SignalTestWaitSigtimedwait:
  915. Timeout.tv_nsec = 0;
  916. Timeout.tv_sec = 1;
  917. while (time(NULL) <= EndTime) {
  918. if (ChildSignalsExpected == 0) {
  919. break;
  920. }
  921. DEBUG_PRINT("Expecting %d more child signals. "
  922. "Running sigtimedwait.\n",
  923. ChildSignalsExpected);
  924. SignalNumber = sigtimedwait(&ChildSignalMask,
  925. &SignalInformation,
  926. &Timeout);
  927. DEBUG_PRINT("Returned from sigtimedwait.\n");
  928. if (SignalNumber == -1) {
  929. if (errno == EAGAIN) {
  930. DEBUG_PRINT("sigtimedwait timed out. Retrying.\n");
  931. } else if (errno != EINTR) {
  932. PRINT_ERROR("Failed sigtimedwait: %s.\n", strerror(errno));
  933. Errors += 1;
  934. }
  935. continue;
  936. }
  937. //
  938. // Handle the signal in-line as the handler was not called.
  939. //
  940. TestWaitpidProcessChildSignal(SignalNumber, &SignalInformation);
  941. }
  942. break;
  943. case SignalTestWaitBusy:
  944. default:
  945. sigprocmask(SIG_UNBLOCK, &ChildSignalMask, NULL);
  946. while (time(NULL) <= EndTime) {
  947. if (ChildSignalsExpected == 0) {
  948. break;
  949. }
  950. }
  951. sigprocmask(SIG_BLOCK, &ChildSignalMask, NULL);
  952. break;
  953. }
  954. if (ChildSignalsExpected != 0) {
  955. PRINT_ERROR("Error: Never saw SIGCHLD.\n");
  956. Errors += 1;
  957. }
  958. ChildSignalsExpected = 0;
  959. //
  960. // Waitpid better not find anything.
  961. //
  962. WaitPid = waitpid(-1, &Status, WUNTRACED | WCONTINUED | WNOHANG);
  963. if (WaitPid > 0) {
  964. PRINT_ERROR("Error: waitpid unexpectedly gave up a %d\n", WaitPid);
  965. Errors += 1;
  966. }
  967. if (ChildSignalFailures != 0) {
  968. PRINT_ERROR("Error: %d child signal failures.\n", ChildSignalFailures);
  969. }
  970. Errors += ChildSignalFailures;
  971. ChildSignalFailures = 0;
  972. ChildProcessesReady = 0;
  973. //
  974. // Restore the original signal mask.
  975. //
  976. sigaction(SIGCHLD, &OriginalChildAction, NULL);
  977. sigaction(SIGRTMIN + 0, &OriginalRealtimeAction, NULL);
  978. sigprocmask(SIG_SETMASK, &OriginalSignalMask, NULL);
  979. free(Children);
  980. DEBUG_PRINT("Done with SIGCHLD test.\n");
  981. return Errors;
  982. }
  983. void
  984. TestWaitpidChildSignalHandler (
  985. int Signal,
  986. siginfo_t *SignalInformation,
  987. void *Context
  988. )
  989. /*++
  990. Routine Description:
  991. This routine responds to child signals.
  992. Arguments:
  993. Signal - Supplies the signal number coming in, in this case always SIGCHLD.
  994. SignalInformation - Supplies a pointer to the signal information.
  995. Context - Supplies a pointer to some unused context information.
  996. Return Value:
  997. None.
  998. --*/
  999. {
  1000. TestWaitpidProcessChildSignal(Signal, SignalInformation);
  1001. return;
  1002. }
  1003. void
  1004. TestWaitpidProcessChildSignal (
  1005. int Signal,
  1006. siginfo_t *SignalInformation
  1007. )
  1008. /*++
  1009. Routine Description:
  1010. This routine processes a child signal.
  1011. Arguments:
  1012. Signal - Supplies the signal number coming in, in this case always SIGCHLD.
  1013. SignalInformation - Supplies an optional pointer to the signal information.
  1014. Return Value:
  1015. None.
  1016. --*/
  1017. {
  1018. int PidStatus;
  1019. BOOL SignaledPidFound;
  1020. int Status;
  1021. LONG WaitPidResult;
  1022. if (SignalInformation != NULL) {
  1023. DEBUG_PRINT("SIGCHLD Pid %d Status %d.\n",
  1024. SignalInformation->si_pid,
  1025. SignalInformation->si_status);
  1026. }
  1027. if (Signal != SIGCHLD) {
  1028. PRINT_ERROR("Error: Signal %d came in instead of SIGCHLD.\n", Signal);
  1029. ChildSignalFailures += 1;
  1030. }
  1031. if (ChildSignalsExpected == 0) {
  1032. PRINT_ERROR("Error: Unexpected child signal.\n");
  1033. ChildSignalFailures += 1;
  1034. }
  1035. if (SignalInformation != NULL) {
  1036. if (SignalInformation->si_signo != SIGCHLD) {
  1037. PRINT_ERROR("Error: Signal %d came in si_signo instead of "
  1038. "SIGCHLD.\n",
  1039. SignalInformation->si_signo);
  1040. ChildSignalFailures += 1;
  1041. }
  1042. if (SignalInformation->si_code == CLD_EXITED) {
  1043. if (SignalInformation->si_status != 99) {
  1044. PRINT_ERROR("Error: si_status was %d instead of %d.\n",
  1045. SignalInformation->si_status,
  1046. 99);
  1047. ChildSignalFailures += 1;
  1048. }
  1049. } else if (SignalInformation->si_code != CLD_KILLED) {
  1050. PRINT_ERROR("Error: unexpected si_code %x.\n",
  1051. SignalInformation->si_code);
  1052. ChildSignalFailures += 1;
  1053. }
  1054. }
  1055. //
  1056. // Make sure a wait also gets the same thing.
  1057. //
  1058. if (ChildSignalsExpected == 1) {
  1059. SignaledPidFound = TRUE;
  1060. WaitPidResult = waitpid(-1, &Status, WNOHANG);
  1061. if ((SignalInformation != NULL) &&
  1062. (WaitPidResult != SignalInformation->si_pid)) {
  1063. SignaledPidFound = FALSE;
  1064. PRINT_ERROR("Error: SignalInformation->si_pid = %d but "
  1065. "waitpid() = %d\n.",
  1066. SignalInformation->si_pid,
  1067. WaitPidResult);
  1068. ChildSignalFailures += 1;
  1069. }
  1070. ChildSignalsExpected -= 1;
  1071. } else {
  1072. SignaledPidFound = FALSE;
  1073. while (ChildSignalsExpected != 0) {
  1074. WaitPidResult = waitpid(-1, &PidStatus, WNOHANG);
  1075. if ((SignalInformation != NULL) &&
  1076. (WaitPidResult == SignalInformation->si_pid)) {
  1077. Status = PidStatus;
  1078. SignaledPidFound = TRUE;
  1079. }
  1080. DEBUG_PRINT("SIGCHLD handler waited and got %d.\n", WaitPidResult);
  1081. if ((WaitPidResult == -1) || (WaitPidResult == 0)) {
  1082. break;
  1083. }
  1084. ChildSignalsExpected -= 1;
  1085. }
  1086. }
  1087. if (SignalInformation != NULL) {
  1088. if (SignaledPidFound == FALSE) {
  1089. PRINT_ERROR("Error: Pid %d signaled but waitpid could not find "
  1090. "it.\n",
  1091. SignalInformation->si_pid);
  1092. ChildSignalFailures += 1;
  1093. } else {
  1094. if (SignalInformation->si_code == CLD_EXITED) {
  1095. if ((!WIFEXITED(Status)) || (WEXITSTATUS(Status) != 99)) {
  1096. PRINT_ERROR("Error: Status was %x, not returning exited "
  1097. "or exit status %d.\n",
  1098. Status,
  1099. 99);
  1100. ChildSignalFailures += 1;
  1101. }
  1102. } else if (SignalInformation->si_code == CLD_KILLED) {
  1103. if ((!WIFSIGNALED(Status)) || (WTERMSIG(Status) != SIGKILL)) {
  1104. PRINT_ERROR("Error: Status was %x, not returning signaled "
  1105. "or SIGKILL.\n",
  1106. Status);
  1107. ChildSignalFailures += 1;
  1108. }
  1109. }
  1110. }
  1111. }
  1112. //
  1113. // If all the children have been accounted for, make sure there's not
  1114. // another signal in the queue too.
  1115. //
  1116. if (ChildSignalsExpected == 0) {
  1117. WaitPidResult = waitpid(-1, NULL, WNOHANG);
  1118. if (WaitPidResult > 0) {
  1119. PRINT_ERROR("Error: waitpid got another child %d unexpectedly.\n",
  1120. WaitPidResult);
  1121. ChildSignalFailures += 1;
  1122. }
  1123. }
  1124. if (SignalInformation != NULL) {
  1125. ChildSignalPid = SignalInformation->si_pid;
  1126. }
  1127. return;
  1128. }
  1129. void
  1130. TestSigchldRealtime1SignalHandler (
  1131. int Signal,
  1132. siginfo_t *SignalInformation,
  1133. void *Context
  1134. )
  1135. /*++
  1136. Routine Description:
  1137. This routine responds to the first real time signal, used to count ready
  1138. processes.
  1139. Arguments:
  1140. Signal - Supplies the signal number coming in, in this case always SIGCHLD.
  1141. SignalInformation - Supplies a pointer to the signal information.
  1142. Context - Supplies a pointer to some unused context information.
  1143. Return Value:
  1144. None.
  1145. --*/
  1146. {
  1147. DEBUG_PRINT("SIGRTMIN+0 %d\n", SignalInformation->si_value.sival_int);
  1148. if (SignalInformation->si_signo != SIGRTMIN + 0) {
  1149. PRINT_ERROR("Got si_signo %d when expected %d.\n",
  1150. SignalInformation->si_signo,
  1151. SIGRTMIN + 0);
  1152. ChildSignalFailures += 1;
  1153. }
  1154. ChildProcessesReady += 1;
  1155. return;
  1156. }
  1157. PVOID
  1158. TestThreadSpinForever (
  1159. PVOID Parameter
  1160. )
  1161. /*++
  1162. Routine Description:
  1163. This routine implements a thread routine that simply spins forever.
  1164. Arguments:
  1165. Parameter - Supplies a parameter assumed to be of type PULONG whose
  1166. contents will be set to 0.
  1167. Return Value:
  1168. None. This thread never returns voluntarily.
  1169. --*/
  1170. {
  1171. *((PULONG)Parameter) = 0;
  1172. while (TRUE) {
  1173. sleep(1);
  1174. }
  1175. return NULL;
  1176. }
  1177. ULONG
  1178. RunNestedSignalsTest (
  1179. VOID
  1180. )
  1181. /*++
  1182. Routine Description:
  1183. This routine tests nested signal reception.
  1184. Arguments:
  1185. None.
  1186. Return Value:
  1187. Returns the number of failures.
  1188. --*/
  1189. {
  1190. struct sigaction Action;
  1191. UCHAR Byte;
  1192. pid_t Child;
  1193. ULONG Count;
  1194. ULONG Failures;
  1195. ULONG Index;
  1196. int Pipe[2];
  1197. int Received[2];
  1198. union sigval SigVal;
  1199. Count = 200;
  1200. Child = -1;
  1201. Failures = 0;
  1202. PRINT("Running nested signals test\n");
  1203. memset(&Action, 0, sizeof(Action));
  1204. Action.sa_flags = SA_SIGINFO;
  1205. Action.sa_sigaction = TestNestedSignalHandler;
  1206. if (pipe(Pipe) != 0) {
  1207. PRINT_ERROR("pipe failed.\n");
  1208. return 1;
  1209. }
  1210. Child = fork();
  1211. if (Child == -1) {
  1212. PRINT_ERROR("fork failed.\n");
  1213. Failures += 1;
  1214. goto TestNestedSignalsEnd;
  1215. //
  1216. // This is the child.
  1217. //
  1218. } else if (Child == 0) {
  1219. close(Pipe[0]);
  1220. Pipe[0] = -1;
  1221. if ((sigaction(SIGRTMIN, &Action, NULL) != 0) ||
  1222. (sigaction(SIGRTMIN + 1, &Action, NULL) != 0)) {
  1223. PRINT_ERROR("Sigaction failed.\n");
  1224. exit(1);
  1225. }
  1226. SigtestWritePipe = Pipe[1];
  1227. Byte = 1;
  1228. write(Pipe[1], &Byte, 1);
  1229. while ((SigtestSignalCount[0] < Count) ||
  1230. (SigtestSignalCount[1] < Count)) {
  1231. pause();
  1232. }
  1233. DEBUG_PRINT("Got %d and %d signals\n",
  1234. SigtestSignalCount[0],
  1235. SigtestSignalCount[1]);
  1236. exit(0);
  1237. //
  1238. // This is the parent.
  1239. //
  1240. } else {
  1241. close(Pipe[1]);
  1242. Pipe[1] = -1;
  1243. if ((read(Pipe[0], &Byte, 1) != 1) || (Byte != 1)) {
  1244. PRINT_ERROR("Child not read\n");
  1245. Failures += 1;
  1246. goto TestNestedSignalsEnd;
  1247. }
  1248. Received[0] = 0;
  1249. Received[1] = 0;
  1250. fcntl(Pipe[0], F_SETFL, O_NONBLOCK);
  1251. for (Index = 0; Index < Count; Index += 1) {
  1252. if ((sigqueue(Child, SIGRTMIN, SigVal) != 0) ||
  1253. (sigqueue(Child, SIGRTMIN + 1, SigVal) != 0)) {
  1254. PRINT_ERROR("Failed to queue signa.\n");
  1255. Failures += 1;
  1256. goto TestNestedSignalsEnd;
  1257. }
  1258. while (read(Pipe[0], &Byte, 1) == 1) {
  1259. if (Byte == SIGRTMIN) {
  1260. Received[0] += 1;
  1261. } else if (Byte == SIGRTMIN + 1) {
  1262. Received[1] += 1;
  1263. } else {
  1264. PRINT_ERROR("Unknown signal received\n");
  1265. Failures += 1;
  1266. goto TestNestedSignalsEnd;
  1267. }
  1268. }
  1269. }
  1270. DEBUG_PRINT("Sent %d signals\n", Index);
  1271. fcntl(Pipe[0], F_SETFL, 0);
  1272. while ((Received[0] != Count) ||
  1273. (Received[1] != Count)) {
  1274. if (read(Pipe[0], &Byte, 1) != 1) {
  1275. perror("Error");
  1276. PRINT_ERROR("Pipe read failure.\n");
  1277. Failures += 1;
  1278. goto TestNestedSignalsEnd;
  1279. }
  1280. if (Byte == SIGRTMIN) {
  1281. Received[0] += 1;
  1282. } else if (Byte == SIGRTMIN + 1) {
  1283. Received[1] += 1;
  1284. } else {
  1285. PRINT_ERROR("Unknown signal received\n");
  1286. Failures += 1;
  1287. goto TestNestedSignalsEnd;
  1288. }
  1289. }
  1290. }
  1291. DEBUG_PRINT("\n");
  1292. TestNestedSignalsEnd:
  1293. if (Pipe[0] >= 0) {
  1294. close(Pipe[0]);
  1295. }
  1296. if (Pipe[1] >= 0) {
  1297. close(Pipe[1]);
  1298. }
  1299. if (Child > 0) {
  1300. kill(Child, SIGKILL);
  1301. waitpid(Child, NULL, 0);
  1302. }
  1303. return Failures;
  1304. }
  1305. VOID
  1306. TestNestedSignalHandler (
  1307. int Signal,
  1308. siginfo_t *Info,
  1309. void *Ignored
  1310. )
  1311. /*++
  1312. Routine Description:
  1313. This routine tests nested signal reception.
  1314. Arguments:
  1315. Signal - Supplies the signal that occurred.
  1316. Info - Supplies a pointer to the signal information.
  1317. Ignored - Supplies an ignored context pointer.
  1318. Return Value:
  1319. None.
  1320. --*/
  1321. {
  1322. ssize_t BytesComplete;
  1323. assert(Info->si_signo == Signal);
  1324. assert((Signal == SIGRTMIN) || (Signal == SIGRTMIN + 1));
  1325. do {
  1326. BytesComplete = write(SigtestWritePipe, &(Info->si_signo), 1);
  1327. } while ((BytesComplete < 0) && (errno == EINTR));
  1328. if (BytesComplete != 1) {
  1329. assert(FALSE);
  1330. }
  1331. if (Signal == SIGRTMIN) {
  1332. DEBUG_PRINT("A%d ", SigtestSignalCount[0]);
  1333. SigtestSignalCount[0] += 1;
  1334. } else {
  1335. assert(Signal == SIGRTMIN + 1);
  1336. DEBUG_PRINT("B%d ", SigtestSignalCount[1]);
  1337. SigtestSignalCount[1] += 1;
  1338. }
  1339. return;
  1340. }
  1341. ULONG
  1342. RunSetContextTest (
  1343. VOID
  1344. )
  1345. /*++
  1346. Routine Description:
  1347. This routine tests the ucontext related functions.
  1348. Arguments:
  1349. None.
  1350. Return Value:
  1351. Returns the number of failures.
  1352. --*/
  1353. {
  1354. ULONG Failures;
  1355. Failures = TestContextSwap(TRUE);
  1356. Failures += TestContextSwap(FALSE);
  1357. return Failures;
  1358. }
  1359. ULONG
  1360. TestContextSwap (
  1361. BOOL Exit
  1362. )
  1363. /*++
  1364. Routine Description:
  1365. This routine tests the ucontext related functions.
  1366. Arguments:
  1367. Exit - Supplies a boolean indicating whether to test a context swap that
  1368. exits or returns.
  1369. Return Value:
  1370. Returns the number of failures.
  1371. --*/
  1372. {
  1373. pid_t Child;
  1374. ucontext_t Context1;
  1375. ucontext_t Context2;
  1376. ucontext_t MainContext;
  1377. int Status;
  1378. Child = fork();
  1379. if (Child < 0) {
  1380. PRINT_ERROR("Failed to fork\n");
  1381. return 1;
  1382. } else if (Child > 0) {
  1383. if (waitpid(Child, &Status, 0) != Child) {
  1384. PRINT_ERROR("Failed to wait\n");
  1385. return 1;
  1386. }
  1387. if ((!WIFEXITED(Status)) || (WEXITSTATUS(Status) != 0)) {
  1388. PRINT_ERROR("Child exited with %x\n", Status);
  1389. return 1;
  1390. }
  1391. return 0;
  1392. }
  1393. //
  1394. // This is the child.
  1395. //
  1396. SigtestContextHits = 0;
  1397. if (getcontext(&Context1) != 0) {
  1398. PRINT_ERROR("getcontext failed");
  1399. exit(1);
  1400. }
  1401. Context1.uc_stack.ss_sp = alloca(SIGNAL_TEST_CONTEXT_STACK_SIZE);
  1402. Context1.uc_stack.ss_size = SIGNAL_TEST_CONTEXT_STACK_SIZE;
  1403. Context1.uc_link = &MainContext;
  1404. makecontext(&Context1,
  1405. TestMakecontext,
  1406. 3,
  1407. &Context1,
  1408. &Context2,
  1409. 5);
  1410. if (getcontext(&Context2) != 0) {
  1411. PRINT_ERROR("getcontext failed");
  1412. exit(1);
  1413. }
  1414. Context2.uc_stack.ss_sp = alloca(SIGNAL_TEST_CONTEXT_STACK_SIZE);
  1415. Context2.uc_stack.ss_size = SIGNAL_TEST_CONTEXT_STACK_SIZE;
  1416. Context2.uc_link = NULL;
  1417. if (Exit == FALSE) {
  1418. Context2.uc_link = &Context1;
  1419. }
  1420. makecontext(&Context2,
  1421. TestMakecontext,
  1422. 3,
  1423. &Context2,
  1424. &Context1,
  1425. 10);
  1426. DEBUG_PRINT("MainContext swapping\n");
  1427. SigtestContextHits += 1;
  1428. if (swapcontext(&MainContext, &Context2) != 0) {
  1429. PRINT_ERROR("swapcontext failed.\n");
  1430. exit(1);
  1431. }
  1432. SigtestContextHits += 1;
  1433. if (Exit != FALSE) {
  1434. PRINT_ERROR("Main context returned instead of exited!\n");
  1435. exit(1);
  1436. }
  1437. if (SigtestContextHits != ((5 * 2) + (10 * 2) + 2)) {
  1438. PRINT_ERROR("Context hits were %d.\n", SigtestContextHits);
  1439. exit(1);
  1440. }
  1441. DEBUG_PRINT("MainContext exiting\n");
  1442. exit(0);
  1443. return 0;
  1444. }
  1445. VOID
  1446. TestMakecontext (
  1447. ucontext_t *OldContext,
  1448. ucontext_t *NextContext,
  1449. INT Identifier
  1450. )
  1451. /*++
  1452. Routine Description:
  1453. This routine swaps contexts.
  1454. Arguments:
  1455. OldContext - Supplies a pointer to the previous context.
  1456. NextContext - Supplies a pointer to the next context.
  1457. Identifier - Supplies an identifier for this context.
  1458. Return Value:
  1459. None.
  1460. --*/
  1461. {
  1462. DEBUG_PRINT("Context %d: Swapping\n", Identifier);
  1463. SigtestContextHits += Identifier;
  1464. if (swapcontext(OldContext, NextContext) != 0) {
  1465. PRINT_ERROR("Swapcontext failed from %d\n", Identifier);
  1466. exit(1);
  1467. }
  1468. DEBUG_PRINT("Context %d: Exiting\n", Identifier);
  1469. SigtestContextHits += Identifier;
  1470. return;
  1471. }