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]);