예제 #1
0
/**
 * Call omrdump_create() without passing in core file name. This does not actually test that a core file was actually created.
 */
TEST(PortDumpTest, dump_test_create_dump_with_NO_name)
{
	OMRPORT_ACCESS_FROM_OMRPORT(portTestEnv->getPortLibrary());
	const char *testName = "omrdump_test_create_dump_with_NO_name";
	uintptr_t rc = 99;
	char coreFileName[EsMaxPath];
	BOOLEAN doFileVerification = FALSE;
#if defined(AIXPPC)
	struct vario myvar;
	int sys_parmRC;
#endif

	reportTestEntry(OMRPORTLIB, testName);

	coreFileName[0] = '\0';

#if 0
	/* try out a NULL test (turns out this crashes) */
	rc = omrdump_create(NULL, NULL, NULL); /* this crashes */
#endif

	/* try out a more sane NULL test */
	portTestEnv->log("calling omrdump_create with empty filename\n");

#if defined(J9ZOS390)
	rc = omrdump_create(coreFileName, "IEATDUMP", NULL);
#else
	rc = omrdump_create(coreFileName, NULL, NULL);
#endif

	if (rc == 0) {
		uintptr_t verifyFileRC = 99;

		portTestEnv->log("omrdump_create claims to have written a core file to: %s\n", coreFileName);


#if defined(AIXPPC)
		/* We defer to fork abort on AIX machines that don't have "Enable full CORE dump" enabled in smit,
		 * in which case omrdump_create will not return the filename.
		 * So, only check for a specific filename if we are getting full core dumps */
		sys_parmRC = sys_parm(SYSP_GET, SYSP_V_FULLCORE, &myvar);

		if ((sys_parmRC == 0) && (myvar.v.v_fullcore.value == 1)) {

			doFileVerification = TRUE;
		}
#else /* defined(AIXPPC) */
		doFileVerification = TRUE;
#endif /* defined(AIXPPC) */
		if (doFileVerification) {
			verifyFileRC = verifyFileExists(PORTTEST_ERROR_ARGS, coreFileName);
			if (verifyFileRC == 0) {
				removeDump(OMRPORTLIB, coreFileName, testName);
			}
		}
	} else {
		outputErrorMessage(PORTTEST_ERROR_ARGS, "omrdump_create returned: %u, with filename: %s", rc, coreFileName);
	}
	reportTestExit(OMRPORTLIB, testName);
}
예제 #2
0
파일: omrosdump.c 프로젝트: ChengJin01/omr
/**
 * Create a dump file of the OS state.
 *
 * @param[in] portLibrary The port library.
 * @param[in] filename Buffer for filename optionally containing the filename where dump is to be output.
 * @param[out] filename filename used for dump file or error message.
 * @param[in] dumpType Type of dump to perform.
 * @param[in] userData Implementation specific data.
 *
 * @return 0 on success, non-zero otherwise.
 *
 * @note filename buffer can not be NULL.
 * @note user allocates and frees filename buffer.
 * @note filename buffer length is platform dependent, assumed to be EsMaxPath/MAX_PATH
 *
 * @note if filename buffer is empty, a filename will be generated.
 * @note if J9UNIQUE_DUMPS is set, filename will be unique.
 */
