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>
31 extern char **environ;
34 #include <afs/procmgmt.h>
37 /* define constants */
39 #define TEST_CHILD_MAX 20 /* max number of active child procs in test */
41 #if defined(AFS_NT40_ENV)
42 /* Test for reset of signal() handler (i.e., unreliable signal() behavior).
43 * Note: some Unix systems implement a reliable form of signal(), some
44 * do not; NT does not. Only test the NT behavior because we trust
45 * the Unix implementation.
47 #define TEST_SIGNAL_RESET
53 static volatile int lastSignalCaught; /* last signo caught by sig handler */
54 static volatile int chldSignalCaught; /* SIGCHLD caught by sig handler */
56 static pid_t childPid[TEST_CHILD_MAX]; /* pids of active child procs */
58 static char spawntestDataBuffer[] = "Four score and seven years ago...";
61 /* define arguments for child processes
65 * argv[1] - CHILD_ARG1
67 * argv[3...n] - arguments for specified test (argv[2])
69 #define CHILD_ARG_BAD 255 /* child got bad args for test (exit status) */
70 #define CHILD_EXEC_FAILED 254 /* child failed exec() (Unix only) */
72 #define CHILD_ARG1 "cHiLd" /* indicates that proc is a child */
74 #define SPAWNTEST_ARG2 "spawntest" /* spawn test child */
75 #define SPAWNTEST_ARG_MAX 4 /* must match SPAWNTEST_ARG[] count */
76 static char *SPAWNTEST_ARG[] = { "fred and wilma",
78 "", /* test empty string arg */
79 "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) || sigismember(&sigSet, SIGINT)
239 || sigismember(&sigSet, SIGQUIT) || sigismember(&sigSet, SIGILL)
240 || sigismember(&sigSet, SIGABRT) || sigismember(&sigSet, SIGFPE)
241 || sigismember(&sigSet, SIGKILL) || sigismember(&sigSet, SIGSEGV)
242 || sigismember(&sigSet, SIGTERM) || sigismember(&sigSet, SIGUSR1)
243 || sigismember(&sigSet, SIGUSR2) || sigismember(&sigSet, SIGCHLD)
244 || sigismember(&sigSet, SIGTSTP)) {
245 printf("sigemptyset() did not clear all defined signals\n");
251 if (!sigismember(&sigSet, SIGHUP) || !sigismember(&sigSet, SIGINT)
252 || !sigismember(&sigSet, SIGQUIT) || !sigismember(&sigSet, SIGILL)
253 || !sigismember(&sigSet, SIGABRT) || !sigismember(&sigSet, SIGFPE)
254 || !sigismember(&sigSet, SIGKILL) || !sigismember(&sigSet, SIGSEGV)
255 || !sigismember(&sigSet, SIGTERM) || !sigismember(&sigSet, SIGUSR1)
256 || !sigismember(&sigSet, SIGUSR2) || !sigismember(&sigSet, SIGCHLD)
257 || !sigismember(&sigSet, SIGTSTP)) {
258 printf("sigfillset() did not set all defined signals\n");
262 sigaddset(&sigSet, SIGUSR1);
263 sigaddset(&sigSet, SIGUSR2);
264 sigaddset(&sigSet, SIGINT);
266 if (!sigismember(&sigSet, SIGINT) || !sigismember(&sigSet, SIGUSR1)
267 || !sigismember(&sigSet, SIGUSR2)) {
268 printf("sigaddset() did not add defined signal to set\n");
272 sigdelset(&sigSet, SIGUSR1);
273 sigdelset(&sigSet, SIGUSR2);
274 sigdelset(&sigSet, SIGINT);
276 if (sigismember(&sigSet, SIGINT) || sigismember(&sigSet, SIGUSR1)
277 || sigismember(&sigSet, SIGUSR2)) {
278 printf("sigdelset() did not delete defined signal from set\n");
283 /* -------------------------------------------------------------- */
285 printf("Testing signal handler installation (sigaction(), signal())\n");
287 newAction.sa_handler = SignalCatcher;
288 sigemptyset(&newAction.sa_mask);
289 newAction.sa_flags = 0;
292 if (!sigaction(SIGKILL, &newAction, NULL)) {
293 printf("sigaction() allowed a handler to be set for SIGKILL\n");
295 } else if (errno != EINVAL) {
296 printf("sigaction(SIGKILL,...) did not set errno to EINVAL\n");
301 if (!sigaction(NSIG, &newAction, NULL)) {
302 printf("sigaction() allowed a handler for an invalid signo\n");
304 } else if (errno != EINVAL) {
305 printf("sigaction(NSIG,...) did not set errno to EINVAL\n");
310 if (signal(SIGKILL, SignalCatcher) != SIG_ERR) {
311 printf("signal() allowed a handler to be set for SIGKILL\n");
313 } else if (errno != EINVAL) {
314 printf("signal(SIGKILL,...) did not set errno to EINVAL\n");
319 if (signal(NSIG, SignalCatcher) != SIG_ERR) {
320 printf("signal() allowed a handler to be set for an invalid signo\n");
322 } else if (errno != EINVAL) {
323 printf("signal(NSIG,...) did not set errno to EINVAL\n");
327 if (sigaction(SIGTERM, &newAction, NULL)) {
328 printf("sigaction() failed to install valid signal handler\n");
332 if (sigaction(SIGTERM, NULL, &oldAction)) {
333 printf("sigaction() failed to retrieve old signal handler\n");
335 } else if (oldAction.sa_handler != newAction.sa_handler
336 || oldAction.sa_flags != newAction.sa_flags) {
337 printf("sigaction() returned incorrect old signal handler values\n");
341 if ((sigDisp = signal(SIGTERM, SIG_DFL)) == SIG_ERR) {
342 printf("signal() failed to install valid signal handler\n");
344 } else if (sigDisp != newAction.sa_handler) {
345 printf("signal() returned incorrect old signal handler\n");
349 if ((sigDisp = signal(SIGTERM, SIG_DFL)) == SIG_ERR) {
350 printf("signal() failed to install valid signal handler (2)\n");
352 } else if (sigDisp != SIG_DFL) {
353 printf("signal() returned incorrect old signal handler (2)\n");
357 if (sigaction(SIGTERM, NULL, &oldAction)) {
358 printf("sigaction() failed to retrieve old signal handler (2)\n");
360 } else if (oldAction.sa_handler != SIG_DFL) {
361 printf("sigaction() returned incorrect old signal handler (2)\n");
366 /* -------------------------------------------------------------- */
369 ("Testing signal catching (sigaction(), signal(), kill(), raise())\n");
371 newAction.sa_handler = SIG_DFL;
372 sigemptyset(&newAction.sa_mask);
373 newAction.sa_flags = 0;
375 if (sigaction(SIGCHLD, &newAction, NULL)) {
376 printf("sigaction() failed to install valid signal handler\n");
380 if (raise(SIGCHLD)) {
381 printf("raise() failed to send SIGCHLD (errno = %d)\n", errno);
385 TimedSleep(1); /* wait for signal delivery */
387 /* if made it here means SIGCHLD was (correctly) ignored */
389 newAction.sa_handler = SignalCatcher;
390 sigemptyset(&newAction.sa_mask);
391 newAction.sa_flags = 0;
393 if (sigaction(SIGTERM, &newAction, NULL)
394 || sigaction(SIGUSR1, &newAction, NULL)
395 || sigaction(SIGUSR2, &newAction, NULL)) {
396 printf("sigaction() failed to install valid signal handler (2)\n");
400 lastSignalCaught = NSIG;
402 if (raise(SIGTERM)) {
403 printf("raise() failed to send SIGTERM (errno = %d)\n", errno);
407 TimedSleep(1); /* wait for signal delivery */
409 if (lastSignalCaught != SIGTERM) {
410 printf("raise() failed to deliver SIGTERM\n");
414 if (raise(SIGUSR1)) {
415 printf("raise() failed to send SIGUSR1 (errno = %d)\n", errno);
419 TimedSleep(1); /* wait for signal delivery */
421 if (lastSignalCaught != SIGUSR1) {
422 printf("raise() failed to deliver SIGUSR1\n");
426 if (raise(SIGUSR2)) {
427 printf("raise() failed to send SIGUSR2 (errno = %d)\n", errno);
431 TimedSleep(1); /* wait for signal delivery */
433 if (lastSignalCaught != SIGUSR2) {
434 printf("raise() failed to deliver SIGUSR2\n");
438 if (sigaction(SIGTERM, NULL, &oldAction)) {
439 printf("sigaction() failed to retrieve old SIGTERM handler\n");
441 } else if (oldAction.sa_handler != newAction.sa_handler
442 || oldAction.sa_flags != newAction.sa_flags) {
443 printf("sigaction() returned incorrect old SIGTERM handler values\n");
447 if (sigaction(SIGUSR1, NULL, &oldAction)) {
448 printf("sigaction() failed to retrieve old SIGUSR1 handler\n");
450 } else if (oldAction.sa_handler != newAction.sa_handler
451 || oldAction.sa_flags != newAction.sa_flags) {
452 printf("sigaction() returned incorrect old SIGUSR1 handler values\n");
456 if (sigaction(SIGUSR2, NULL, &oldAction)) {
457 printf("sigaction() failed to retrieve old SIGUSR2 handler\n");
459 } else if (oldAction.sa_handler != newAction.sa_handler
460 || oldAction.sa_flags != newAction.sa_flags) {
461 printf("sigaction() returned incorrect old SIGUSR2 handler values\n");
465 if (signal(SIGTERM, SignalCatcher) == SIG_ERR
466 || signal(SIGUSR1, SignalCatcher) == SIG_ERR
467 || signal(SIGUSR2, SignalCatcher) == SIG_ERR) {
468 printf("signal() failed to install valid signal handler (3)\n");
472 lastSignalCaught = NSIG;
474 if (kill(getpid(), SIGTERM)) {
475 printf("kill() failed to send SIGTERM (errno = %d)\n", errno);
479 TimedSleep(1); /* wait for signal delivery */
481 if (lastSignalCaught != SIGTERM) {
482 printf("kill() failed to deliver SIGTERM\n");
486 if (kill(getpid(), SIGUSR1)) {
487 printf("kill() failed to send SIGUSR1 (errno = %d)\n", errno);
491 TimedSleep(1); /* wait for signal delivery */
493 if (lastSignalCaught != SIGUSR1) {
494 printf("kill() failed to deliver SIGUSR1\n");
498 if (kill(getpid(), SIGUSR2)) {
499 printf("kill() failed to send SIGUSR2 (errno = %d)\n", errno);
503 TimedSleep(1); /* wait for signal delivery */
505 if (lastSignalCaught != SIGUSR2) {
506 printf("kill() failed to deliver SIGUSR2\n");
510 if ((sigDisp = signal(SIGTERM, SIG_DFL)) == SIG_ERR) {
511 printf("signal() failed to retrieve old SIGTERM handler\n");
513 } else if (sigDisp != SIG_DFL) {
514 #ifdef TEST_SIGNAL_RESET
515 printf("signal() returned incorrect old SIGTERM handler\n");
520 if ((sigDisp = signal(SIGUSR1, SIG_DFL)) == SIG_ERR) {
521 printf("signal() failed to retrieve old SIGUSR1 handler\n");
523 } else if (sigDisp != SIG_DFL) {
524 #ifdef TEST_SIGNAL_RESET
525 printf("signal() returned incorrect old SIGUSR1 handler\n");
530 if ((sigDisp = signal(SIGUSR2, SIG_DFL)) == SIG_ERR) {
531 printf("signal() failed to retrieve old SIGUSR2 handler\n");
533 } else if (sigDisp != SIG_DFL) {
534 #ifdef TEST_SIGNAL_RESET
535 printf("signal() returned incorrect old SIGUSR2 handler\n");
541 * NOTE: not testing effects of sa_mask in sigaction(); the NT process
542 * management library currently serializes signals (to get Unix
543 * signal handling semantics on a uniprocessor) so sa_mask is
544 * effectively ignored (since all signals, except SIGKILL, are
545 * blocked while a signal handler is running).
547 printf("\tNOTICE: effectiveness of sigaction()'s sa_mask not tested;\n");
548 printf("\tsee comments in test source\n");
552 /* -------------------------------------------------------------- */
554 printf("Testing childless waiting (wait(), waitpid())\n");
557 if (waitpid((pid_t) 17, NULL, 0) != -1) {
558 printf("waitpid(17,...) with no child did not return -1\n");
560 } else if (errno != ECHILD) {
561 printf("waitpid(17,...) with no child did not set errno to ECHILD\n");
566 if (waitpid((pid_t) - 1, NULL, 0) != -1) {
567 printf("waitpid(-1,...) with no child did not return -1\n");
569 } else if (errno != ECHILD) {
570 printf("waitpid(-1,...) with no child did not set errno to ECHILD\n");
575 if (wait(NULL) != -1) {
576 printf("wait() with no child did not return -1\n");
578 } else if (errno != ECHILD) {
579 printf("wait() with no child did not set errno to ECHILD\n");
587 * Process management test -- single threaded.
590 SingleThreadMgmtTest(char *exeName)
592 struct sigaction newAction;
593 char *childArgv[SPAWNTEST_ARG_MAX + 10];
594 char childArgStr[50];
596 int waitStatus, waitIdx;
600 printf("\n\nPROCESS MANAGEMENT TEST: SINGLE THREADED\n\n");
602 /* -------------------------------------------------------------- */
605 ("Testing child spawning (spawnprocve(), wait(), WIFEXITED(), WEXITSTATUS())\n");
607 /* clear child pid vector for Bailout() */
610 /* Set SIGCHLD handler to SIG_DFL. NOTE: on some Unix systems, setting
611 * SIGCHLD handler to SIG_IGN changes the semantics of wait()/waitpid().
613 newAction.sa_handler = SIG_DFL;
614 sigfillset(&newAction.sa_mask);
615 newAction.sa_flags = 0;
617 if (sigaction(SIGCHLD, &newAction, NULL)) {
618 printf("sigaction() failed to install valid signal handler\n");
622 if (putenv(SPAWNTEST_ENV_SETSTR)) {
623 printf("putenv() failed\n");
627 childArgv[0] = exeName;
628 childArgv[1] = CHILD_ARG1;
629 childArgv[2] = SPAWNTEST_ARG2;
631 for (i = 0; i <= SPAWNTEST_ARG_MAX; i++) {
633 sprintf(countBuf, "%d", i);
635 childArgv[3] = countBuf;
637 for (j = 0; j < i; j++) {
638 childArgv[4 + j] = SPAWNTEST_ARG[j];
640 childArgv[4 + j] = NULL;
644 spawnprocve(exeName, childArgv, environ, CHILD_EXEC_FAILED);
646 childPid[1] = spawnprocv(exeName, childArgv, CHILD_EXEC_FAILED);
649 if (childPid[1] == (pid_t) - 1) {
650 printf("spawnprocve(%s,...) failed to start child (errno = %d)\n",
656 waitPid = wait(&waitStatus);
657 } while (waitPid == (pid_t) - 1 && errno == EINTR);
659 if (waitPid != childPid[1]) {
660 if (waitPid == (pid_t) - 1) {
661 printf("wait() failed getting child status (errno = %d)\n",
665 ("wait() returned wrong pid (expected = %d, got = %d)\n",
666 (int)childPid[1], (int)waitPid);
671 childPid[1] = (pid_t) - 1; /* clear child pid for Bailout() */
673 if (!WIFEXITED(waitStatus)) {
674 printf("WIFEXITED() returned FALSE, expected TRUE\n");
678 if (WEXITSTATUS(waitStatus) != i) {
679 if (WEXITSTATUS(waitStatus) == CHILD_ARG_BAD) {
680 printf("WEXITSTATUS() indicates child got bad args\n");
681 } else if (WEXITSTATUS(waitStatus) == CHILD_EXEC_FAILED) {
682 printf("WEXITSTATUS() indicates child exec() failed\n");
684 printf("WEXITSTATUS() returned %d, expected %d\n",
685 (int)WEXITSTATUS(waitStatus), i);
692 /* -------------------------------------------------------------- */
694 #if defined(AFS_NT40_ENV)
697 ("Testing child spawning with data buffer (spawnprocveb(), wait(), WIFEXITED(), WEXITSTATUS())\n");
699 /* clear child pid vector for Bailout() */
702 /* Set SIGCHLD handler to SIG_DFL. NOTE: on some Unix systems, setting
703 * SIGCHLD handler to SIG_IGN changes the semantics of wait()/waitpid().
705 newAction.sa_handler = SIG_DFL;
706 sigfillset(&newAction.sa_mask);
707 newAction.sa_flags = 0;
709 if (sigaction(SIGCHLD, &newAction, NULL)) {
710 printf("sigaction() failed to install valid signal handler\n");
714 if (putenv(SPAWNTEST_ENV_SETSTR)) {
715 printf("putenv() failed\n");
719 childArgv[0] = exeName;
720 childArgv[1] = CHILD_ARG1;
721 childArgv[2] = SPAWNBUFTEST_ARG2;
723 for (i = 0; i <= SPAWNTEST_ARG_MAX; i++) {
725 sprintf(countBuf, "%d", i);
727 childArgv[3] = countBuf;
729 for (j = 0; j < i; j++) {
730 childArgv[4 + j] = SPAWNTEST_ARG[j];
732 childArgv[4 + j] = NULL;
735 spawnprocveb(exeName, childArgv, environ, spawntestDataBuffer,
736 sizeof(spawntestDataBuffer));
738 if (childPid[1] == (pid_t) - 1) {
740 ("spawnprocveb(%s,...) failed to start child (errno = %d)\n",
746 waitPid = wait(&waitStatus);
747 } while (waitPid == (pid_t) - 1 && errno == EINTR);
749 if (waitPid != childPid[1]) {
750 if (waitPid == (pid_t) - 1) {
751 printf("wait() failed getting child status (errno = %d)\n",
755 ("wait() returned wrong pid (expected = %d, got = %d)\n",
756 (int)childPid[1], (int)waitPid);
761 childPid[1] = (pid_t) - 1; /* clear child pid for Bailout() */
763 if (!WIFEXITED(waitStatus)) {
764 printf("WIFEXITED() returned FALSE, expected TRUE\n");
768 if (WEXITSTATUS(waitStatus) != i) {
769 if (WEXITSTATUS(waitStatus) == CHILD_ARG_BAD) {
770 printf("WEXITSTATUS() indicates child got bad args\n");
772 printf("WEXITSTATUS() returned %d, expected %d\n",
773 (int)WEXITSTATUS(waitStatus), i);
779 #endif /* AFS_NT40_ENV */
782 /* -------------------------------------------------------------- */
785 ("Testing child waiting (spawnprocve(), wait(), waitpid(), sigaction(), WIFEXITED(), WEXITSTATUS())\n");
787 /* clear child pid vector for Bailout() */
790 TimedSleep(3); /* wait for outstanding SIGCHLD's to get delivered */
792 lastSignalCaught = NSIG;
793 chldSignalCaught = 0;
795 newAction.sa_handler = SignalCatcher;
796 sigfillset(&newAction.sa_mask);
797 newAction.sa_flags = 0;
799 if (sigaction(SIGCHLD, &newAction, NULL)) {
800 printf("sigaction() failed to install valid signal handler\n");
804 childArgv[0] = exeName;
805 childArgv[1] = CHILD_ARG1;
806 childArgv[2] = WAITTEST_ARG2;
807 childArgv[3] = childArgStr;
810 for (i = 0; i < TEST_CHILD_MAX; i++) {
811 sprintf(childArgStr, "%d", i);
814 spawnprocve(exeName, childArgv, environ, CHILD_EXEC_FAILED);
816 if (childPid[i] == (pid_t) - 1) {
817 printf("spawnprocve(%s,...) failed to start child (errno = %d)\n",
823 for (i = 0; i < TEST_CHILD_MAX; i++) {
827 waitPid = wait(&waitStatus);
828 } while (waitPid == (pid_t) - 1 && errno == EINTR);
830 if (waitPid == (pid_t) - 1) {
831 printf("wait() failed getting child status (errno = %d)\n",
836 waitIdx = ChildTableLookup(waitPid);
839 printf("wait() returned unknown pid (%d)\n", (int)waitPid);
844 waitIdx = ChildTableLookup((pid_t) - 1);
847 printf("Child table unexpectedly empty\n");
852 waitPid = waitpid(childPid[waitIdx], &waitStatus, 0);
853 } while (waitPid == (pid_t) - 1 && errno == EINTR);
855 if (waitPid != childPid[waitIdx]) {
856 if (waitPid == (pid_t) - 1) {
857 printf("waitpid() failed getting status (errno = %d)\n",
860 printf("waitpid() returned wrong pid "
861 "(expected = %d, got = %d)\n",
862 (int)childPid[waitIdx], (int)waitPid);
868 childPid[waitIdx] = (pid_t) - 1; /* clear child pid for Bailout() */
870 if (!WIFEXITED(waitStatus)) {
871 printf("WIFEXITED() returned FALSE, expected TRUE\n");
875 if (WEXITSTATUS(waitStatus) != waitIdx) {
876 if (WEXITSTATUS(waitStatus) == CHILD_ARG_BAD) {
877 printf("WEXITSTATUS() indicates child got bad args\n");
878 } else if (WEXITSTATUS(waitStatus) == CHILD_EXEC_FAILED) {
879 printf("WEXITSTATUS() indicates child exec() failed\n");
881 printf("WEXITSTATUS() returned %d, expected %d\n",
882 (int)WEXITSTATUS(waitStatus), waitIdx);
888 TimedSleep(3); /* wait for outstanding SIGCHLD's to get delivered */
890 if (!chldSignalCaught) {
891 printf("SIGCHLD never caught (last signo = %d)\n", lastSignalCaught);
896 /* -------------------------------------------------------------- */
899 ("Testing child waiting with WNOHANG (spawnprocve(), waitpid(), kill())\n");
901 /* clear child pid vector for Bailout() */
904 /* Set SIGCHLD handler to SIG_DFL. NOTE: on some Unix systems, setting
905 * SIGCHLD handler to SIG_IGN changes the semantics of wait()/waitpid().
907 newAction.sa_handler = SIG_DFL;
908 sigfillset(&newAction.sa_mask);
909 newAction.sa_flags = 0;
911 if (sigaction(SIGCHLD, &newAction, NULL)) {
912 printf("sigaction() failed to install valid signal handler\n");
916 childArgv[0] = exeName;
917 childArgv[1] = CHILD_ARG1;
918 childArgv[2] = WNOHANGTEST_ARG2;
921 childPid[1] = spawnprocve(exeName, childArgv, environ, CHILD_EXEC_FAILED);
923 if (childPid[1] == (pid_t) - 1) {
924 printf("spawnprocve(%s,...) failed to start child (errno = %d)\n",
929 for (i = 0; i < 20; i++) {
931 waitPid = waitpid(childPid[1], &waitStatus, WNOHANG);
932 } while (waitPid == (pid_t) - 1 && errno == EINTR);
934 if (waitPid != (pid_t) 0) {
935 if (waitPid == (pid_t) - 1) {
936 printf("waitpid() failed getting child status (errno = %d)\n",
940 printf("waitpid() returned unexpected value (%d)\n", waitPid);
946 TimedSleep(2); /* wait for child to init signal mechanism (NT only) */
948 if (kill(childPid[1], SIGKILL)) {
949 printf("kill() failed to send SIGKILL (errno = %d)\n", errno);
954 waitPid = waitpid(childPid[1], &waitStatus, 0);
955 } while (waitPid == (pid_t) - 1 && errno == EINTR);
957 if (waitPid != childPid[1]) {
958 if (waitPid == (pid_t) - 1) {
959 printf("waitpid() failed getting child status (errno = %d)\n",
962 printf("waitpid() returned wrong pid (expected = %d, got = %d)\n",
963 (int)childPid[1], (int)waitPid);
968 childPid[1] = (pid_t) - 1; /* clear child pid for Bailout() */
971 /* -------------------------------------------------------------- */
974 ("Testing child signaling (spawnprocve(), kill(), waitpid(), sigaction(), WIFSIGNALED(), WTERMSIG())\n");
976 /* clear child pid vector for Bailout() */
979 TimedSleep(3); /* wait for outstanding SIGCHLD's to get delivered */
981 lastSignalCaught = NSIG;
982 chldSignalCaught = 0;
984 newAction.sa_handler = SignalCatcher;
985 sigfillset(&newAction.sa_mask);
986 newAction.sa_flags = 0;
988 if (sigaction(SIGCHLD, &newAction, NULL)) {
989 printf("sigaction() failed to install valid signal handler\n");
993 childArgv[0] = exeName;
994 childArgv[1] = CHILD_ARG1;
995 childArgv[2] = SIGNALTEST_ARG2;
998 for (i = 0; i < TEST_CHILD_MAX; i++) {
1000 spawnprocve(exeName, childArgv, environ, CHILD_EXEC_FAILED);
1002 if (childPid[i] == (pid_t) - 1) {
1003 printf("spawnprocve(%s,...) failed to start child (errno = %d)\n",
1009 TimedSleep(4); /* wait for children to init signal mechanism (NT only) */
1011 for (i = 0; i < TEST_CHILD_MAX; i++) {
1014 } else if (i % 3 == 1) {
1020 if (kill(childPid[i], signo)) {
1021 printf("kill() failed to send signal (errno = %d)\n", errno);
1026 for (i = 0; i < TEST_CHILD_MAX; i++) {
1029 } else if (i % 3 == 1) {
1036 waitPid = waitpid(childPid[i], &waitStatus, 0);
1037 } while (waitPid == (pid_t) - 1 && errno == EINTR);
1039 if (waitPid != childPid[i]) {
1040 if (waitPid == (pid_t) - 1) {
1041 printf("waitpid() failed getting child status (errno = %d)\n",
1044 printf("waitpid() returned wrong pid "
1045 "(expected = %d, got = %d)\n", (int)childPid[i],
1051 childPid[i] = (pid_t) - 1; /* clear child pid for Bailout() */
1053 if (!WIFSIGNALED(waitStatus)) {
1054 printf("WIFSIGNALED() returned FALSE, expected TRUE\n");
1058 if (WTERMSIG(waitStatus) != signo) {
1059 printf("WTERMSIG() returned %d, expected %d\n",
1060 (int)WTERMSIG(waitStatus), signo);
1065 TimedSleep(3); /* wait for outstanding SIGCHLD's to get delivered */
1067 if (!chldSignalCaught) {
1068 printf("SIGCHLD never caught (last signo = %d)\n", lastSignalCaught);
1072 if (signal(SIGCHLD, SIG_DFL) == SIG_ERR) {
1073 printf("sigaction() failed to install valid signal handler\n");
1078 /* -------------------------------------------------------------- */
1081 ("Testing child aborting (spawnprocve(), waitpid(), WIFSIGNALED(), WTERMSIG())\n");
1083 /* clear child pid vector for Bailout() */
1086 TimedSleep(3); /* wait for outstanding SIGCHLD's to get delivered */
1088 lastSignalCaught = NSIG;
1089 chldSignalCaught = 0;
1091 newAction.sa_handler = SignalCatcher;
1092 sigfillset(&newAction.sa_mask);
1093 newAction.sa_flags = 0;
1095 if (sigaction(SIGCHLD, &newAction, NULL)) {
1096 printf("sigaction() failed to install valid signal handler\n");
1100 childArgv[0] = exeName;
1101 childArgv[1] = CHILD_ARG1;
1102 childArgv[2] = ABORTTEST_ARG2;
1103 childArgv[3] = NULL;
1105 childPid[1] = spawnprocve(exeName, childArgv, environ, CHILD_EXEC_FAILED);
1107 if (childPid[1] == (pid_t) - 1) {
1108 printf("spawnprocve(%s,...) failed to start child (errno = %d)\n",
1113 TimedSleep(2); /* wait for child to init signal mechanism (NT only) */
1116 waitPid = waitpid(childPid[1], &waitStatus, 0);
1117 } while (waitPid == (pid_t) - 1 && errno == EINTR);
1119 if (waitPid != childPid[1]) {
1120 if (waitPid == (pid_t) - 1) {
1121 printf("waitpid() failed getting child status (errno = %d)\n",
1124 printf("waitpid() returned wrong pid (expected = %d, got = %d)\n",
1125 (int)childPid[1], (int)waitPid);
1130 childPid[1] = (pid_t) - 1; /* clear child pid for Bailout() */
1132 if (!WIFSIGNALED(waitStatus)) {
1133 printf("WIFSIGNALED() returned FALSE, expected TRUE\n");
1137 if (WTERMSIG(waitStatus) != SIGABRT) {
1138 printf("WTERMSIG() returned %d, expected SIGABRT (%d)\n",
1139 (int)WTERMSIG(waitStatus), (int)SIGABRT);
1143 TimedSleep(3); /* wait for outstanding SIGCHLD's to get delivered */
1145 if (!chldSignalCaught) {
1146 printf("SIGCHLD never caught (last signo = %d)\n", lastSignalCaught);
1150 if (signal(SIGCHLD, SIG_DFL) == SIG_ERR) {
1151 printf("sigaction() failed to install valid signal handler\n");
1159 * Parent process behavior.
1162 BehaveLikeAParent(int argc, char *argv[])
1165 SingleThreadMgmtTest(argv[0]);
1167 printf("\nAll tests completed successfully.\n");
1172 * Child process behavior.
1175 BehaveLikeAChild(int argc, char *argv[])
1181 /* Turn off debug message box used by abort()/assert() in debug
1182 * version of MSVC C run-time library.
1184 (void)_CrtSetReportMode(_CRT_WARN, 0);
1185 (void)_CrtSetReportMode(_CRT_ERROR, 0);
1186 (void)_CrtSetReportMode(_CRT_ASSERT, 0);
1189 /* verify that argc and argv are in sync */
1190 for (argvCount = 0; argv[argvCount]; argvCount++);
1192 if (argc != argvCount) {
1193 exit(CHILD_ARG_BAD);
1196 /* verify test argument format */
1199 /* all tests require at least argv[2] (test name) */
1200 exit(CHILD_ARG_BAD);
1203 /* perform as required for particular test */
1207 if (!strcmp(testName, SPAWNTEST_ARG2)) {
1208 /* SPAWN TEST child */
1212 if (((envstr = getenv(SPAWNTEST_ENV_NAME)) == NULL)
1213 || (strcmp(envstr, SPAWNTEST_ENV_VALUE))) {
1214 exit(CHILD_ARG_BAD);
1217 if (atoi(argv[3]) != (argc - 4)) {
1218 exit(CHILD_ARG_BAD);
1221 for (i = 0; i < argc - 4; i++) {
1222 if (strcmp(argv[4 + i], SPAWNTEST_ARG[i])) {
1223 exit(CHILD_ARG_BAD);
1227 #if defined(AFS_NT40_ENV)
1228 if (spawnDatap != NULL || spawnDataLen != 0) {
1229 exit(CHILD_ARG_BAD);
1235 #if defined(AFS_NT40_ENV)
1236 } else if (!strcmp(testName, SPAWNBUFTEST_ARG2)) {
1237 /* SPAWNBUF TEST child */
1241 if (((envstr = getenv(SPAWNTEST_ENV_NAME)) == NULL)
1242 || (strcmp(envstr, SPAWNTEST_ENV_VALUE))) {
1243 exit(CHILD_ARG_BAD);
1246 if (atoi(argv[3]) != (argc - 4)) {
1247 exit(CHILD_ARG_BAD);
1250 for (i = 0; i < argc - 4; i++) {
1251 if (strcmp(argv[4 + i], SPAWNTEST_ARG[i])) {
1252 exit(CHILD_ARG_BAD);
1256 if (spawnDataLen != sizeof(spawntestDataBuffer)
1257 || strcmp(spawnDatap, spawntestDataBuffer)) {
1258 exit(CHILD_ARG_BAD);
1262 #endif /* AFS_NT40_ENV */
1265 } else if (!strcmp(testName, WAITTEST_ARG2)) {
1266 /* WAIT TEST child */
1270 exit(CHILD_ARG_BAD);
1273 rc = strtol(argv[3], NULL, 10);
1277 } else if (!strcmp(testName, WNOHANGTEST_ARG2)) {
1278 /* WNOHANG TEST child */
1279 TimedSleep(FOREVER);
1280 printf("\tchild unexpectedly returned from TimedSleep(FOREVER)\n");
1281 exit(1); /* should never execute */
1283 } else if (!strcmp(testName, SIGNALTEST_ARG2)) {
1284 /* SIGNAL 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, ABORTTEST_ARG2)) {
1290 /* ABORT TEST child */
1293 printf("\tNOTICE:\n");
1294 printf("\t\tChild is calling abort().\n");
1295 printf("\t\tAbnormal termination message will appear.\n");
1296 printf("\t\tA software exception dialog will appear; press 'OK'.\n");
1297 printf("\t\tAutomatic debugger invocation MUST be disabled.\n");
1301 printf("\tchild unexpectedly returned from abort()\n");
1302 exit(1); /* should never execute */
1306 exit(CHILD_ARG_BAD);
1315 main(int argc, char *argv[])
1318 /* PARENT process */
1319 BehaveLikeAParent(argc, argv);
1320 } else if ((argc > 1) && !strcmp(argv[1], CHILD_ARG1)) {
1322 BehaveLikeAChild(argc, argv);
1324 printf("\nUsage: %s\n", argv[0]);