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 <afs/param.h>
28 extern char **environ;
31 #include <afs/procmgmt.h>
34 /* define constants */
36 #define TEST_CHILD_MAX 20 /* max number of active child procs in test */
38 #if defined(AFS_NT40_ENV)
39 /* Test for reset of signal() handler (i.e., unreliable signal() behavior).
40 * Note: some Unix systems implement a reliable form of signal(), some
41 * do not; NT does not. Only test the NT behavior because we trust
42 * the Unix implementation.
44 #define TEST_SIGNAL_RESET
50 static volatile int lastSignalCaught; /* last signo caught by sig handler */
51 static volatile int chldSignalCaught; /* SIGCHLD caught by sig handler */
53 static pid_t childPid[TEST_CHILD_MAX]; /* pids of active child procs */
55 static char spawntestDataBuffer[] = "Four score and seven years ago...";
58 /* define arguments for child processes
62 * argv[1] - CHILD_ARG1
64 * argv[3...n] - arguments for specified test (argv[2])
66 #define CHILD_ARG_BAD 255 /* child got bad args for test (exit status) */
67 #define CHILD_EXEC_FAILED 254 /* child failed exec() (Unix only) */
69 #define CHILD_ARG1 "cHiLd" /* indicates that proc is a child */
71 #define SPAWNTEST_ARG2 "spawntest" /* spawn test child */
72 #define SPAWNTEST_ARG_MAX 4 /* must match SPAWNTEST_ARG[] count */
73 static char *SPAWNTEST_ARG[] = {"fred and wilma",
75 "", /* test empty string arg */
76 "flintstone and rubble"};
78 #define SPAWNTEST_ENV_NAME "PMGT_SPAWNTEST"
79 #define SPAWNTEST_ENV_VALUE "bambam"
80 #define SPAWNTEST_ENV_SETSTR SPAWNTEST_ENV_NAME "=" SPAWNTEST_ENV_VALUE
82 #define SPAWNBUFTEST_ARG2 "spawnbuftest" /* spawn with buffer test child */
84 #define WAITTEST_ARG2 "waittest" /* wait test child */
86 #define WNOHANGTEST_ARG2 "wnohangtest" /* wait w/ WNOHANG test child */
88 #define SIGNALTEST_ARG2 "signaltest" /* signal test child */
90 #define ABORTTEST_ARG2 "aborttest" /* abort test child */
93 /* define utility functions */
96 * TimedSleep() -- put thread to sleep for specified number of seconds.
98 #define FOREVER 0xFFFFFFFF
101 TimedSleep(unsigned sec)
104 if (sec == FOREVER) {
110 if (sec == FOREVER) {
112 select(0, 0, 0, 0, 0);
115 time_t timeStart = time(NULL);
116 struct timeval sleeptime;
118 sleeptime.tv_sec = sec;
119 sleeptime.tv_usec = 0;
122 if (select(0, 0, 0, 0, &sleeptime) == 0) {
126 /* returned for reason other than timeout */
127 double cumSec = difftime(time(NULL), timeStart);
128 double remSec = (double)sec - cumSec;
133 sleeptime.tv_sec = ceil(remSec);
142 * Bailout() -- cleanup and exit test; parent only.
149 /* kill any child processes */
150 for (i = 0; i < TEST_CHILD_MAX; i++) {
151 if (childPid[i] > (pid_t)0) {
152 (void) kill(childPid[i], SIGKILL);
156 printf("\nAbandoning test due to error\n");
162 * ChildTableLookup() -- lookup child in childPid[] table and return index.
164 * Find specified child, or any child if pid is (pid_t)-1.
167 ChildTableLookup(pid_t pid)
171 for (i = 0; i < TEST_CHILD_MAX; i++) {
172 if ((childPid[i] > (pid_t)0) &&
173 (pid == (pid_t)-1 || childPid[i] == pid)) {
178 if (i >= TEST_CHILD_MAX) {
187 * ChildTableClear() -- clear childPid[] table.
190 ChildTableClear(void)
194 for (i = 0; i < TEST_CHILD_MAX; i++) {
195 childPid[i] = (pid_t)-1;
200 * Signal catching routine.
203 SignalCatcher(int signo)
205 lastSignalCaught = signo;
207 if (signo == SIGCHLD) {
208 chldSignalCaught = 1;
214 * Basic API test -- single threaded, no child processes.
220 void (*sigDisp)(int);
221 struct sigaction newAction, oldAction;
223 /* clear child pid vector for Bailout() */
226 printf("\n\nBASIC API TEST: SINGLE THREADED, NO CHILDREN\n\n");
228 /* -------------------------------------------------------------- */
230 printf("Testing signal set (sigset_t) manipulation functions\n");
232 sigemptyset(&sigSet);
234 if (sigismember(&sigSet, SIGHUP) ||
235 sigismember(&sigSet, SIGINT) ||
236 sigismember(&sigSet, SIGQUIT) ||
237 sigismember(&sigSet, SIGILL) ||
238 sigismember(&sigSet, SIGABRT) ||
239 sigismember(&sigSet, SIGFPE) ||
240 sigismember(&sigSet, SIGKILL) ||
241 sigismember(&sigSet, SIGSEGV) ||
242 sigismember(&sigSet, SIGTERM) ||
243 sigismember(&sigSet, SIGUSR1) ||
244 sigismember(&sigSet, SIGUSR2) ||
245 sigismember(&sigSet, SIGCHLD) ||
246 sigismember(&sigSet, SIGTSTP)) {
247 printf("sigemptyset() did not clear all defined signals\n");
253 if (!sigismember(&sigSet, SIGHUP) ||
254 !sigismember(&sigSet, SIGINT) ||
255 !sigismember(&sigSet, SIGQUIT) ||
256 !sigismember(&sigSet, SIGILL) ||
257 !sigismember(&sigSet, SIGABRT) ||
258 !sigismember(&sigSet, SIGFPE) ||
259 !sigismember(&sigSet, SIGKILL) ||
260 !sigismember(&sigSet, SIGSEGV) ||
261 !sigismember(&sigSet, SIGTERM) ||
262 !sigismember(&sigSet, SIGUSR1) ||
263 !sigismember(&sigSet, SIGUSR2) ||
264 !sigismember(&sigSet, SIGCHLD) ||
265 !sigismember(&sigSet, SIGTSTP)) {
266 printf("sigfillset() did not set all defined signals\n");
270 sigaddset(&sigSet, SIGUSR1);
271 sigaddset(&sigSet, SIGUSR2);
272 sigaddset(&sigSet, SIGINT);
274 if (!sigismember(&sigSet, SIGINT) ||
275 !sigismember(&sigSet, SIGUSR1) ||
276 !sigismember(&sigSet, SIGUSR2)) {
277 printf("sigaddset() did not add defined signal to set\n");
281 sigdelset(&sigSet, SIGUSR1);
282 sigdelset(&sigSet, SIGUSR2);
283 sigdelset(&sigSet, SIGINT);
285 if (sigismember(&sigSet, SIGINT) ||
286 sigismember(&sigSet, SIGUSR1) ||
287 sigismember(&sigSet, SIGUSR2)) {
288 printf("sigdelset() did not delete defined signal from set\n");
293 /* -------------------------------------------------------------- */
295 printf("Testing signal handler installation (sigaction(), signal())\n");
297 newAction.sa_handler = SignalCatcher;
298 sigemptyset(&newAction.sa_mask);
299 newAction.sa_flags = 0;
302 if (!sigaction(SIGKILL, &newAction, NULL)) {
303 printf("sigaction() allowed a handler to be set for SIGKILL\n");
305 } else if (errno != EINVAL) {
306 printf("sigaction(SIGKILL,...) did not set errno to EINVAL\n");
311 if (!sigaction(NSIG, &newAction, NULL)) {
312 printf("sigaction() allowed a handler for an invalid signo\n");
314 } else if (errno != EINVAL) {
315 printf("sigaction(NSIG,...) did not set errno to EINVAL\n");
320 if (signal(SIGKILL, SignalCatcher) != SIG_ERR) {
321 printf("signal() allowed a handler to be set for SIGKILL\n");
323 } else if (errno != EINVAL) {
324 printf("signal(SIGKILL,...) did not set errno to EINVAL\n");
329 if (signal(NSIG, SignalCatcher) != SIG_ERR) {
330 printf("signal() allowed a handler to be set for an invalid signo\n");
332 } else if (errno != EINVAL) {
333 printf("signal(NSIG,...) did not set errno to EINVAL\n");
337 if (sigaction(SIGTERM, &newAction, NULL)) {
338 printf("sigaction() failed to install valid signal handler\n");
342 if (sigaction(SIGTERM, NULL, &oldAction)) {
343 printf("sigaction() failed to retrieve old signal handler\n");
345 } else if (oldAction.sa_handler != newAction.sa_handler ||
346 oldAction.sa_flags != newAction.sa_flags) {
347 printf("sigaction() returned incorrect old signal handler values\n");
351 if ((sigDisp = signal(SIGTERM, SIG_DFL)) == SIG_ERR) {
352 printf("signal() failed to install valid signal handler\n");
354 } else if (sigDisp != newAction.sa_handler) {
355 printf("signal() returned incorrect old signal handler\n");
359 if ((sigDisp = signal(SIGTERM, SIG_DFL)) == SIG_ERR) {
360 printf("signal() failed to install valid signal handler (2)\n");
362 } else if (sigDisp != SIG_DFL) {
363 printf("signal() returned incorrect old signal handler (2)\n");
367 if (sigaction(SIGTERM, NULL, &oldAction)) {
368 printf("sigaction() failed to retrieve old signal handler (2)\n");
370 } else if (oldAction.sa_handler != SIG_DFL) {
371 printf("sigaction() returned incorrect old signal handler (2)\n");
376 /* -------------------------------------------------------------- */
378 printf("Testing signal catching (sigaction(), signal(), kill(), raise())\n");
380 newAction.sa_handler = SIG_DFL;
381 sigemptyset(&newAction.sa_mask);
382 newAction.sa_flags = 0;
384 if (sigaction(SIGCHLD, &newAction, NULL)) {
385 printf("sigaction() failed to install valid signal handler\n");
389 if (raise(SIGCHLD)) {
390 printf("raise() failed to send SIGCHLD (errno = %d)\n", errno);
394 TimedSleep(1); /* wait for signal delivery */
396 /* if made it here means SIGCHLD was (correctly) ignored */
398 newAction.sa_handler = SignalCatcher;
399 sigemptyset(&newAction.sa_mask);
400 newAction.sa_flags = 0;
402 if (sigaction(SIGTERM, &newAction, NULL) ||
403 sigaction(SIGUSR1, &newAction, NULL) ||
404 sigaction(SIGUSR2, &newAction, NULL)) {
405 printf("sigaction() failed to install valid signal handler (2)\n");
409 lastSignalCaught = NSIG;
411 if (raise(SIGTERM)) {
412 printf("raise() failed to send SIGTERM (errno = %d)\n", errno);
416 TimedSleep(1); /* wait for signal delivery */
418 if (lastSignalCaught != SIGTERM) {
419 printf("raise() failed to deliver SIGTERM\n");
423 if (raise(SIGUSR1)) {
424 printf("raise() failed to send SIGUSR1 (errno = %d)\n", errno);
428 TimedSleep(1); /* wait for signal delivery */
430 if (lastSignalCaught != SIGUSR1) {
431 printf("raise() failed to deliver SIGUSR1\n");
435 if (raise(SIGUSR2)) {
436 printf("raise() failed to send SIGUSR2 (errno = %d)\n", errno);
440 TimedSleep(1); /* wait for signal delivery */
442 if (lastSignalCaught != SIGUSR2) {
443 printf("raise() failed to deliver SIGUSR2\n");
447 if (sigaction(SIGTERM, NULL, &oldAction)) {
448 printf("sigaction() failed to retrieve old SIGTERM handler\n");
450 } else if (oldAction.sa_handler != newAction.sa_handler ||
451 oldAction.sa_flags != newAction.sa_flags) {
452 printf("sigaction() returned incorrect old SIGTERM handler values\n");
456 if (sigaction(SIGUSR1, NULL, &oldAction)) {
457 printf("sigaction() failed to retrieve old SIGUSR1 handler\n");
459 } else if (oldAction.sa_handler != newAction.sa_handler ||
460 oldAction.sa_flags != newAction.sa_flags) {
461 printf("sigaction() returned incorrect old SIGUSR1 handler values\n");
465 if (sigaction(SIGUSR2, NULL, &oldAction)) {
466 printf("sigaction() failed to retrieve old SIGUSR2 handler\n");
468 } else if (oldAction.sa_handler != newAction.sa_handler ||
469 oldAction.sa_flags != newAction.sa_flags) {
470 printf("sigaction() returned incorrect old SIGUSR2 handler values\n");
474 if (signal(SIGTERM, SignalCatcher) == SIG_ERR ||
475 signal(SIGUSR1, SignalCatcher) == SIG_ERR ||
476 signal(SIGUSR2, SignalCatcher) == SIG_ERR) {
477 printf("signal() failed to install valid signal handler (3)\n");
481 lastSignalCaught = NSIG;
483 if (kill(getpid(), SIGTERM)) {
484 printf("kill() failed to send SIGTERM (errno = %d)\n", errno);
488 TimedSleep(1); /* wait for signal delivery */
490 if (lastSignalCaught != SIGTERM) {
491 printf("kill() failed to deliver SIGTERM\n");
495 if (kill(getpid(), SIGUSR1)) {
496 printf("kill() failed to send SIGUSR1 (errno = %d)\n", errno);
500 TimedSleep(1); /* wait for signal delivery */
502 if (lastSignalCaught != SIGUSR1) {
503 printf("kill() failed to deliver SIGUSR1\n");
507 if (kill(getpid(), SIGUSR2)) {
508 printf("kill() failed to send SIGUSR2 (errno = %d)\n", errno);
512 TimedSleep(1); /* wait for signal delivery */
514 if (lastSignalCaught != SIGUSR2) {
515 printf("kill() failed to deliver SIGUSR2\n");
519 if ((sigDisp = signal(SIGTERM, SIG_DFL)) == SIG_ERR) {
520 printf("signal() failed to retrieve old SIGTERM handler\n");
522 } else if (sigDisp != SIG_DFL) {
523 #ifdef TEST_SIGNAL_RESET
524 printf("signal() returned incorrect old SIGTERM handler\n");
529 if ((sigDisp = signal(SIGUSR1, SIG_DFL)) == SIG_ERR) {
530 printf("signal() failed to retrieve old SIGUSR1 handler\n");
532 } else if (sigDisp != SIG_DFL) {
533 #ifdef TEST_SIGNAL_RESET
534 printf("signal() returned incorrect old SIGUSR1 handler\n");
539 if ((sigDisp = signal(SIGUSR2, SIG_DFL)) == SIG_ERR) {
540 printf("signal() failed to retrieve old SIGUSR2 handler\n");
542 } else if (sigDisp != SIG_DFL) {
543 #ifdef TEST_SIGNAL_RESET
544 printf("signal() returned incorrect old SIGUSR2 handler\n");
550 * NOTE: not testing effects of sa_mask in sigaction(); the NT process
551 * management library currently serializes signals (to get Unix
552 * signal handling semantics on a uniprocessor) so sa_mask is
553 * effectively ignored (since all signals, except SIGKILL, are
554 * blocked while a signal handler is running).
556 printf("\tNOTICE: effectiveness of sigaction()'s sa_mask not tested;\n");
557 printf("\tsee comments in test source\n");
561 /* -------------------------------------------------------------- */
563 printf("Testing childless waiting (wait(), waitpid())\n");
566 if (waitpid((pid_t)17, NULL, 0) != -1) {
567 printf("waitpid(17,...) with no child did not return -1\n");
569 } else if (errno != ECHILD) {
570 printf("waitpid(17,...) with no child did not set errno to ECHILD\n");
575 if (waitpid((pid_t)-1, NULL, 0) != -1) {
576 printf("waitpid(-1,...) with no child did not return -1\n");
578 } else if (errno != ECHILD) {
579 printf("waitpid(-1,...) with no child did not set errno to ECHILD\n");
584 if (wait(NULL) != -1) {
585 printf("wait() with no child did not return -1\n");
587 } else if (errno != ECHILD) {
588 printf("wait() with no child did not set errno to ECHILD\n");
596 * Process management test -- single threaded.
599 SingleThreadMgmtTest(char *exeName)
601 struct sigaction newAction;
602 char *childArgv[SPAWNTEST_ARG_MAX + 10];
603 char childArgStr[50];
605 int waitStatus, waitIdx;
609 printf("\n\nPROCESS MANAGEMENT TEST: SINGLE THREADED\n\n");
611 /* -------------------------------------------------------------- */
613 printf("Testing child spawning (spawnprocve(), wait(), WIFEXITED(), WEXITSTATUS())\n");
615 /* clear child pid vector for Bailout() */
618 /* Set SIGCHLD handler to SIG_DFL. NOTE: on some Unix systems, setting
619 * SIGCHLD handler to SIG_IGN changes the semantics of wait()/waitpid().
621 newAction.sa_handler = SIG_DFL;
622 sigfillset(&newAction.sa_mask);
623 newAction.sa_flags = 0;
625 if (sigaction(SIGCHLD, &newAction, NULL)) {
626 printf("sigaction() failed to install valid signal handler\n");
630 if (putenv(SPAWNTEST_ENV_SETSTR)) {
631 printf("putenv() failed\n");
635 childArgv[0] = exeName;
636 childArgv[1] = CHILD_ARG1;
637 childArgv[2] = SPAWNTEST_ARG2;
639 for (i = 0; i <= SPAWNTEST_ARG_MAX; i++) {
641 sprintf(countBuf, "%d", i);
643 childArgv[3] = countBuf;
645 for (j = 0; j < i; j++) {
646 childArgv[4 + j] = SPAWNTEST_ARG[j];
648 childArgv[4 + j] = NULL;
651 childPid[1] = spawnprocve(exeName,
652 childArgv, environ, CHILD_EXEC_FAILED);
654 childPid[1] = spawnprocv(exeName, childArgv, CHILD_EXEC_FAILED);
657 if (childPid[1] == (pid_t)-1) {
658 printf("spawnprocve(%s,...) failed to start child (errno = %d)\n",
664 waitPid = wait(&waitStatus);
665 } while (waitPid == (pid_t)-1 && errno == EINTR);
667 if (waitPid != childPid[1]) {
668 if (waitPid == (pid_t)-1) {
669 printf("wait() failed getting child status (errno = %d)\n",
672 printf("wait() returned wrong pid (expected = %d, got = %d)\n",
673 (int)childPid[1], (int)waitPid);
678 childPid[1] = (pid_t)-1; /* clear child pid for Bailout() */
680 if (!WIFEXITED(waitStatus)) {
681 printf("WIFEXITED() returned FALSE, expected TRUE\n");
685 if (WEXITSTATUS(waitStatus) != i) {
686 if (WEXITSTATUS(waitStatus) == CHILD_ARG_BAD) {
687 printf("WEXITSTATUS() indicates child got bad args\n");
688 } else if (WEXITSTATUS(waitStatus) == CHILD_EXEC_FAILED) {
689 printf("WEXITSTATUS() indicates child exec() failed\n");
691 printf("WEXITSTATUS() returned %d, expected %d\n",
692 (int)WEXITSTATUS(waitStatus), i);
699 /* -------------------------------------------------------------- */
701 #if defined(AFS_NT40_ENV)
703 printf("Testing child spawning with data buffer (spawnprocveb(), wait(), WIFEXITED(), WEXITSTATUS())\n");
705 /* clear child pid vector for Bailout() */
708 /* Set SIGCHLD handler to SIG_DFL. NOTE: on some Unix systems, setting
709 * SIGCHLD handler to SIG_IGN changes the semantics of wait()/waitpid().
711 newAction.sa_handler = SIG_DFL;
712 sigfillset(&newAction.sa_mask);
713 newAction.sa_flags = 0;
715 if (sigaction(SIGCHLD, &newAction, NULL)) {
716 printf("sigaction() failed to install valid signal handler\n");
720 if (putenv(SPAWNTEST_ENV_SETSTR)) {
721 printf("putenv() failed\n");
725 childArgv[0] = exeName;
726 childArgv[1] = CHILD_ARG1;
727 childArgv[2] = SPAWNBUFTEST_ARG2;
729 for (i = 0; i <= SPAWNTEST_ARG_MAX; i++) {
731 sprintf(countBuf, "%d", i);
733 childArgv[3] = countBuf;
735 for (j = 0; j < i; j++) {
736 childArgv[4 + j] = SPAWNTEST_ARG[j];
738 childArgv[4 + j] = NULL;
741 spawnprocveb(exeName,
743 spawntestDataBuffer, sizeof(spawntestDataBuffer));
745 if (childPid[1] == (pid_t)-1) {
746 printf("spawnprocveb(%s,...) failed to start child (errno = %d)\n",
752 waitPid = wait(&waitStatus);
753 } while (waitPid == (pid_t)-1 && errno == EINTR);
755 if (waitPid != childPid[1]) {
756 if (waitPid == (pid_t)-1) {
757 printf("wait() failed getting child status (errno = %d)\n",
760 printf("wait() returned wrong pid (expected = %d, got = %d)\n",
761 (int)childPid[1], (int)waitPid);
766 childPid[1] = (pid_t)-1; /* clear child pid for Bailout() */
768 if (!WIFEXITED(waitStatus)) {
769 printf("WIFEXITED() returned FALSE, expected TRUE\n");
773 if (WEXITSTATUS(waitStatus) != i) {
774 if (WEXITSTATUS(waitStatus) == CHILD_ARG_BAD) {
775 printf("WEXITSTATUS() indicates child got bad args\n");
777 printf("WEXITSTATUS() returned %d, expected %d\n",
778 (int)WEXITSTATUS(waitStatus), i);
784 #endif /* AFS_NT40_ENV */
787 /* -------------------------------------------------------------- */
789 printf("Testing child waiting (spawnprocve(), wait(), waitpid(), sigaction(), WIFEXITED(), WEXITSTATUS())\n");
791 /* clear child pid vector for Bailout() */
794 TimedSleep(3); /* wait for outstanding SIGCHLD's to get delivered */
796 lastSignalCaught = NSIG;
797 chldSignalCaught = 0;
799 newAction.sa_handler = SignalCatcher;
800 sigfillset(&newAction.sa_mask);
801 newAction.sa_flags = 0;
803 if (sigaction(SIGCHLD, &newAction, NULL)) {
804 printf("sigaction() failed to install valid signal handler\n");
808 childArgv[0] = exeName;
809 childArgv[1] = CHILD_ARG1;
810 childArgv[2] = WAITTEST_ARG2;
811 childArgv[3] = childArgStr;
814 for (i = 0; i < TEST_CHILD_MAX; i++) {
815 sprintf(childArgStr, "%d", i);
818 spawnprocve(exeName, childArgv, environ, CHILD_EXEC_FAILED);
820 if (childPid[i] == (pid_t)-1) {
821 printf("spawnprocve(%s,...) failed to start child (errno = %d)\n",
827 for (i = 0; i < TEST_CHILD_MAX; i++) {
831 waitPid = wait(&waitStatus);
832 } while (waitPid == (pid_t)-1 && errno == EINTR);
834 if (waitPid == (pid_t)-1) {
835 printf("wait() failed getting child status (errno = %d)\n",
840 waitIdx = ChildTableLookup(waitPid);
843 printf("wait() returned unknown pid (%d)\n", (int)waitPid);
848 waitIdx = ChildTableLookup((pid_t)-1);
851 printf("Child table unexpectedly empty\n");
856 waitPid = waitpid(childPid[waitIdx], &waitStatus, 0);
857 } while (waitPid == (pid_t)-1 && errno == EINTR);
859 if (waitPid != childPid[waitIdx]) {
860 if (waitPid == (pid_t)-1) {
861 printf("waitpid() failed getting status (errno = %d)\n",
864 printf("waitpid() returned wrong pid "
865 "(expected = %d, got = %d)\n",
866 (int)childPid[waitIdx], (int)waitPid);
872 childPid[waitIdx] = (pid_t)-1; /* clear child pid for Bailout() */
874 if (!WIFEXITED(waitStatus)) {
875 printf("WIFEXITED() returned FALSE, expected TRUE\n");
879 if (WEXITSTATUS(waitStatus) != waitIdx) {
880 if (WEXITSTATUS(waitStatus) == CHILD_ARG_BAD) {
881 printf("WEXITSTATUS() indicates child got bad args\n");
882 } else if (WEXITSTATUS(waitStatus) == CHILD_EXEC_FAILED) {
883 printf("WEXITSTATUS() indicates child exec() failed\n");
885 printf("WEXITSTATUS() returned %d, expected %d\n",
886 (int)WEXITSTATUS(waitStatus), waitIdx);
892 TimedSleep(3); /* wait for outstanding SIGCHLD's to get delivered */
894 if (!chldSignalCaught) {
895 printf("SIGCHLD never caught (last signo = %d)\n", lastSignalCaught);
900 /* -------------------------------------------------------------- */
902 printf("Testing child waiting with WNOHANG (spawnprocve(), waitpid(), kill())\n");
904 /* clear child pid vector for Bailout() */
907 /* Set SIGCHLD handler to SIG_DFL. NOTE: on some Unix systems, setting
908 * SIGCHLD handler to SIG_IGN changes the semantics of wait()/waitpid().
910 newAction.sa_handler = SIG_DFL;
911 sigfillset(&newAction.sa_mask);
912 newAction.sa_flags = 0;
914 if (sigaction(SIGCHLD, &newAction, NULL)) {
915 printf("sigaction() failed to install valid signal handler\n");
919 childArgv[0] = exeName;
920 childArgv[1] = CHILD_ARG1;
921 childArgv[2] = WNOHANGTEST_ARG2;
924 childPid[1] = spawnprocve(exeName, childArgv, environ, CHILD_EXEC_FAILED);
926 if (childPid[1] == (pid_t)-1) {
927 printf("spawnprocve(%s,...) failed to start child (errno = %d)\n",
932 for (i = 0; i < 20; i++) {
934 waitPid = waitpid(childPid[1], &waitStatus, WNOHANG);
935 } while (waitPid == (pid_t)-1 && errno == EINTR);
937 if (waitPid != (pid_t)0) {
938 if (waitPid == (pid_t)-1) {
939 printf("waitpid() failed getting child status (errno = %d)\n",
943 printf("waitpid() returned unexpected value (%d)\n", waitPid);
949 TimedSleep(2); /* wait for child to init signal mechanism (NT only) */
951 if (kill(childPid[1], SIGKILL)) {
952 printf("kill() failed to send SIGKILL (errno = %d)\n", errno);
957 waitPid = waitpid(childPid[1], &waitStatus, 0);
958 } while (waitPid == (pid_t)-1 && errno == EINTR);
960 if (waitPid != childPid[1]) {
961 if (waitPid == (pid_t)-1) {
962 printf("waitpid() failed getting child status (errno = %d)\n",
965 printf("waitpid() returned wrong pid (expected = %d, got = %d)\n",
966 (int)childPid[1], (int)waitPid);
971 childPid[1] = (pid_t)-1; /* clear child pid for Bailout() */
974 /* -------------------------------------------------------------- */
976 printf("Testing child signaling (spawnprocve(), kill(), waitpid(), sigaction(), WIFSIGNALED(), WTERMSIG())\n");
978 /* clear child pid vector for Bailout() */
981 TimedSleep(3); /* wait for outstanding SIGCHLD's to get delivered */
983 lastSignalCaught = NSIG;
984 chldSignalCaught = 0;
986 newAction.sa_handler = SignalCatcher;
987 sigfillset(&newAction.sa_mask);
988 newAction.sa_flags = 0;
990 if (sigaction(SIGCHLD, &newAction, NULL)) {
991 printf("sigaction() failed to install valid signal handler\n");
995 childArgv[0] = exeName;
996 childArgv[1] = CHILD_ARG1;
997 childArgv[2] = SIGNALTEST_ARG2;
1000 for (i = 0; i < TEST_CHILD_MAX; i++) {
1002 spawnprocve(exeName, childArgv, environ, CHILD_EXEC_FAILED);
1004 if (childPid[i] == (pid_t)-1) {
1005 printf("spawnprocve(%s,...) failed to start child (errno = %d)\n",
1011 TimedSleep(4); /* wait for children to init signal mechanism (NT only) */
1013 for (i = 0; i < TEST_CHILD_MAX; i++) {
1016 } else if (i % 3 == 1) {
1022 if (kill(childPid[i], signo)) {
1023 printf("kill() failed to send signal (errno = %d)\n", errno);
1028 for (i = 0; i < TEST_CHILD_MAX; i++) {
1031 } else if (i % 3 == 1) {
1038 waitPid = waitpid(childPid[i], &waitStatus, 0);
1039 } while (waitPid == (pid_t)-1 && errno == EINTR);
1041 if (waitPid != childPid[i]) {
1042 if (waitPid == (pid_t)-1) {
1043 printf("waitpid() failed getting child status (errno = %d)\n",
1046 printf("waitpid() returned wrong pid "
1047 "(expected = %d, got = %d)\n",
1048 (int)childPid[i], (int)waitPid);
1053 childPid[i] = (pid_t)-1; /* clear child pid for Bailout() */
1055 if (!WIFSIGNALED(waitStatus)) {
1056 printf("WIFSIGNALED() returned FALSE, expected TRUE\n");
1060 if (WTERMSIG(waitStatus) != signo) {
1061 printf("WTERMSIG() returned %d, expected %d\n",
1062 (int)WTERMSIG(waitStatus), signo);
1067 TimedSleep(3); /* wait for outstanding SIGCHLD's to get delivered */
1069 if (!chldSignalCaught) {
1070 printf("SIGCHLD never caught (last signo = %d)\n", lastSignalCaught);
1074 if (signal(SIGCHLD, SIG_DFL) == SIG_ERR) {
1075 printf("sigaction() failed to install valid signal handler\n");
1080 /* -------------------------------------------------------------- */
1082 printf("Testing child aborting (spawnprocve(), waitpid(), WIFSIGNALED(), WTERMSIG())\n");
1084 /* clear child pid vector for Bailout() */
1087 TimedSleep(3); /* wait for outstanding SIGCHLD's to get delivered */
1089 lastSignalCaught = NSIG;
1090 chldSignalCaught = 0;
1092 newAction.sa_handler = SignalCatcher;
1093 sigfillset(&newAction.sa_mask);
1094 newAction.sa_flags = 0;
1096 if (sigaction(SIGCHLD, &newAction, NULL)) {
1097 printf("sigaction() failed to install valid signal handler\n");
1101 childArgv[0] = exeName;
1102 childArgv[1] = CHILD_ARG1;
1103 childArgv[2] = ABORTTEST_ARG2;
1104 childArgv[3] = NULL;
1107 spawnprocve(exeName, childArgv, environ, CHILD_EXEC_FAILED);
1109 if (childPid[1] == (pid_t)-1) {
1110 printf("spawnprocve(%s,...) failed to start child (errno = %d)\n",
1115 TimedSleep(2); /* wait for child to init signal mechanism (NT only) */
1118 waitPid = waitpid(childPid[1], &waitStatus, 0);
1119 } while (waitPid == (pid_t)-1 && errno == EINTR);
1121 if (waitPid != childPid[1]) {
1122 if (waitPid == (pid_t)-1) {
1123 printf("waitpid() failed getting child status (errno = %d)\n",
1126 printf("waitpid() returned wrong pid (expected = %d, got = %d)\n",
1127 (int)childPid[1], (int)waitPid);
1132 childPid[1] = (pid_t)-1; /* clear child pid for Bailout() */
1134 if (!WIFSIGNALED(waitStatus)) {
1135 printf("WIFSIGNALED() returned FALSE, expected TRUE\n");
1139 if (WTERMSIG(waitStatus) != SIGABRT) {
1140 printf("WTERMSIG() returned %d, expected SIGABRT (%d)\n",
1141 (int)WTERMSIG(waitStatus), (int)SIGABRT);
1145 TimedSleep(3); /* wait for outstanding SIGCHLD's to get delivered */
1147 if (!chldSignalCaught) {
1148 printf("SIGCHLD never caught (last signo = %d)\n", lastSignalCaught);
1152 if (signal(SIGCHLD, SIG_DFL) == SIG_ERR) {
1153 printf("sigaction() failed to install valid signal handler\n");
1161 * Parent process behavior.
1164 BehaveLikeAParent(int argc, char *argv[])
1167 SingleThreadMgmtTest(argv[0]);
1169 printf("\nAll tests completed successfully.\n");
1174 * Child process behavior.
1177 BehaveLikeAChild(int argc, char *argv[])
1183 /* Turn off debug message box used by abort()/assert() in debug
1184 * version of MSVC C run-time library.
1186 (void) _CrtSetReportMode(_CRT_WARN, 0);
1187 (void) _CrtSetReportMode(_CRT_ERROR, 0);
1188 (void) _CrtSetReportMode(_CRT_ASSERT, 0);
1191 /* verify that argc and argv are in sync */
1192 for (argvCount = 0; argv[argvCount]; argvCount++);
1194 if (argc != argvCount) {
1195 exit(CHILD_ARG_BAD);
1198 /* verify test argument format */
1201 /* all tests require at least argv[2] (test name) */
1202 exit(CHILD_ARG_BAD);
1205 /* perform as required for particular test */
1209 if (!strcmp(testName, SPAWNTEST_ARG2)) {
1210 /* SPAWN TEST child */
1214 if (((envstr = getenv(SPAWNTEST_ENV_NAME)) == NULL) ||
1215 (strcmp(envstr, SPAWNTEST_ENV_VALUE))) {
1216 exit(CHILD_ARG_BAD);
1219 if (atoi(argv[3]) != (argc - 4)) {
1220 exit(CHILD_ARG_BAD);
1223 for (i = 0; i < argc - 4; i++) {
1224 if (strcmp(argv[4 + i], SPAWNTEST_ARG[i])) {
1225 exit(CHILD_ARG_BAD);
1229 #if defined(AFS_NT40_ENV)
1230 if (spawnDatap != NULL || spawnDataLen != 0) {
1231 exit(CHILD_ARG_BAD);
1237 #if defined(AFS_NT40_ENV)
1238 } else if (!strcmp(testName, SPAWNBUFTEST_ARG2)) {
1239 /* SPAWNBUF TEST child */
1243 if (((envstr = getenv(SPAWNTEST_ENV_NAME)) == NULL) ||
1244 (strcmp(envstr, SPAWNTEST_ENV_VALUE))) {
1245 exit(CHILD_ARG_BAD);
1248 if (atoi(argv[3]) != (argc - 4)) {
1249 exit(CHILD_ARG_BAD);
1252 for (i = 0; i < argc - 4; i++) {
1253 if (strcmp(argv[4 + i], SPAWNTEST_ARG[i])) {
1254 exit(CHILD_ARG_BAD);
1258 if (spawnDataLen != sizeof(spawntestDataBuffer) ||
1259 strcmp(spawnDatap, spawntestDataBuffer)) {
1260 exit(CHILD_ARG_BAD);
1264 #endif /* AFS_NT40_ENV */
1267 } else if (!strcmp(testName, WAITTEST_ARG2)) {
1268 /* WAIT TEST child */
1272 exit(CHILD_ARG_BAD);
1275 rc = strtol(argv[3], NULL, 10);
1279 } else if (!strcmp(testName, WNOHANGTEST_ARG2)) {
1280 /* WNOHANG TEST child */
1281 TimedSleep(FOREVER);
1282 printf("\tchild unexpectedly returned from TimedSleep(FOREVER)\n");
1283 exit(1); /* should never execute */
1285 } else if (!strcmp(testName, SIGNALTEST_ARG2)) {
1286 /* SIGNAL TEST child */
1287 TimedSleep(FOREVER);
1288 printf("\tchild unexpectedly returned from TimedSleep(FOREVER)\n");
1289 exit(1); /* should never execute */
1291 } else if (!strcmp(testName, ABORTTEST_ARG2)) {
1292 /* ABORT TEST child */
1295 printf("\tNOTICE:\n");
1296 printf("\t\tChild is calling abort().\n");
1297 printf("\t\tAbnormal termination message will appear.\n");
1298 printf("\t\tA software exception dialog will appear; press 'OK'.\n");
1299 printf("\t\tAutomatic debugger invocation MUST be disabled.\n");
1303 printf("\tchild unexpectedly returned from abort()\n");
1304 exit(1); /* should never execute */
1308 exit(CHILD_ARG_BAD);
1316 int main(int argc, char *argv[])
1319 /* PARENT process */
1320 BehaveLikeAParent(argc, argv);
1321 } else if ((argc > 1) && !strcmp(argv[1], CHILD_ARG1)) {
1323 BehaveLikeAChild(argc, argv);
1325 printf("\nUsage: %s\n", argv[0]);