uintptr_t
omrdump_create(struct OMRPortLibrary *portLibrary, char *filename, char *dumpType, void *userData)
{

#if !defined(J9OS_I5)
	char *lastSep;
	intptr_t pid;

#if defined(AIXPPC)
	int rc = -1;
	struct vario myvar;
	int sys_parmRC;

	/* check to see if full core dumps are enabled */
	sys_parmRC = sys_parm(SYSP_GET, SYSP_V_FULLCORE, &myvar);

	if ((sys_parmRC == 0) && (myvar.v.v_fullcore.value == 1)) {

		/* full core dumps are enabled, go ahead and use gencore */
		unlimitCoreFileSize(portLibrary);
		rc = genSystemCoreUsingGencore(portLibrary, filename);

		if (rc == 0) {
			/* we have successfully generated the system core file */
			return rc;
		}
	} else {
		portLibrary->tty_err_printf(portLibrary, "Note: \"Enable full CORE dump\" in smit is set to FALSE and as a result there will be limited threading information in core file.\n");
	}
#endif /* aix_ppc */

	lastSep = filename ? strrchr(filename, DIR_SEPARATOR) : NULL;

	/* fork a child process from which we'll dump a core file */
	if ((pid = fork()) == 0) {
		/* in the child process */

#if defined(LINUX)
		/*
		 * on Linux, shared library pages don't appear in core files by default.
		 * Mark all pages writable to force these pages to appear
		 */
		markAllPagesWritable(portLibrary);
#endif /* defined(LINUX) */

#ifdef AIXPPC
		/* On AIX we need to ask sigaction for full dumps */
		{
			struct sigaction act;
			act.sa_handler = SIG_DFL;
			act.sa_flags = SA_FULLDUMP;
			sigfillset(&act.sa_mask);
			sigaction(SIGIOT, &act, 0);
		}
#endif

		/*
		 * CMVC 95748: don't use abort() after fork() on Linux as this seems to upset certain levels of glibc
		 */
#if defined(LINUX) || defined(OSX)
#define J9_DUMP_SIGNAL  SIGSEGV
#else /* defined(LINUX) || defined(OSX) */
#define J9_DUMP_SIGNAL  SIGABRT
#endif /* defined(LINUX) || defined(OSX) */

		/* Ensure we get default action (core) - reset primary&app handlers */
		OMRSIG_SIGNAL(J9_DUMP_SIGNAL, SIG_DFL);

		/* Move to specified folder before dumping? */
		if (lastSep != NULL) {
			lastSep[1] = '\0';
			chdir(filename);
		}

		/*
		 * Ensure that ulimit doesn't get in our way
		 */
		unlimitCoreFileSize(portLibrary);

#if defined(LINUX) || defined(OSX)
		pthread_kill(pthread_self(), J9_DUMP_SIGNAL);
#endif /* defined(LINUX) || defined(OSX) */

		abort();
	} /* end of child process */

	/* We are now in the parent process. First check that the fork() worked OK (CMVC 130439) */
	if (pid < 0) {
		portLibrary->str_printf(portLibrary, filename, EsMaxPath, "insufficient system resources to generate dump, errno=%d \"%s\"", errno, strerror(errno));
		return 1;
	}

#if defined(LINUX) || defined(OSX)

	if (NULL != filename) {

		/* Wait for child process that is generating core file to finish */
		waitpid(pid, NULL, 0);

		return renameDump(portLibrary, filename, pid, J9_DUMP_SIGNAL);
	} else {
		return 1;
	}

#elif defined(AIXPPC)

	if (filename && filename[0] != '\0') {
		char corepath[EsMaxPath] = "";

		/* Wait for child process that is generating core file to finish */
		waitpid(pid, NULL, 0);

		/* Copy path and remove basename */
		if (lastSep != NULL) {
			strcpy(corepath, filename);
			corepath[1 + lastSep - filename] = '\0';
		}

		findOSPreferredCoreDir(portLibrary, corepath);

		/* Search for expected names in the directory <corepath>
		 * and get the absolute path for the generated core file */
		appendCoreName(portLibrary, corepath, pid);

		/* check if the generated core filename ends in .Z (which indicates core compression was on) */
		if (strstr(corepath, ".Z") == (corepath + strlen(corepath) - strlen(".Z"))) {
			/* append the filename with ".Z" */
			if ((strlen(filename) + strlen(".Z") + 1) < EsMaxPath) {
				strcat(filename, ".Z");
			}
		}

		/* Apply suggested name */
		if (rename(corepath, filename)) {
			portLibrary->str_printf(portLibrary, filename, EsMaxPath, "cannot find core file: \"%s\". check \"ulimit -Hc\" is set high enough", strerror(errno));
			return 1;
		}

		return 0;
	}

	portLibrary->tty_err_printf(portLibrary, "Note: dump may be truncated if \"ulimit -c\" is set too low\n");

	/* guess typical filename */
	if (lastSep != NULL) {
		lastSep[1] = '\0';
		strcat(filename, "{default OS core name}");
	} else if (filename != NULL) {
		strcpy(filename, "{default OS core name}");
	}

	return 0;

#else

#error "This platform doesn't have an implementation of omrdump_create"

#endif /* #if defined(AIX) */

#else /* J9OS_I5 */

	if (getenv("I5_JVM_SUPPLIED_DUMP") == 0) {
		char corefile[EsMaxPath + 1] = "";
		intptr_t i5Pid = getpid();

		/* Ensure that ulimit doesn't get in our way */
		unlimitCoreFileSize(portLibrary);

		if (filename && filename[0] != '\0') {
			if (getenv("J9NO_DUMP_RENAMING")) {
				char *lastSep = filename ? strrchr(filename, DIR_SEPARATOR) : NULL;
				if (lastSep != NULL) {
					lastSep[1] = '\0';
					strcat(filename, "core");
				}
				strcpy(corefile, filename);
			} else {
				strcpy(corefile, filename);
			}
		} else {
			strcpy(corefile, "core");
			strcpy(filename, "{default OS core name}");
		}

		/* Generate the core file. On I5 gencore will always generate a full core dump */
		struct coredumpinfo coredumpinfop;
		memset(&coredumpinfop, 0, sizeof(coredumpinfop));

		coredumpinfop.length = strlen(corefile) + 1;
		coredumpinfop.name = corefile;
		coredumpinfop.pid = i5Pid;
		coredumpinfop.flags = GENCORE_VERSION_1;
		return gencore(&coredumpinfop);
	}
#endif /* J9OS_I5 */
}