#include "tests.h"
#include <mach/mach.h>
-#include <dirent.h> /* crashcount() */
extern char g_target_path[ PATH_MAX ];
*/
static volatile int my_err;
-/*
- * Handler; used by memory_tests() child to reset my_err so that it will
- * exit normally following a SIGBUS, rather than triggering a crash report;
- * this depends on setting the error non-zero before triggering the condition
- * that would trigger a SIGBUS. To avoid confusion, this is most easily done
- * right before the test in question, and if there are subsequent tests, then
- * undone immediately after to avoid false test negatives.
- */
void
bus_handler(int sig, siginfo_t *si, void *mcontext)
{
/* Reset global error value when we see a SIGBUS */
- if (sig == SIGBUS)
- my_err = 0;
-}
-
-/*
- * Count the number of crashes for us in /Library/Logs/CrashReporter/
- *
- * XXX Assumes that CrashReporter uses our name as a prefix
- * XXX Assumes no one lese has the same prefix as our name
- */
-int
-crashcount(char *namebuf1, char *namebuf2)
-{
- char *crashdir1 = "/Library/Logs/CrashReporter";
- char *crashdir2 = "/Library/Logs/DiagnosticReports";
- char *crash_file_pfx = "xnu_quick_test";
- int crash_file_pfxlen = strlen(crash_file_pfx);
- struct stat sb;
- DIR *dirp1 = NULL, *dirp2 = NULL;
- struct dirent *dep1, *dep2;
- int count = 0;
-
- /* If we can't open the directory, dirp1 will be NULL */
- dirp1 = opendir(crashdir1);
-
- while(dirp1 != NULL && ((dep1 = readdir(dirp1)) != NULL)) {
- if (strncmp(crash_file_pfx, dep1->d_name, crash_file_pfxlen))
- continue;
- /* record each one to get the last one */
- if (namebuf1) {
- strcpy(namebuf1, crashdir1);
- strcat(namebuf1, "/");
- strcat(namebuf1, dep1->d_name);
- }
- count++;
+ if (sig == SIGBUS) {
+ _exit(0);
}
-
- if (dirp1 != NULL)
- closedir(dirp1);
-
-#if !TARGET_OS_EMBEDDED
- /* If we can't open the directory, dirp2 will be NULL */
- dirp2 = opendir(crashdir2);
-
- while(dirp2 != NULL && (dep2 = readdir(dirp2)) != NULL) {
- if (strncmp(crash_file_pfx, dep2->d_name, crash_file_pfxlen))
- continue;
- /* record each one to get the last one */
- if (namebuf2) {
- strcpy(namebuf2, crashdir2);
- strcat(namebuf2, "/");
- strcat(namebuf2, dep2->d_name);
- }
- count++;
- }
- if (dirp2 != NULL)
- closedir(dirp2);
-#endif
- return( count );
}
-
/* **************************************************************************************************************
* Test madvise, mincore, minherit, mlock, mlock, mmap, mprotect, msync, munmap system calls.
* todo - see if Francois has better versions of these tests...
pid_t my_pid, my_wait_pid;
kern_return_t my_kr;
struct sigaction my_sa;
- static int my_crashcount;
- static char my_namebuf1[256]; /* XXX big enough */
- static char my_namebuf2[256];
my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
if(my_kr != KERN_SUCCESS){
goto test_failed_exit;
}
- /*
- * Find out how many crashes there have already been; if it's not
- * zero, then don't even attempt this test.
- */
- my_namebuf1[0] = '\0';
- my_namebuf2[0] = '\0';
- if ((my_crashcount = crashcount(my_namebuf1, my_namebuf2)) != 0) {
- printf( "memtest aborted: can not distinguish our expected crash from \n");
- printf( "%d existing crashes including %s \n", my_crashcount, my_namebuf2);
- goto test_failed_exit;
- }
-
/*
* spin off a child process that we will use for testing.
*/
goto exit_child;
}
- /*
- * Establish SIGBUS handler; will reset (disable itself) if it fires;
- * we would need how to recover from the exceptional condition that
- * raised the SIGBUS by modifying the contents of the (opaque to us)
- * mcontext in order to prevent this from being terminal, so we let
- * it be terminal. This is enough to avoid triggering crash reporter.
- */
my_sa.sa_sigaction = bus_handler;
my_sa.sa_flags = SA_SIGINFO | SA_RESETHAND;
if ((my_err = sigaction(SIGBUS, &my_sa, NULL)) != 0) {
goto test_failed_exit;
}
- /* If we were not signalled, or we died from an unexpected signal, report it.
- */
- if ( !WIFSIGNALED( my_status ) || WTERMSIG( my_status ) != SIGBUS) {
- printf( "wait4 returned child died of status - 0x%02X \n", my_status );
- goto test_failed_exit;
- }
-
- /*
- * Wait long enough that CrashReporter has finished.
- */
- sleep(5);
-
- /*
- * Find out how many crashes there have already been; if it's not
- * one, then don't even attempt this test.
+ /* If we did not exit cleanly, report it
*/
- my_namebuf1[0] = '\0';
- my_namebuf2[0] = '\0';
- my_crashcount = crashcount(my_namebuf1, my_namebuf2);
- if (!(my_crashcount == 1 || my_crashcount == 2)) {
- printf( "child did not crash as expected \n");
- printf( "saw %d crashes including %s \n", my_crashcount, my_namebuf1);
+ if ( !WIFEXITED( my_status ) || (WEXITSTATUS( my_status ) != 0)) {
+ printf( "wait4 returned child died of status - 0x%08X \n", my_status );
goto test_failed_exit;
}
- /* post-remove the expected crash report */
- if (unlink(my_namebuf1) && !(errno == ENOENT || errno == ENOTDIR)) {
- printf("unlink of expected crash report '%s' failed \n", my_namebuf1);
- goto test_failed_exit;
- }
-#if !TARGET_OS_EMBEDDED
- /* /Library/Logs/DiagnosticReports/ does not exist on embedded targets. */
- if (unlink(my_namebuf2) && !(errno == ENOENT || errno == ENOTDIR)) {
- printf("unlink of expected crash report '%s' failed \n", my_namebuf2);
- goto test_failed_exit;
- }
-#endif
/* make sure shared page got modified in child */
if ( strcmp( my_test_page_p, "parent data child data" ) != 0 ) {
printf( "minherit did not work correctly - shared page looks wrong \n" );