2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 /* Test of the process management library */
13 #include <afsconfig.h>
14 #include <afs/param.h>
32 extern char **environ;
35 #include <afs/procmgmt.h>
38 /* define constants */
40 #define TEST_CHILD_MAX 20 /* max number of active child procs in test */
42 #if defined(AFS_NT40_ENV)
43 /* Test for reset of signal() handler (i.e., unreliable signal() behavior).
44 * Note: some Unix systems implement a reliable form of signal(), some
45 * do not; NT does not. Only test the NT behavior because we trust
46 * the Unix implementation.
48 #define TEST_SIGNAL_RESET
54 static volatile int lastSignalCaught; /* last signo caught by sig handler */
55 static volatile int chldSignalCaught; /* SIGCHLD caught by sig handler */
57 static pid_t childPid[TEST_CHILD_MAX]; /* pids of active child procs */
59 static char spawntestDataBuffer[] = "Four score and seven years ago...";
62 /* define arguments for child processes
66 * argv[1] - CHILD_ARG1
68 * argv[3...n] - arguments for specified test (argv[2])
70 #define CHILD_ARG_BAD 255 /* child got bad args for test (exit status) */
71 #define CHILD_EXEC_FAILED 254 /* child failed exec() (Unix only) */
73 #define CHILD_ARG1 "cHiLd" /* indicates that proc is a child */
75 #define SPAWNTEST_ARG2 "spawntest" /* spawn test child */
76 #define SPAWNTEST_ARG_MAX 4 /* must match SPAWNTEST_ARG[] count */
77 static char *SPAWNTEST_ARG[] = {"fred and wilma",
79 "", /* test empty string arg */
80 "flintstone and rubble"};
82 #define SPAWNTEST_ENV_NAME "PMGT_SPAWNTEST"
83 #define SPAWNTEST_ENV_VALUE "bambam"
84 #define SPAWNTEST_ENV_SETSTR SPAWNTEST_ENV_NAME "=" SPAWNTEST_ENV_VALUE
86 #define SPAWNBUFTEST_ARG2 "spawnbuftest" /* spawn with buffer test child */
88 #define WAITTEST_ARG2 "waittest" /* wait test child */
90 #define WNOHANGTEST_ARG2 "wnohangtest" /* wait w/ WNOHANG test child */
92 #define SIGNALTEST_ARG2 "signaltest" /* signal test child */
94 #define ABORTTEST_ARG2 "aborttest" /* abort test child */
97 /* define utility functions */
100 * TimedSleep() -- put thread to sleep for specified number of seconds.
102 #define FOREVER 0xFFFFFFFF
105 TimedSleep(unsigned sec)
108 if (sec == FOREVER) {
114 if (sec == FOREVER) {
116 select(0, 0, 0, 0, 0);
119 time_t timeStart = time(NULL);
120 struct timeval sleeptime;
122 sleeptime.tv_sec = sec;
123 sleeptime.tv_usec = 0;
126 if (select(0, 0, 0, 0, &sleeptime) == 0) {
130 /* returned for reason other than timeout */
131 double cumSec = difftime(time(NULL), timeStart);
132 double remSec = (double)sec - cumSec;
137 sleeptime.tv_sec = ceil(remSec);
146 * Bailout() -- cleanup and exit test; parent only.
153 /* kill any child processes */
154 for (i = 0; i < TEST_CHILD_MAX; i++) {
155 if (childPid[i] > (pid_t)0) {
156 (void) kill(childPid[i], SIGKILL);
160 printf("\nAbandoning test due to error\n");
166 * ChildTableLookup() -- lookup child in childPid[] table and return index.
168 * Find specified child, or any child if pid is (pid_t)-1.
171 ChildTableLookup(pid_t pid)
175 for (i = 0; i < TEST_CHILD_MAX; i++) {
176 if ((childPid[i] > (pid_t)0) &&
177 (pid == (pid_t)-1 || childPid[i] == pid)) {
182 if (i >= TEST_CHILD_MAX) {
191 * ChildTableClear() -- clear childPid[] table.
194 ChildTableClear(void)
198 for (i = 0; i < TEST_CHILD_MAX; i++) {
199 childPid[i] = (pid_t)-1;
204 * Signal catching routine.
207 SignalCatcher(int signo)
209 lastSignalCaught = signo;
211 if (signo == SIGCHLD) {
212 chldSignalCaught = 1;
218 * Basic API test -- single threaded, no child processes.
224 void (*sigDisp)(int);
225 struct sigaction newAction, oldAction;
227 /* clear child pid vector for Bailout() */
230 printf("\n\nBASIC API TEST: SINGLE THREADED, NO CHILDREN\n\n");
232 /* -------------------------------------------------------------- */
234 printf("Testing signal set (sigset_t) manipulation functions\n");
236 sigemptyset(&sigSet);
238 if (sigismember(&sigSet, SIGHUP) ||
239 sigismember(&sigSet, SIGINT) ||
240 sigismember(&sigSet, SIGQUIT) ||
241 sigismember(&sigSet, SIGILL) ||
242 sigismember(&sigSet, SIGABRT) ||
243 sigismember(&sigSet, SIGFPE) ||
244 sigismember(&sigSet, SIGKILL) ||
245 sigismember(&sigSet, SIGSEGV) ||
246 sigismember(&sigSet, SIGTERM) ||
247 sigismember(&sigSet, SIGUSR1) ||
248 sigismember(&sigSet, SIGUSR2) ||
249 sigismember(&sigSet, SIGCHLD) ||
250 sigismember(&sigSet, SIGTSTP)) {
251 printf("sigemptyset() did not clear all defined signals\n");
257 if (!sigismember(&sigSet, SIGHUP) ||
258 !sigismember(&sigSet, SIGINT) ||
259 !sigismember(&sigSet, SIGQUIT) ||
260 !sigismember(&sigSet, SIGILL) ||
261 !sigismember(&sigSet, SIGABRT) ||
262 !sigismember(&sigSet, SIGFPE) ||
263 !sigismember(&sigSet, SIGKILL) ||
264 !sigismember(&sigSet, SIGSEGV) ||
265 !sigismember(&sigSet, SIGTERM) ||
266 !sigismember(&sigSet, SIGUSR1) ||
267 !sigismember(&sigSet, SIGUSR2) ||
268 !sigismember(&sigSet, SIGCHLD) ||
269 !sigismember(&sigSet, SIGTSTP)) {
270 printf("sigfillset() did not set all defined signals\n");
274 sigaddset(&sigSet, SIGUSR1);
275 sigaddset(&sigSet, SIGUSR2);
276 sigaddset(&sigSet, SIGINT);
278 if (!sigismember(&sigSet, SIGINT) ||
279 !sigismember(&sigSet, SIGUSR1) ||
280 !sigismember(&sigSet, SIGUSR2)) {
281 printf("sigaddset() did not add defined signal to set\n");
285 sigdelset(&sigSet, SIGUSR1);
286 sigdelset(&sigSet, SIGUSR2);
287 sigdelset(&sigSet, SIGINT);
289 if (sigismember(&sigSet, SIGINT) ||
290 sigismember(&sigSet, SIGUSR1) ||
291 sigismember(&sigSet, SIGUSR2)) {
292 printf("sigdelset() did not delete defined signal from set\n");
297 /* -------------------------------------------------------------- */
299 printf("Testing signal handler installation (sigaction(), signal())\n");
301 newAction.sa_handler = SignalCatcher;
302 sigemptyset(&newAction.sa_mask);
303 newAction.sa_flags = 0;
306 if (!sigaction(SIGKILL, &newAction, NULL)) {
307 printf("sigaction() allowed a handler to be set for SIGKILL\n");
309 } else if (errno != EINVAL) {
310 printf("sigaction(SIGKILL,...) did not set errno to EINVAL\n");
315 if (!sigaction(NSIG, &newAction, NULL)) {
316 printf("sigaction() allowed a handler for an invalid signo\n");
318 } else if (errno != EINVAL) {
319 printf("sigaction(NSIG,...) did not set errno to EINVAL\n");
324 if (signal(SIGKILL, SignalCatcher) != SIG_ERR) {
325 printf("signal() allowed a handler to be set for SIGKILL\n");
327 } else if (errno != EINVAL) {
328 printf("signal(SIGKILL,...) did not set errno to EINVAL\n");
333 if (signal(NSIG, SignalCatcher) != SIG_ERR) {
334 printf("signal() allowed a handler to be set for an invalid signo\n");
336 } else if (errno != EINVAL) {
337 printf("signal(NSIG,...) did not set errno to EINVAL\n");
341 if (sigaction(SIGTERM, &newAction, NULL)) {
342 printf("sigaction() failed to install valid signal handler\n");
346 if (sigaction(SIGTERM, NULL, &oldAction)) {
347 printf("sigaction() failed to retrieve old signal handler\n");
349 } else if (oldAction.sa_handler != newAction.sa_handler ||
350 oldAction.sa_flags != newAction.sa_flags) {
351 printf("sigaction() returned incorrect old signal handler values\n");
355 if ((sigDisp = signal(SIGTERM, SIG_DFL)) == SIG_ERR) {
356 printf("signal() failed to install valid signal handler\n");
358 } else if (sigDisp != newAction.sa_handler) {
359 printf("signal() returned incorrect old signal handler\n");
363 if ((sigDisp = signal(SIGTERM, SIG_DFL)) == SIG_ERR) {
364 printf("signal() failed to install valid signal handler (2)\n");
366 } else if (sigDisp != SIG_DFL) {
367 printf("signal() returned incorrect old signal handler (2)\n");
371 if (sigaction(SIGTERM, NULL, &oldAction)) {
372 printf("sigaction() failed to retrieve old signal handler (2)\n");
374 } else if (oldAction.sa_handler != SIG_DFL) {
375 printf("sigaction() returned incorrect old signal handler (2)\n");
380 /* -------------------------------------------------------------- */
382 printf("Testing signal catching (sigaction(), signal(), kill(), raise())\n");
384 newAction.sa_handler = SIG_DFL;
385 sigemptyset(&newAction.sa_mask);
386 newAction.sa_flags = 0;
388 if (sigaction(SIGCHLD, &newAction, NULL)) {
389 printf("sigaction() failed to install valid signal handler\n");
393 if (raise(SIGCHLD)) {
394 printf("raise() failed to send SIGCHLD (errno = %d)\n", errno);
398 TimedSleep(1); /* wait for signal delivery */
400 /* if made it here means SIGCHLD was (correctly) ignored */
402 newAction.sa_handler = SignalCatcher;
403 sigemptyset(&newAction.sa_mask);
404 newAction.sa_flags = 0;
406 if (sigaction(SIGTERM, &newAction, NULL) ||
407 sigaction(SIGUSR1, &newAction, NULL) ||
408 sigaction(SIGUSR2, &newAction, NULL)) {
409 printf("sigaction() failed to install valid signal handler (2)\n");
413 lastSignalCaught = NSIG;
415 if (raise(SIGTERM)) {
416 printf("raise() failed to send SIGTERM (errno = %d)\n", errno);
420 TimedSleep(1); /* wait for signal delivery */
422 if (lastSignalCaught != SIGTERM) {
423 printf("raise() failed to deliver SIGTERM\n");
427 if (raise(SIGUSR1)) {
428 printf("raise() failed to send SIGUSR1 (errno = %d)\n", errno);
432 TimedSleep(1); /* wait for signal delivery */
434 if (lastSignalCaught != SIGUSR1) {
435 printf("raise() failed to deliver SIGUSR1\n");
439 if (raise(SIGUSR2)) {
440 printf("raise() failed to send SIGUSR2 (errno = %d)\n", errno);
444 TimedSleep(1); /* wait for signal delivery */
446 if (lastSignalCaught != SIGUSR2) {
447 printf("raise() failed to deliver SIGUSR2\n");
451 if (sigaction(SIGTERM, NULL, &oldAction)) {
452 printf("sigaction() failed to retrieve old SIGTERM handler\n");
454 } else if (oldAction.sa_handler != newAction.sa_handler ||
455 oldAction.sa_flags != newAction.sa_flags) {
456 printf("sigaction() returned incorrect old SIGTERM handler values\n");
460 if (sigaction(SIGUSR1, NULL, &oldAction)) {
461 printf("sigaction() failed to retrieve old SIGUSR1 handler\n");
463 } else if (oldAction.sa_handler != newAction.sa_handler ||
464 oldAction.sa_flags != newAction.sa_flags) {
465 printf("sigaction() returned incorrect old SIGUSR1 handler values\n");
469 if (sigaction(SIGUSR2, NULL, &oldAction)) {
470 printf("sigaction() failed to retrieve old SIGUSR2 handler\n");
472 } else if (oldAction.sa_handler != newAction.sa_handler ||
473 oldAction.sa_flags != newAction.sa_flags) {
474 printf("sigaction() returned incorrect old SIGUSR2 handler values\n");
478 if (signal(SIGTERM, SignalCatcher) == SIG_ERR ||
479 signal(SIGUSR1, SignalCatcher) == SIG_ERR ||
480 signal(SIGUSR2, SignalCatcher) == SIG_ERR) {
481 printf("signal() failed to install valid signal handler (3)\n");
485 lastSignalCaught = NSIG;
487 if (kill(getpid(), SIGTERM)) {
488 printf("kill() failed to send SIGTERM (errno = %d)\n", errno);
492 TimedSleep(1); /* wait for signal delivery */
494 if (lastSignalCaught != SIGTERM) {
495 printf("kill() failed to deliver SIGTERM\n");
499 if (kill(getpid(), SIGUSR1)) {
500 printf("kill() failed to send SIGUSR1 (errno = %d)\n", errno);
504 TimedSleep(1); /* wait for signal delivery */
506 if (lastSignalCaught != SIGUSR1) {
507 printf("kill() failed to deliver SIGUSR1\n");
511 if (kill(getpid(), SIGUSR2)) {
512 printf("kill() failed to send SIGUSR2 (errno = %d)\n", errno);
516 TimedSleep(1); /* wait for signal delivery */
518 if (lastSignalCaught != SIGUSR2) {
519 printf("kill() failed to deliver SIGUSR2\n");
523 if ((sigDisp = signal(SIGTERM, SIG_DFL)) == SIG_ERR) {
524 printf("signal() failed to retrieve old SIGTERM handler\n");
526 } else if (sigDisp != SIG_DFL) {
527 #ifdef TEST_SIGNAL_RESET
528 printf("signal() returned incorrect old SIGTERM handler\n");
533 if ((sigDisp = signal(SIGUSR1, SIG_DFL)) == SIG_ERR) {
534 printf("signal() failed to retrieve old SIGUSR1 handler\n");
536 } else if (sigDisp != SIG_DFL) {
537 #ifdef TEST_SIGNAL_RESET
538 printf("signal() returned incorrect old SIGUSR1 handler\n");
543 if ((sigDisp = signal(SIGUSR2, SIG_DFL)) == SIG_ERR) {
544 printf("signal() failed to retrieve old SIGUSR2 handler\n");
546 } else if (sigDisp != SIG_DFL) {
547 #ifdef TEST_SIGNAL_RESET
548 printf("signal() returned incorrect old SIGUSR2 handler\n");
554 * NOTE: not testing effects of sa_mask in sigaction(); the NT process
555 * management library currently serializes signals (to get Unix
556 * signal handling semantics on a uniprocessor) so sa_mask is
557 * effectively ignored (since all signals, except SIGKILL, are
558 * blocked while a signal handler is running).
560 printf("\tNOTICE: effectiveness of sigaction()'s sa_mask not tested;\n");
561 printf("\tsee comments in test source\n");
565 /* -------------------------------------------------------------- */
567 printf("Testing childless waiting (wait(), waitpid())\n");
570 if (waitpid((pid_t)17, NULL, 0) != -1) {
571 printf("waitpid(17,...) with no child did not return -1\n");
573 } else if (errno != ECHILD) {
574 printf("waitpid(17,...) with no child did not set errno to ECHILD\n");
579 if (waitpid((pid_t)-1, NULL, 0) != -1) {
580 printf("waitpid(-1,...) with no child did not return -1\n");
582 } else if (errno != ECHILD) {
583 printf("waitpid(-1,...) with no child did not set errno to ECHILD\n");
588 if (wait(NULL) != -1) {
589 printf("wait() with no child did not return -1\n");
591 } else if (errno != ECHILD) {
592 printf("wait() with no child did not set errno to ECHILD\n");
600 * Process management test -- single threaded.
603 SingleThreadMgmtTest(char *exeName)
605 struct sigaction newAction;
606 char *childArgv[SPAWNTEST_ARG_MAX + 10];
607 char childArgStr[50];
609 int waitStatus, waitIdx;
613 printf("\n\nPROCESS MANAGEMENT TEST: SINGLE THREADED\n\n");
615 /* -------------------------------------------------------------- */
617 printf("Testing child spawning (spawnprocve(), wait(), WIFEXITED(), WEXITSTATUS())\n");
619 /* clear child pid vector for Bailout() */
622 /* Set SIGCHLD handler to SIG_DFL. NOTE: on some Unix systems, setting
623 * SIGCHLD handler to SIG_IGN changes the semantics of wait()/waitpid().
625 newAction.sa_handler = SIG_DFL;
626 sigfillset(&newAction.sa_mask);
627 newAction.sa_flags = 0;
629 if (sigaction(SIGCHLD, &newAction, NULL)) {
630 printf("sigaction() failed to install valid signal handler\n");
634 if (putenv(SPAWNTEST_ENV_SETSTR)) {
635 printf("putenv() failed\n");
639 childArgv[0] = exeName;
640 childArgv[1] = CHILD_ARG1;
641 childArgv[2] = SPAWNTEST_ARG2;
643 for (i = 0; i <= SPAWNTEST_ARG_MAX; i++) {
645 sprintf(countBuf, "%d", i);
647 childArgv[3] = countBuf;
649 for (j = 0; j < i; j++) {
650 childArgv[4 + j] = SPAWNTEST_ARG[j];
652 childArgv[4 + j] = NULL;
655 childPid[1] = spawnprocve(exeName,
656 childArgv, environ, CHILD_EXEC_FAILED);
658 childPid[1] = spawnprocv(exeName, childArgv, CHILD_EXEC_FAILED);
661 if (childPid[1] == (pid_t)-1) {
662 printf("spawnprocve(%s,...) failed to start child (errno = %d)\n",
668 waitPid = wait(&waitStatus);
669 } while (waitPid == (pid_t)-1 && errno == EINTR);
671 if (waitPid != childPid[1]) {
672 if (waitPid == (pid_t)-1) {
673 printf("wait() failed getting child status (errno = %d)\n",
676 printf("wait() returned wrong pid (expected = %d, got = %d)\n",
677 (int)childPid[1], (int)waitPid);
682 childPid[1] = (pid_t)-1; /* clear child pid for Bailout() */
684 if (!WIFEXITED(waitStatus)) {
685 printf("WIFEXITED() returned FALSE, expected TRUE\n");
689 if (WEXITSTATUS(waitStatus) != i) {
690 if (WEXITSTATUS(waitStatus) == CHILD_ARG_BAD) {
691 printf("WEXITSTATUS() indicates child got bad args\n");
692 } else if (WEXITSTATUS(waitStatus) == CHILD_EXEC_FAILED) {
693 printf("WEXITSTATUS() indicates child exec() failed\n");
695 printf("WEXITSTATUS() returned %d, expected %d\n",
696 (int)WEXITSTATUS(waitStatus), i);
703 /* -------------------------------------------------------------- */
705 #if defined(AFS_NT40_ENV)
707 printf("Testing child spawning with data buffer (spawnprocveb(), wait(), WIFEXITED(), WEXITSTATUS())\n");
709 /* clear child pid vector for Bailout() */
712 /* Set SIGCHLD handler to SIG_DFL. NOTE: on some Unix systems, setting
713 * SIGCHLD handler to SIG_IGN changes the semantics of wait()/waitpid().
715 newAction.sa_handler = SIG_DFL;
716 sigfillset(&newAction.sa_mask);
717 newAction.sa_flags = 0;
719 if (sigaction(SIGCHLD, &newAction, NULL)) {
720 printf("sigaction() failed to install valid signal handler\n");
724 if (putenv(SPAWNTEST_ENV_SETSTR)) {
725 printf("putenv() failed\n");
729 childArgv[0] = exeName;
730 childArgv[1] = CHILD_ARG1;
731 childArgv[2] = SPAWNBUFTEST_ARG2;
733 for (i = 0; i <= SPAWNTEST_ARG_MAX; i++) {
735 sprintf(countBuf, "%d", i);
737 childArgv[3] = countBuf;
739 for (j = 0; j < i; j++) {
740 childArgv[4 + j] = SPAWNTEST_ARG[j];
742 childArgv[4 + j] = NULL;
745 spawnprocveb(exeName,
747 spawntestDataBuffer, sizeof(spawntestDataBuffer));
749 if (childPid[1] == (pid_t)-1) {
750 printf("spawnprocveb(%s,...) failed to start child (errno = %d)\n",
756 waitPid = wait(&waitStatus);
757 } while (waitPid == (pid_t)-1 && errno == EINTR);
759 if (waitPid != childPid[1]) {
760 if (waitPid == (pid_t)-1) {
761 printf("wait() failed getting child status (errno = %d)\n",
764 printf("wait() returned wrong pid (expected = %d, got = %d)\n",
765 (int)childPid[1], (int)waitPid);
770 childPid[1] = (pid_t)-1; /* clear child pid for Bailout() */
772 if (!WIFEXITED(waitStatus)) {
773 printf("WIFEXITED() returned FALSE, expected TRUE\n");
777 if (WEXITSTATUS(waitStatus) != i) {
778 if (WEXITSTATUS(waitStatus) == CHILD_ARG_BAD) {
779 printf("WEXITSTATUS() indicates child got bad args\n");
781 printf("WEXITSTATUS() returned %d, expected %d\n",
782 (int)WEXITSTATUS(waitStatus), i);
788 #endif /* AFS_NT40_ENV */
791 /* -------------------------------------------------------------- */
793 printf("Testing child waiting (spawnprocve(), wait(), waitpid(), sigaction(), WIFEXITED(), WEXITSTATUS())\n");
795 /* clear child pid vector for Bailout() */
798 TimedSleep(3); /* wait for outstanding SIGCHLD's to get delivered */
800 lastSignalCaught = NSIG;
801 chldSignalCaught = 0;
803 newAction.sa_handler = SignalCatcher;
804 sigfillset(&newAction.sa_mask);
805 newAction.sa_flags = 0;
807 if (sigaction(SIGCHLD, &newAction, NULL)) {
808 printf("sigaction() failed to install valid signal handler\n");
812 childArgv[0] = exeName;
813 childArgv[1] = CHILD_ARG1;
814 childArgv[2] = WAITTEST_ARG2;
815 childArgv[3] = childArgStr;
818 for (i = 0; i < TEST_CHILD_MAX; i++) {
819 sprintf(childArgStr, "%d", i);
822 spawnprocve(exeName, childArgv, environ, CHILD_EXEC_FAILED);
824 if (childPid[i] == (pid_t)-1) {
825 printf("spawnprocve(%s,...) failed to start child (errno = %d)\n",
831 for (i = 0; i < TEST_CHILD_MAX; i++) {
835 waitPid = wait(&waitStatus);
836 } while (waitPid == (pid_t)-1 && errno == EINTR);
838 if (waitPid == (pid_t)-1) {
839 printf("wait() failed getting child status (errno = %d)\n",
844 waitIdx = ChildTableLookup(waitPid);
847 printf("wait() returned unknown pid (%d)\n", (int)waitPid);
852 waitIdx = ChildTableLookup((pid_t)-1);
855 printf("Child table unexpectedly empty\n");
860 waitPid = waitpid(childPid[waitIdx], &waitStatus, 0);
861 } while (waitPid == (pid_t)-1 && errno == EINTR);
863 if (waitPid != childPid[waitIdx]) {
864 if (waitPid == (pid_t)-1) {
865 printf("waitpid() failed getting status (errno = %d)\n",
868 printf("waitpid() returned wrong pid "
869 "(expected = %d, got = %d)\n",
870 (int)childPid[waitIdx], (int)waitPid);
876 childPid[waitIdx] = (pid_t)-1; /* clear child pid for Bailout() */
878 if (!WIFEXITED(waitStatus)) {
879 printf("WIFEXITED() returned FALSE, expected TRUE\n");
883 if (WEXITSTATUS(waitStatus) != waitIdx) {
884 if (WEXITSTATUS(waitStatus) == CHILD_ARG_BAD) {
885 printf("WEXITSTATUS() indicates child got bad args\n");
886 } else if (WEXITSTATUS(waitStatus) == CHILD_EXEC_FAILED) {
887 printf("WEXITSTATUS() indicates child exec() failed\n");
889 printf("WEXITSTATUS() returned %d, expected %d\n",
890 (int)WEXITSTATUS(waitStatus), waitIdx);
896 TimedSleep(3); /* wait for outstanding SIGCHLD's to get delivered */
898 if (!chldSignalCaught) {
899 printf("SIGCHLD never caught (last signo = %d)\n", lastSignalCaught);
904 /* -------------------------------------------------------------- */
906 printf("Testing child waiting with WNOHANG (spawnprocve(), waitpid(), kill())\n");
908 /* clear child pid vector for Bailout() */
911 /* Set SIGCHLD handler to SIG_DFL. NOTE: on some Unix systems, setting
912 * SIGCHLD handler to SIG_IGN changes the semantics of wait()/waitpid().
914 newAction.sa_handler = SIG_DFL;
915 sigfillset(&newAction.sa_mask);
916 newAction.sa_flags = 0;
918 if (sigaction(SIGCHLD, &newAction, NULL)) {
919 printf("sigaction() failed to install valid signal handler\n");
923 childArgv[0] = exeName;
924 childArgv[1] = CHILD_ARG1;
925 childArgv[2] = WNOHANGTEST_ARG2;
928 childPid[1] = spawnprocve(exeName, childArgv, environ, CHILD_EXEC_FAILED);
930 if (childPid[1] == (pid_t)-1) {
931 printf("spawnprocve(%s,...) failed to start child (errno = %d)\n",
936 for (i = 0; i < 20; i++) {
938 waitPid = waitpid(childPid[1], &waitStatus, WNOHANG);
939 } while (waitPid == (pid_t)-1 && errno == EINTR);
941 if (waitPid != (pid_t)0) {
942 if (waitPid == (pid_t)-1) {
943 printf("waitpid() failed getting child status (errno = %d)\n",
947 printf("waitpid() returned unexpected value (%d)\n", waitPid);
953 TimedSleep(2); /* wait for child to init signal mechanism (NT only) */
955 if (kill(childPid[1], SIGKILL)) {
956 printf("kill() failed to send SIGKILL (errno = %d)\n", errno);
961 waitPid = waitpid(childPid[1], &waitStatus, 0);
962 } while (waitPid == (pid_t)-1 && errno == EINTR);
964 if (waitPid != childPid[1]) {
965 if (waitPid == (pid_t)-1) {
966 printf("waitpid() failed getting child status (errno = %d)\n",
969 printf("waitpid() returned wrong pid (expected = %d, got = %d)\n",
970 (int)childPid[1], (int)waitPid);
975 childPid[1] = (pid_t)-1; /* clear child pid for Bailout() */
978 /* -------------------------------------------------------------- */
980 printf("Testing child signaling (spawnprocve(), kill(), waitpid(), sigaction(), WIFSIGNALED(), WTERMSIG())\n");
982 /* clear child pid vector for Bailout() */
985 TimedSleep(3); /* wait for outstanding SIGCHLD's to get delivered */
987 lastSignalCaught = NSIG;
988 chldSignalCaught = 0;
990 newAction.sa_handler = SignalCatcher;
991 sigfillset(&newAction.sa_mask);
992 newAction.sa_flags = 0;
994 if (sigaction(SIGCHLD, &newAction, NULL)) {
995 printf("sigaction() failed to install valid signal handler\n");
999 childArgv[0] = exeName;
1000 childArgv[1] = CHILD_ARG1;
1001 childArgv[2] = SIGNALTEST_ARG2;
1002 childArgv[3] = NULL;
1004 for (i = 0; i < TEST_CHILD_MAX; i++) {
1006 spawnprocve(exeName, childArgv, environ, CHILD_EXEC_FAILED);
1008 if (childPid[i] == (pid_t)-1) {
1009 printf("spawnprocve(%s,...) failed to start child (errno = %d)\n",
1015 TimedSleep(4); /* wait for children to init signal mechanism (NT only) */
1017 for (i = 0; i < TEST_CHILD_MAX; i++) {
1020 } else if (i % 3 == 1) {
1026 if (kill(childPid[i], signo)) {
1027 printf("kill() failed to send signal (errno = %d)\n", errno);
1032 for (i = 0; i < TEST_CHILD_MAX; i++) {
1035 } else if (i % 3 == 1) {
1042 waitPid = waitpid(childPid[i], &waitStatus, 0);
1043 } while (waitPid == (pid_t)-1 && errno == EINTR);
1045 if (waitPid != childPid[i]) {
1046 if (waitPid == (pid_t)-1) {
1047 printf("waitpid() failed getting child status (errno = %d)\n",
1050 printf("waitpid() returned wrong pid "
1051 "(expected = %d, got = %d)\n",
1052 (int)childPid[i], (int)waitPid);
1057 childPid[i] = (pid_t)-1; /* clear child pid for Bailout() */
1059 if (!WIFSIGNALED(waitStatus)) {
1060 printf("WIFSIGNALED() returned FALSE, expected TRUE\n");
1064 if (WTERMSIG(waitStatus) != signo) {
1065 printf("WTERMSIG() returned %d, expected %d\n",
1066 (int)WTERMSIG(waitStatus), signo);
1071 TimedSleep(3); /* wait for outstanding SIGCHLD's to get delivered */
1073 if (!chldSignalCaught) {
1074 printf("SIGCHLD never caught (last signo = %d)\n", lastSignalCaught);
1078 if (signal(SIGCHLD, SIG_DFL) == SIG_ERR) {
1079 printf("sigaction() failed to install valid signal handler\n");
1084 /* -------------------------------------------------------------- */
1086 printf("Testing child aborting (spawnprocve(), waitpid(), WIFSIGNALED(), WTERMSIG())\n");
1088 /* clear child pid vector for Bailout() */
1091 TimedSleep(3); /* wait for outstanding SIGCHLD's to get delivered */
1093 lastSignalCaught = NSIG;
1094 chldSignalCaught = 0;
1096 newAction.sa_handler = SignalCatcher;
1097 sigfillset(&newAction.sa_mask);
1098 newAction.sa_flags = 0;
1100 if (sigaction(SIGCHLD, &newAction, NULL)) {
1101 printf("sigaction() failed to install valid signal handler\n");
1105 childArgv[0] = exeName;
1106 childArgv[1] = CHILD_ARG1;
1107 childArgv[2] = ABORTTEST_ARG2;
1108 childArgv[3] = NULL;
1111 spawnprocve(exeName, childArgv, environ, CHILD_EXEC_FAILED);
1113 if (childPid[1] == (pid_t)-1) {
1114 printf("spawnprocve(%s,...) failed to start child (errno = %d)\n",
1119 TimedSleep(2); /* wait for child to init signal mechanism (NT only) */
1122 waitPid = waitpid(childPid[1], &waitStatus, 0);
1123 } while (waitPid == (pid_t)-1 && errno == EINTR);
1125 if (waitPid != childPid[1]) {
1126 if (waitPid == (pid_t)-1) {
1127 printf("waitpid() failed getting child status (errno = %d)\n",
1130 printf("waitpid() returned wrong pid (expected = %d, got = %d)\n",
1131 (int)childPid[1], (int)waitPid);
1136 childPid[1] = (pid_t)-1; /* clear child pid for Bailout() */
1138 if (!WIFSIGNALED(waitStatus)) {
1139 printf("WIFSIGNALED() returned FALSE, expected TRUE\n");
1143 if (WTERMSIG(waitStatus) != SIGABRT) {
1144 printf("WTERMSIG() returned %d, expected SIGABRT (%d)\n",
1145 (int)WTERMSIG(waitStatus), (int)SIGABRT);
1149 TimedSleep(3); /* wait for outstanding SIGCHLD's to get delivered */
1151 if (!chldSignalCaught) {
1152 printf("SIGCHLD never caught (last signo = %d)\n", lastSignalCaught);
1156 if (signal(SIGCHLD, SIG_DFL) == SIG_ERR) {
1157 printf("sigaction() failed to install valid signal handler\n");
1165 * Parent process behavior.
1168 BehaveLikeAParent(int argc, char *argv[])
1171 SingleThreadMgmtTest(argv[0]);
1173 printf("\nAll tests completed successfully.\n");
1178 * Child process behavior.
1181 BehaveLikeAChild(int argc, char *argv[])
1187 /* Turn off debug message box used by abort()/assert() in debug
1188 * version of MSVC C run-time library.
1190 (void) _CrtSetReportMode(_CRT_WARN, 0);
1191 (void) _CrtSetReportMode(_CRT_ERROR, 0);
1192 (void) _CrtSetReportMode(_CRT_ASSERT, 0);
1195 /* verify that argc and argv are in sync */
1196 for (argvCount = 0; argv[argvCount]; argvCount++);
1198 if (argc != argvCount) {
1199 exit(CHILD_ARG_BAD);
1202 /* verify test argument format */
1205 /* all tests require at least argv[2] (test name) */
1206 exit(CHILD_ARG_BAD);
1209 /* perform as required for particular test */
1213 if (!strcmp(testName, SPAWNTEST_ARG2)) {
1214 /* SPAWN TEST child */
1218 if (((envstr = getenv(SPAWNTEST_ENV_NAME)) == NULL) ||
1219 (strcmp(envstr, SPAWNTEST_ENV_VALUE))) {
1220 exit(CHILD_ARG_BAD);
1223 if (atoi(argv[3]) != (argc - 4)) {
1224 exit(CHILD_ARG_BAD);
1227 for (i = 0; i < argc - 4; i++) {
1228 if (strcmp(argv[4 + i], SPAWNTEST_ARG[i])) {
1229 exit(CHILD_ARG_BAD);
1233 #if defined(AFS_NT40_ENV)
1234 if (spawnDatap != NULL || spawnDataLen != 0) {
1235 exit(CHILD_ARG_BAD);
1241 #if defined(AFS_NT40_ENV)
1242 } else if (!strcmp(testName, SPAWNBUFTEST_ARG2)) {
1243 /* SPAWNBUF TEST child */
1247 if (((envstr = getenv(SPAWNTEST_ENV_NAME)) == NULL) ||
1248 (strcmp(envstr, SPAWNTEST_ENV_VALUE))) {
1249 exit(CHILD_ARG_BAD);
1252 if (atoi(argv[3]) != (argc - 4)) {
1253 exit(CHILD_ARG_BAD);
1256 for (i = 0; i < argc - 4; i++) {
1257 if (strcmp(argv[4 + i], SPAWNTEST_ARG[i])) {
1258 exit(CHILD_ARG_BAD);
1262 if (spawnDataLen != sizeof(spawntestDataBuffer) ||
1263 strcmp(spawnDatap, spawntestDataBuffer)) {
1264 exit(CHILD_ARG_BAD);
1268 #endif /* AFS_NT40_ENV */
1271 } else if (!strcmp(testName, WAITTEST_ARG2)) {
1272 /* WAIT TEST child */
1276 exit(CHILD_ARG_BAD);
1279 rc = strtol(argv[3], NULL, 10);
1283 } else if (!strcmp(testName, WNOHANGTEST_ARG2)) {
1284 /* WNOHANG TEST child */
1285 TimedSleep(FOREVER);
1286 printf("\tchild unexpectedly returned from TimedSleep(FOREVER)\n");
1287 exit(1); /* should never execute */
1289 } else if (!strcmp(testName, SIGNALTEST_ARG2)) {
1290 /* SIGNAL TEST child */
1291 TimedSleep(FOREVER);
1292 printf("\tchild unexpectedly returned from TimedSleep(FOREVER)\n");
1293 exit(1); /* should never execute */
1295 } else if (!strcmp(testName, ABORTTEST_ARG2)) {
1296 /* ABORT TEST child */
1299 printf("\tNOTICE:\n");
1300 printf("\t\tChild is calling abort().\n");
1301 printf("\t\tAbnormal termination message will appear.\n");
1302 printf("\t\tA software exception dialog will appear; press 'OK'.\n");
1303 printf("\t\tAutomatic debugger invocation MUST be disabled.\n");
1307 printf("\tchild unexpectedly returned from abort()\n");
1308 exit(1); /* should never execute */
1312 exit(CHILD_ARG_BAD);
1320 int main(int argc, char *argv[])
1323 /* PARENT process */
1324 BehaveLikeAParent(argc, argv);
1325 } else if ((argc > 1) && !strcmp(argv[1], CHILD_ARG1)) {
1327 BehaveLikeAChild(argc, argv);
1329 printf("\nUsage: %s\n", argv[0]);