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; }
/** * 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 */ }