diff --git a/runtime/include/chpl-mem-desc.h b/runtime/include/chpl-mem-desc.h index f9e65ea46892..7e5fccad38ca 100644 --- a/runtime/include/chpl-mem-desc.h +++ b/runtime/include/chpl-mem-desc.h @@ -57,6 +57,7 @@ extern "C" { m(SET_WIDE_STRING, "set wide string", true ), \ m(GET_WIDE_STRING, "get wide string", true ), \ m(COMMAND_BUFFER, "command buffer", true ), \ + m(FILENAME, "filename string", true ), \ m(COMM_UTIL, "comm layer utility space", false), \ m(COMM_XMIT_RCV_BUF, "comm layer transmit/receive buffer", false), \ m(COMM_FRK_SND_INFO, "comm layer sent remote fork info", false), \ diff --git a/runtime/include/chpllaunch.h b/runtime/include/chpllaunch.h index 43c1926c6b29..839847b35f4d 100644 --- a/runtime/include/chpllaunch.h +++ b/runtime/include/chpllaunch.h @@ -45,6 +45,9 @@ typedef struct { int chpl_doDryRun(void); void chpl_append_to_largv(int* largc, const char*** largv, int* largv_len, const char* arg); +void chpl_append_to_cmd(char** cmdBufPtr, int* charsWritten, + const char* format, ...) + __attribute__((format(printf, 3, 4))); int chpl_run_utility1K(const char *command, char *const argv[], char *outbuf, int outbuflen); int chpl_run_cmdstr(const char *commandStr, char *outbuf, int outbuflen); diff --git a/runtime/src/chpl-launcher-common.c b/runtime/src/chpl-launcher-common.c index c5abe13877ba..28d16962dd24 100644 --- a/runtime/src/chpl-launcher-common.c +++ b/runtime/src/chpl-launcher-common.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "chplcgfns.h" #include "chpl-comm-launch.h" #include "chpl-comm-locales.h" @@ -102,6 +103,45 @@ void chpl_append_to_largv(int* largc, const char*** largv, int* largv_len, (*largv)[(*largc)++] = (arg); } +// Helper for appending arguments to a variable-size command buffer. +// - Requires cmdBufPtr points to an uninitialized pointer on first call, and +// charsWritten is 0. +// - After exceeding an initial allocated size estimate, each call will allocate +// additional memory as needed. +void chpl_append_to_cmd(char** cmdBufPtr, int* charsWritten, + const char* format, ...) { + // Estimate of a buffer size that probably won't require extending, to avoid + // reallocations and copying. + static const int initialSize = 2048; + + va_list argsForLen, argsForPrint; + va_start(argsForLen, format); + va_copy(argsForPrint, argsForLen); + + // Allocate buffer to initial size on first call + if (*cmdBufPtr == NULL) { + assert(*charsWritten == 0); + *cmdBufPtr = (char*)chpl_mem_allocMany(initialSize, sizeof(char), + CHPL_RT_MD_COMMAND_BUFFER, -1, 0); + } + + // Determine additional characters to be written + const int addedLen = vsnprintf(NULL, 0, format, argsForLen); + va_end(argsForLen); + int newLen = *charsWritten + addedLen; + + // Allocate more memory if needed + if (newLen >= initialSize) { + *cmdBufPtr = (char*)chpl_mem_realloc(*cmdBufPtr, newLen * sizeof(char), + CHPL_RT_MD_COMMAND_BUFFER, -1, 0); + } + + // Write the new characters + vsnprintf(*cmdBufPtr + *charsWritten, addedLen + 1, format, argsForPrint); + va_end(argsForPrint); + *charsWritten = newLen; +} + // // Use this function to run short utility programs that will return less // than 1024 characters of output. The program must not expect any input. diff --git a/runtime/src/launch/pbs-aprun/launch-pbs-aprun.c b/runtime/src/launch/pbs-aprun/launch-pbs-aprun.c index 86408e084422..2e1b6ae3ad10 100644 --- a/runtime/src/launch/pbs-aprun/launch-pbs-aprun.c +++ b/runtime/src/launch/pbs-aprun/launch-pbs-aprun.c @@ -50,7 +50,7 @@ static char* walltime = NULL; static char* queue = NULL; static int generate_qsub_script = 0; -static char expectFilename[FILENAME_MAX]; +static char* expectFilename = NULL; extern int fileno(FILE *stream); @@ -236,8 +236,12 @@ static char** chpl_launch_create_argv(int argc, char* argv[], } else { mypid = 0; } - snprintf(expectFilename, FILENAME_MAX, "%s%d", - baseExpectFilename, (int)mypid); + int expectFilenameLen = + strlen(baseExpectFilename) + snprintf(NULL, 0, "%d", (int)mypid) + 1; + expectFilename = (char*)chpl_mem_allocMany(expectFilenameLen, sizeof(char), + CHPL_RT_MD_FILENAME, -1, 0); + snprintf(expectFilename, expectFilenameLen, "%s%d", baseExpectFilename, + (int)mypid); initAprunAttributes(); numCoresPerLocale = getCoresPerLocale(); @@ -386,10 +390,15 @@ static void genQsubScript(int argc, char *argv[], int numLocales) { static void chpl_launch_cleanup(void) { if (!chpl_doDryRun() && !debug) { if (unlink(expectFilename)) { - char msg[FILENAME_MAX + 35]; - snprintf(msg, FILENAME_MAX + 35, "Error removing temporary file '%s': %s", + char* format = "Error removing temporary file '%s': %s"; + int msgLen = + strlen(format) + strlen(expectFilename) + strlen(strerror(errno)); + char* msg = (char*)chpl_mem_allocMany(msgLen, sizeof(char), + CHPL_RT_MD_COMMAND_BUFFER, -1, 0); + snprintf(msg, msgLen, "Error removing temporary file '%s': %s", expectFilename, strerror(errno)); chpl_warning(msg, 0, 0); + chpl_mem_free(msg); } } } @@ -414,7 +423,7 @@ int chpl_launch(int argc, char* argv[], int32_t numLocales, argv[0]); chpl_launch_cleanup(); } - + chpl_mem_free(expectFilename); return retcode; } diff --git a/runtime/src/launch/pbs-gasnetrun_ibv/launch-pbs-gasnetrun_ibv.c b/runtime/src/launch/pbs-gasnetrun_ibv/launch-pbs-gasnetrun_ibv.c index bdcd4617509d..a05db314aec3 100644 --- a/runtime/src/launch/pbs-gasnetrun_ibv/launch-pbs-gasnetrun_ibv.c +++ b/runtime/src/launch/pbs-gasnetrun_ibv/launch-pbs-gasnetrun_ibv.c @@ -41,8 +41,8 @@ static char* walltime = NULL; #define basePBSFilename ".chpl-pbs-qsub-" #define baseExpectFilename ".chpl-expect-" -char pbsFilename[FILENAME_MAX]; -char expectFilename[FILENAME_MAX]; +char* pbsFilename = NULL; +char* expectFilename = NULL; #define launcherAccountEnvvar "CHPL_LAUNCHER_ACCOUNT" @@ -167,10 +167,17 @@ static char* chpl_launch_create_command(int argc, char* argv[], #else mypid = 0; #endif - snprintf(expectFilename, sizeof(expectFilename), "%s%d", baseExpectFilename, - (int)mypid); - snprintf(pbsFilename, sizeof(pbsFilename), "%s%d", basePBSFilename, + int expectFilenameLen = + strlen(baseExpectFilename) + snprintf(NULL, 0, "%d", (int)mypid) + 1; + expectFilename = (char*)chpl_mem_allocMany(expectFilenameLen, sizeof(char), + CHPL_RT_MD_FILENAME, -1, 0); + int pbsFilenameLen = + strlen(basePBSFilename) + snprintf(NULL, 0, "%d", (int)mypid) + 1; + pbsFilename = (char*)chpl_mem_allocMany(pbsFilenameLen, sizeof(char), + CHPL_RT_MD_FILENAME, -1, 0); + snprintf(expectFilename, expectFilenameLen, "%s%d", baseExpectFilename, (int)mypid); + snprintf(pbsFilename, pbsFilenameLen, "%s%d", basePBSFilename, (int)mypid); pbsFile = fopen(pbsFilename, "w"); fprintf(pbsFile, "#!/bin/sh\n\n"); @@ -254,6 +261,8 @@ static void chpl_launch_cleanup(void) { } } #endif + chpl_mem_free(pbsFilename); + chpl_mem_free(expectFilename); } diff --git a/runtime/src/launch/slurm-gasnetrun_common/slurm-gasnetrun_common.h b/runtime/src/launch/slurm-gasnetrun_common/slurm-gasnetrun_common.h index 9fd90e83c8d3..f49b66636ec9 100644 --- a/runtime/src/launch/slurm-gasnetrun_common/slurm-gasnetrun_common.h +++ b/runtime/src/launch/slurm-gasnetrun_common/slurm-gasnetrun_common.h @@ -56,7 +56,7 @@ static char* nodelist = NULL; static char* partition = NULL; static char* exclude = NULL; static char* gpusPerNode = NULL; -char slurmFilename[FILENAME_MAX]; +char* slurmFilename = NULL; /* copies of binary to run per node */ #define procsPerNode 1 @@ -173,17 +173,21 @@ static void genNumLocalesOptions(FILE* slurmFile, sbatchVersion sbatch, } } -static int propagate_environment(char* buf, size_t size) +// Append environment variables using chpl_append_to_cmd. +// charsWritten may be NULL, in which case it is ignored. +static void propagate_environment(char** buf, int* charsWritten) { - int len = 0; + int ignoredCharsWritten; + if (!charsWritten) { + charsWritten = &ignoredCharsWritten; + } // Indiscriminately propagate all environment variables. // We could do this more selectively, but we would be likely // to leave out something important. char *enviro_keys = chpl_get_enviro_keys(','); if (enviro_keys) - len += snprintf(buf, size, " -E '%s'", enviro_keys); - return len; + chpl_append_to_cmd(buf, charsWritten, " -E '%s'", enviro_keys); } static char* chpl_launch_create_command(int argc, char* argv[], @@ -192,8 +196,7 @@ static char* chpl_launch_create_command(int argc, char* argv[], int i; int size; - char baseCommand[2*FILENAME_MAX]; - char envProp[2*FILENAME_MAX]; + char* baseCommand = NULL; char* command; FILE* slurmFile; char* projectString = getenv(launcherAccountEnvvar); @@ -273,7 +276,12 @@ static char* chpl_launch_create_command(int argc, char* argv[], } else { mypid = getpid(); } - snprintf(slurmFilename, sizeof(slurmFilename), "%s%d", baseSBATCHFilename, (int)mypid); + int slurmFilenameLen = + strlen(baseSBATCHFilename) + snprintf(NULL, 0, "%d", (int)mypid) + 1; + slurmFilename = (char*)chpl_mem_allocMany(slurmFilenameLen, sizeof(char), + CHPL_RT_MD_FILENAME, -1, 0); + snprintf(slurmFilename, slurmFilenameLen, "%s%d", baseSBATCHFilename, + (int)mypid); if (getenv("CHPL_LAUNCHER_USE_SBATCH") != NULL) { slurmFile = fopen(slurmFilename, "w"); @@ -297,8 +305,10 @@ static char* chpl_launch_create_command(int argc, char* argv[], CHPL_THIRD_PARTY, WRAP_TO_STR(LAUNCH_PATH), GASNETRUN_LAUNCHER, numLocales, numLocales); - propagate_environment(envProp, sizeof(envProp)); + char* envProp = NULL; + propagate_environment(&envProp, NULL); fprintf(slurmFile, "%s", envProp); + chpl_mem_free(envProp); fprintf(slurmFile, " %s %s", chpl_get_real_binary_wrapper(), chpl_get_real_binary_name()); @@ -309,56 +319,54 @@ static char* chpl_launch_create_command(int argc, char* argv[], fclose(slurmFile); chmod(slurmFilename, 0755); - - snprintf(baseCommand, sizeof(baseCommand), "sbatch %s\n", slurmFilename); + char* format="sbatch %s\n"; + int baseCommandLen = strlen(slurmFilename) + strlen(format); + baseCommand = (char*)chpl_mem_allocMany(baseCommandLen, sizeof(char), + CHPL_RT_MD_COMMAND_BUFFER, -1, 0); + snprintf(baseCommand, baseCommandLen, format, slurmFilename); } else { - char iCom[2*FILENAME_MAX-10]; + char* iCom = NULL; int len = 0; if (!getSlurmDebug()) { - len += snprintf(iCom+len, sizeof(iCom)-len, "--quiet "); + chpl_append_to_cmd(&iCom, &len, "--quiet "); } - len += snprintf(iCom+len, sizeof(iCom)-len, "-J %s ", jobName); - len += snprintf(iCom+len, sizeof(iCom)-len, "-N %d ", numNodes); - len += snprintf(iCom+len, sizeof(iCom)-len, "--ntasks=%d ", numLocales); - if (nodeAccessStr != NULL) - len += snprintf(iCom+len, sizeof(iCom)-len, "--%s ", nodeAccessStr); - if (walltime) - len += snprintf(iCom+len, sizeof(iCom)-len, "--time=%s ", walltime); - if (nodelist) - len += snprintf(iCom+len, sizeof(iCom)-len, "--nodelist=%s ", nodelist); - if(partition) - len += snprintf(iCom+len, sizeof(iCom)-len, "--partition=%s ", partition); - if(exclude) - len += snprintf(iCom+len, sizeof(iCom)-len, "--exclude=%s ", exclude); - if(gpusPerNode) - len += snprintf(iCom+len, sizeof(iCom)-len, "--gpus-per-node=%s ", gpusPerNode); - if(projectString && strlen(projectString) > 0) - len += snprintf(iCom+len, sizeof(iCom)-len, "--account=%s ", - projectString); - if (constraint) - len += snprintf(iCom+len, sizeof(iCom)-len, " -C %s", constraint); - len += snprintf(iCom+len, sizeof(iCom)-len, - " %s/%s/%s -n %d -N %d -c 0", + chpl_append_to_cmd(&iCom, &len, "-J %s ", jobName); + chpl_append_to_cmd(&iCom, &len, "-N %d ", numNodes); + chpl_append_to_cmd(&iCom, &len, "--ntasks=%d ", numLocales); + if (nodeAccessStr != NULL) chpl_append_to_cmd(&iCom, &len, "--%s ", nodeAccessStr); + if (walltime) chpl_append_to_cmd(&iCom, &len, "--time=%s ", walltime); + if (nodelist) chpl_append_to_cmd(&iCom, &len, "--nodelist=%s ", nodelist); + if (partition) chpl_append_to_cmd(&iCom, &len, "--partition=%s ", partition); + if (exclude) chpl_append_to_cmd(&iCom, &len, "--exclude=%s ", exclude); + if (gpusPerNode) chpl_append_to_cmd(&iCom, &len, "--gpus-per-node=%s ", gpusPerNode); + if (projectString && strlen(projectString) > 0) + chpl_append_to_cmd(&iCom, &len, "--account=%s ", projectString); + if (constraint) chpl_append_to_cmd(&iCom, &len, "-C %s", constraint); + chpl_append_to_cmd(&iCom, &len, " %s/%s/%s -n %d -N %d -c 0", CHPL_THIRD_PARTY, WRAP_TO_STR(LAUNCH_PATH), GASNETRUN_LAUNCHER, numLocales, numNodes); - len += propagate_environment(iCom+len, sizeof(iCom) - len); - len += snprintf(iCom+len, sizeof(iCom)-len, " %s %s", - chpl_get_real_binary_wrapper(), + propagate_environment(&iCom, &len); + chpl_append_to_cmd(&iCom, &len, " %s %s", chpl_get_real_binary_wrapper(), chpl_get_real_binary_name()); for (i=1; i size) { chpl_internal_error("buffer overflow"); } @@ -385,6 +393,7 @@ int chpl_launch(int argc, char* argv[], int32_t numLocales, numLocales, numLocalesPerNode), argv[0]); chpl_launch_cleanup(); + chpl_mem_free(slurmFilename); return retcode; } diff --git a/runtime/src/launch/slurm-srun/launch-slurm-srun.c b/runtime/src/launch/slurm-srun/launch-slurm-srun.c index 43ba7bb65b46..45c7846363f8 100644 --- a/runtime/src/launch/slurm-srun/launch-slurm-srun.c +++ b/runtime/src/launch/slurm-srun/launch-slurm-srun.c @@ -50,7 +50,7 @@ static char* reservation = NULL; static char* exclude = NULL; static char* gpusPerNode = NULL; -char slurmFilename[FILENAME_MAX]; +char* slurmFilename = NULL; // /tmp is always available on cray compute nodes (it's a memory mounted dir.) // If we ever need this to run on non-cray machines, we should update this to @@ -221,7 +221,6 @@ static chpl_bool getSlurmDebug(chpl_bool batch) { } -#define MAX_COM_LEN (FILENAME_MAX + 128) // create the command that will actually launch the program and // create any files needed for the launch like the batch script static char* chpl_launch_create_command(int argc, char* argv[], @@ -229,7 +228,7 @@ static char* chpl_launch_create_command(int argc, char* argv[], int32_t numLocalesPerNode) { int i; int size; - char baseCommand[MAX_COM_LEN]; + char* baseCommand=NULL; char* command; FILE* slurmFile; char* account = getenv("CHPL_LAUNCHER_ACCOUNT"); @@ -265,9 +264,9 @@ static char* chpl_launch_create_command(int argc, char* argv[], // because they haven't been initialized yet char* bufferStdout = getenv("CHPL_LAUNCHER_SLURM_BUFFER_STDOUT"); const char* tmpDir = getTmpDir(); - char stdoutFile [MAX_COM_LEN]; - char stdoutFileNoFmt [MAX_COM_LEN]; - char tmpStdoutFileNoFmt [MAX_COM_LEN]; + char* stdoutFile = NULL; + char* stdoutFileNoFmt = NULL; + char* tmpStdoutFileNoFmt = NULL; // Note: if numLocalesPerNode > numLocales then some cores will go unused. This // is by design, as it allows for scalability testing by increasing the @@ -361,6 +360,9 @@ static char* chpl_launch_create_command(int argc, char* argv[], // if were running a batch job if (getenv("CHPL_LAUNCHER_USE_SBATCH") != NULL || generate_sbatch_script) { + slurmFilename = (char*)chpl_mem_allocMany( + (strlen(baseSBATCHFilename) + snprintf(NULL, 0, "%d", (int)mypid) + 1), + sizeof(char), CHPL_RT_MD_FILENAME, -1, 0); // set the sbatch filename snprintf(slurmFilename, sizeof(slurmFilename), "%s%d", baseSBATCHFilename, (int)mypid); @@ -432,15 +434,27 @@ static char* chpl_launch_create_command(int argc, char* argv[], // set the output file name to either the user specified // name or to the binaryName..out if none specified if (outputfn != NULL) { - snprintf(stdoutFile, sizeof(stdoutFile), "%s", outputfn); - snprintf(stdoutFileNoFmt, sizeof(stdoutFileNoFmt), "%s", outputfn); + int stdoutFileLen = strlen(outputfn) + 1; + stdoutFile = (char*)chpl_mem_allocMany(stdoutFileLen, sizeof(char), + CHPL_RT_MD_FILENAME, -1, 0); + snprintf(stdoutFile, stdoutFileLen, "%s", outputfn); + stdoutFileNoFmt = (char*)chpl_mem_allocMany(stdoutFileLen, sizeof(char), + CHPL_RT_MD_FILENAME, -1, 0); + snprintf(stdoutFileNoFmt, stdoutFileLen, "%s", outputfn); } else { - snprintf(stdoutFile, sizeof(stdoutFile), "%s.%s.out", argv[0], "%j"); - snprintf(stdoutFileNoFmt, sizeof(stdoutFileNoFmt), "%s.%s.out", argv[0], - "$SLURM_JOB_ID"); + char* format="%s.%s.out"; + int stdoutFileLen = strlen(format) + strlen(argv[0]) + strlen("%j"); + stdoutFile = (char*)chpl_mem_allocMany(stdoutFileLen, sizeof(char), + CHPL_RT_MD_FILENAME, -1, 0); + snprintf(stdoutFile, stdoutFileLen, format, argv[0], "%j"); + char* tempArg = "$SLURM_JOB_ID"; + int stdoutFileNoFmtLen = + strlen(format) + strlen(argv[0]) + strlen(tempArg); + stdoutFileNoFmt = (char*)chpl_mem_allocMany( + stdoutFileNoFmtLen, sizeof(char), CHPL_RT_MD_FILENAME, -1, 0); + snprintf(stdoutFileNoFmt, stdoutFileNoFmtLen, format, argv[0], tempArg); } - // We have slurm use the real output file to capture slurm errors/timeouts // We only redirect the program output to the tmp file fprintf(slurmFile, "#SBATCH --output=%s\n", stdoutFile); @@ -452,8 +466,14 @@ static char* chpl_launch_create_command(int argc, char* argv[], // If we're buffering the output, set the temp output file name. // It's always /binaryName..out. if (bufferStdout != NULL) { - snprintf(tmpStdoutFileNoFmt, sizeof(tmpStdoutFileNoFmt),"%s/%s.%s.out", - tmpDir, argv[0], "$SLURM_JOB_ID"); + char* format = "%s/%s.%s.out"; + char* tempArg = "$SLURM_JOB_ID"; + int tmpStdoutFileNoFmtLen = + strlen(format) + strlen(tmpDir) + strlen(argv[0]) + strlen(tempArg); + tmpStdoutFileNoFmt = (char*)chpl_mem_allocMany( + tmpStdoutFileNoFmtLen, sizeof(char), CHPL_RT_MD_FILENAME, -1, 0); + snprintf(tmpStdoutFileNoFmt, tmpStdoutFileNoFmtLen, format, tmpDir, + argv[0], tempArg); } // add the srun command @@ -486,6 +506,9 @@ static char* chpl_launch_create_command(int argc, char* argv[], if (bufferStdout != NULL) { fprintf(slurmFile, "cat %s >> %s\n", tmpStdoutFileNoFmt, stdoutFileNoFmt); fprintf(slurmFile, "rm %s &> /dev/null\n", tmpStdoutFileNoFmt); + // tmpStdoutFileNoFmt is only allocated memory if bufferStdout!=NULL + // Hence free up inside this condition. + chpl_mem_free(tmpStdoutFileNoFmt); } // close the batch file and change permissions @@ -498,20 +521,22 @@ static char* chpl_launch_create_command(int argc, char* argv[], // the baseCommand is what will call the batch file // that was just created - snprintf(baseCommand, sizeof(baseCommand), "sbatch %s\n", slurmFilename); + char* format = "sbatch %s\n"; + int baseCommandLen = strlen(slurmFilename) + strlen(format); + baseCommand = (char*)chpl_mem_allocMany(baseCommandLen, sizeof(char), + CHPL_RT_MD_COMMAND_BUFFER, -1, 0); + snprintf(baseCommand, baseCommandLen, format, slurmFilename); } // else we're running an interactive job else { - char iCom[1024]; - int len; - - len = 0; + char* iCom = NULL; + int len = 0; // set the job name - len += snprintf(iCom+len, sizeof(iCom)-len, "--job-name=%s ", jobName); + chpl_append_to_cmd(&iCom, &len, "--job-name=%s ", jobName); if (!getSlurmDebug(/*batch=*/false)) { // suppress informational messages, will still display errors - len += snprintf(iCom+len, sizeof(iCom)-len, "--quiet "); + chpl_append_to_cmd(&iCom, &len, "--quiet "); } // request the number of locales, with 1 task per node, and number of cores @@ -519,83 +544,89 @@ static char* chpl_launch_create_command(int argc, char* argv[], // since 1 task-per-node with n --tasks implies -n nodes int32_t numNodes = (numLocales + numLocalesPerNode - 1) / numLocalesPerNode; - len += snprintf(iCom+len, sizeof(iCom)-len, "--nodes=%d ",numNodes); - len += snprintf(iCom+len, sizeof(iCom)-len, "--ntasks=%d ", numLocales); + chpl_append_to_cmd(&iCom, &len, "--nodes=%d ", numNodes); + chpl_append_to_cmd(&iCom, &len, "--ntasks=%d ", numLocales); int localesOnNode = (numLocales < numLocalesPerNode) ? numLocales : numLocalesPerNode; int cpusPerTask = getCoresPerLocale(nomultithread(false), localesOnNode); - len += snprintf(iCom+len, sizeof(iCom)-len, "--cpus-per-task=%d ", - cpusPerTask); + chpl_append_to_cmd(&iCom, &len, "--cpus-per-task=%d ", cpusPerTask); if (numLocalesPerNode > 1) { - len += snprintf(iCom+len, sizeof(iCom)-len, "--cpu-bind=none "); + chpl_append_to_cmd(&iCom, &len, "--cpu-bind=none "); } // request specified node access if (nodeAccessStr != NULL) - len += snprintf(iCom+len, sizeof(iCom)-len, "--%s ", nodeAccessStr); + chpl_append_to_cmd(&iCom, &len, "--%s ", nodeAccessStr); // request specified amount of memory if (memStr != NULL) - len += snprintf(iCom+len, sizeof(iCom)-len, "--mem=%s ", memStr); + chpl_append_to_cmd(&iCom, &len, "--mem=%s ", memStr); // kill the job if any program instance halts with non-zero exit status - len += snprintf(iCom+len, sizeof(iCom)-len, "--kill-on-bad-exit "); + chpl_append_to_cmd(&iCom, &len, "--kill-on-bad-exit "); // Set the walltime if it was specified if (walltime) { - len += snprintf(iCom+len, sizeof(iCom)-len, "--time=%s ",walltime); + chpl_append_to_cmd(&iCom, &len, "--time=%s ", walltime); } // Set the nodelist if it was specified if (nodelist) { - len += snprintf(iCom+len, sizeof(iCom)-len, "--nodelist=%s ", nodelist); + chpl_append_to_cmd(&iCom, &len, "--nodelist=%s ", nodelist); } // Set the partition if it was specified if (partition) { - len += snprintf(iCom+len, sizeof(iCom)-len, "--partition=%s ", - partition); + chpl_append_to_cmd(&iCom, &len, "--partition=%s ", partition); } // Set the exclude list if it was specified if (exclude) { - len += snprintf(iCom+len, sizeof(iCom)-len, "--exclude=%s ", exclude); + chpl_append_to_cmd(&iCom, &len, "--exclude=%s ", exclude); } // Set the gpus per node if it was specified if (gpusPerNode) { - len += snprintf(iCom+len, sizeof(iCom)-len, "--gpus-per-node=%s ", - gpusPerNode); + chpl_append_to_cmd(&iCom, &len, "--gpus-per-node=%s ", gpusPerNode); } // set any constraints if (constraint) { - len += snprintf(iCom+len, sizeof(iCom)-len, "--constraint=%s ", constraint); + chpl_append_to_cmd(&iCom, &len, "--constraint=%s ", constraint); } // set the account name if one was provided if (account && strlen(account) > 0) { - len += snprintf(iCom+len, sizeof(iCom)-len, "--account=%s ", account); + chpl_append_to_cmd(&iCom, &len, "--account=%s ", account); } // add the (possibly wrapped) binary name - len += snprintf(iCom+len, sizeof(iCom)-len, "%s %s", + chpl_append_to_cmd(&iCom, &len, "%s %s ", chpl_get_real_binary_wrapper(), chpl_get_real_binary_name()); // add any arguments passed to the launcher to the binary for (i=1; i size) { chpl_internal_error("buffer overflow"); } @@ -617,10 +648,13 @@ static void chpl_launch_cleanup(void) { // remove sbatch file unless it was explicitly generated by the user if (getenv("CHPL_LAUNCHER_USE_SBATCH") != NULL && !generate_sbatch_script) { if (unlink(slurmFilename)) { - char msg[FILENAME_MAX + 128]; + char* msg = (char*)chpl_mem_allocMany( + (strlen(slurmFilename) + strlen(strerror(errno)) + 36), + sizeof(char), CHPL_RT_MD_FILENAME, -1, 0); snprintf(msg, sizeof(msg), "Error removing temporary file '%s': %s", slurmFilename, strerror(errno)); chpl_warning(msg, 0, 0); + chpl_mem_free(msg); } } } @@ -650,6 +684,7 @@ int chpl_launch(int argc, char* argv[], int32_t numLocales, chpl_launch_cleanup(); } + chpl_mem_free(slurmFilename); return retcode; }