Пример #1
0
static intptr_t
ceedump(struct OMRPortLibrary *portLibrary, char *asciiLabel, char *ebcdicLabel)
{
	/* Optional dump location hint */
	const char *location = getenv("_CEE_DMPTARG");
	char corepath[EsMaxPath] = ".";
	struct stat attrBuf;
	int rc;

	omrtty_err_printf(portLibrary, "CEEDUMP in progress - Please Wait.\n");

	/* replace call to __cdump() with call to csnap() as this does not lock up. see CMVC 134311 */
	/* original line : rc = cdump(ebcdicLabel); */
	rc = csnap(ebcdicLabel);

	if (location) {
		strncpy(corepath, location, EsMaxPath);
		corepath[EsMaxPath - 1] = '\0';
	} else {
		getcwd(corepath, EsMaxPath);
	}

	/* Normalize path */
	if (corepath[strlen(corepath) - 1] != '/') {
		strcat(corepath, "/");
	}

	/* Search for most likely CEEDUMP file */
	appendCoreName(portLibrary, corepath, EsMaxPath, getpid());

	/* __cdump may return 1 even on success, so check that the file exists
	 *  This from the V1R9 C/C++ Runtime Library Reference
	 *  	The output of the dump is directed to the CEESNAP data set.
	 *  	The DD definition for CEESNAP is as follows: //CEESNAP DD SYSOUT= *
	 *  	If the data set is not defined, or is not usable for any reason, cdump() returns a failure code of 1.
	 *  	This occurs even if the call to CEE3DMP is successful.
	 *  	For more information see "Debugging C/C++ Routines" in "z/OS Language Environment Debugging Guide"
	 */
	if (1 == rc) {
		if (stat(corepath, &attrBuf)) {
			rc = errno;
		} else {
			rc = 0;
		}
	}

	if (rc) {
		omrtty_err_printf(portLibrary, "CEEDUMP failure for FILE='%s' RC=0x%08X\n", corepath, rc);
	} else {
		if (asciiLabel != NULL) {
			strncpy(asciiLabel, corepath, EsMaxPath);
		}
		omrtty_err_printf(portLibrary, "CEEDUMP success for FILE='%s'\n", corepath);
	}

	return rc;
}
Пример #2
0
/**
 * 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 */
}