32607528da47324047452ccebe5c1c6c991f37db galt Tue Oct 9 20:38:32 2012 -0700 Fix parasol to correctly enforce memory limits. diff --git src/parasol/paraNode/paraNode.c src/parasol/paraNode/paraNode.c index f23fd16..040eaf5 100644 --- src/parasol/paraNode/paraNode.c +++ src/parasol/paraNode/paraNode.c @@ -349,51 +349,63 @@ errnoAbort("can't open job stdout file %s", out); if (dup2(newStdout, STDOUT_FILENO) < 0) errnoAbort("can't dup2 stdout"); } void execProc(char *managingHost, char *jobIdString, char *reserved, char *user, char *dir, char *in, char *out, char *err, long long memLimit, char *exe, char **params) /* This routine is the child process of doExec. * It spawns a grandchild that actually does the * work and waits on it. It sends message to the * main message loop here when done. */ { if ((grandChildId = forkOrDie()) == 0) { + // use rlimit to limit RAM available to process so it will not hog the machine unfairly. + if (sizeof(long) == 4 && memLimit > 4294967295LL) // 4GB is max value on 32-bit platform. + { + logWarn("memLimit %lld exceeds address space on 32-bit machine, treating it as 4GB limit", memLimit); + memLimit = 4294967295LL; + } + struct rlimit rlim; + rlim.rlim_cur = rlim.rlim_max = memLimit; + if (setrlimit(RLIMIT_DATA, &rlim) < 0) + logWarn("setrlimit failed with RLIMIT_DATA rlim_cur=%lld rlim_max=%lld" + , (long long) rlim.rlim_cur , (long long) rlim.rlim_max); + // although RLIMIT_AS is not supported/enforced on all platforms, + // it is useful for linux and some other unix OSes. + if (setrlimit(RLIMIT_AS, &rlim) < 0) + logWarn("setrlimit failed with RLIMIT_AS rlim_cur=%lld rlim_max=%lld" + , (long long) rlim.rlim_cur , (long long) rlim.rlim_max); + char *homeDir = ""; /* Change to given user (if root) */ changeUid(user, &homeDir); /* create output files just after becoming user so that errors in the rest * of this proc will go to the err file and be available via para * problems */ setupProcStdio(in, out, err); if (chdir(dir) < 0) errnoAbort("can't chdir to %s", dir); setsid(); // setpgid(0,0); umask(umaskVal); - struct rlimit rlim; - rlim.rlim_cur = rlim.rlim_max = memLimit; - if(setrlimit(RLIMIT_CORE, &rlim) < 0) - perror("setrlimit"); - /* Update environment. */ { struct hash *hash = environToHash(environ); hashUpdate(hash, "JOB_ID", jobIdString); hashUpdate(hash, "USER", user); hashUpdate(hash, "HOME", homeDir); hashUpdate(hash, "HOST", hostName); hashUpdate(hash, "PARASOL", "7"); updatePath(hash, userPath, homeDir, sysPath); addEnvExtras(hash); environ = hashToEnviron(hash); freeHashAndVals(&hash); }