Skip to content
Snippets Groups Projects
Commit a531d04b authored by Jeff Cohen's avatar Jeff Cohen
Browse files

Implement memoryLimit on Windows.

llvm-svn: 34922
parent 50bf51e8
No related branches found
No related tags found
No related merge requests found
...@@ -93,8 +93,8 @@ static HANDLE RedirectIO(const Path *path, int fd, std::string* ErrMsg) { ...@@ -93,8 +93,8 @@ static HANDLE RedirectIO(const Path *path, int fd, std::string* ErrMsg) {
if (h == INVALID_HANDLE_VALUE) { if (h == INVALID_HANDLE_VALUE) {
MakeErrMsg(ErrMsg, std::string(fname) + ": Can't open file for " + MakeErrMsg(ErrMsg, std::string(fname) + ": Can't open file for " +
(fd ? "input: " : "output: ")); (fd ? "input: " : "output: "));
return h;
} }
return h; return h;
} }
...@@ -179,7 +179,7 @@ Program::ExecuteAndWait(const Path& path, ...@@ -179,7 +179,7 @@ Program::ExecuteAndWait(const Path& path,
0, TRUE, DUPLICATE_SAME_ACCESS); 0, TRUE, DUPLICATE_SAME_ACCESS);
} }
} }
PROCESS_INFORMATION pi; PROCESS_INFORMATION pi;
memset(&pi, 0, sizeof(pi)); memset(&pi, 0, sizeof(pi));
...@@ -204,6 +204,35 @@ Program::ExecuteAndWait(const Path& path, ...@@ -204,6 +204,35 @@ Program::ExecuteAndWait(const Path& path,
return -1; return -1;
} }
// Make sure these get closed no matter what.
AutoHandle hProcess(pi.hProcess);
AutoHandle hThread(pi.hThread);
// Assign the process to a job if a memory limit is defined.
AutoHandle hJob(0);
if (memoryLimit != 0) {
hJob = CreateJobObject(0, 0);
bool success = false;
if (hJob != 0) {
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli;
memset(&jeli, 0, sizeof(jeli));
jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_PROCESS_MEMORY;
jeli.ProcessMemoryLimit = memoryLimit * 1048576;
if (SetInformationJobObject(hJob, JobObjectExtendedLimitInformation,
&jeli, sizeof(jeli))) {
if (AssignProcessToJobObject(hJob, pi.hProcess))
success = true;
}
}
if (!success) {
SetLastError(GetLastError());
MakeErrMsg(ErrMsg, std::string("Unable to set memory limit"));
TerminateProcess(pi.hProcess, 1);
WaitForSingleObject(pi.hProcess, INFINITE);
return -1;
}
}
// Wait for it to terminate. // Wait for it to terminate.
DWORD millisecondsToWait = INFINITE; DWORD millisecondsToWait = INFINITE;
if (secondsToWait > 0) if (secondsToWait > 0)
...@@ -223,10 +252,6 @@ Program::ExecuteAndWait(const Path& path, ...@@ -223,10 +252,6 @@ Program::ExecuteAndWait(const Path& path,
rc = GetExitCodeProcess(pi.hProcess, &status); rc = GetExitCodeProcess(pi.hProcess, &status);
err = GetLastError(); err = GetLastError();
// Done with the handles; go close them.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
if (!rc) { if (!rc) {
SetLastError(err); SetLastError(err);
MakeErrMsg(ErrMsg, std::string("Failed getting status for program '") + MakeErrMsg(ErrMsg, std::string("Failed getting status for program '") +
......
...@@ -34,3 +34,24 @@ inline bool MakeErrMsg(std::string* ErrMsg, const std::string& prefix) { ...@@ -34,3 +34,24 @@ inline bool MakeErrMsg(std::string* ErrMsg, const std::string& prefix) {
LocalFree(buffer); LocalFree(buffer);
return true; return true;
} }
class AutoHandle {
HANDLE handle;
public:
AutoHandle(HANDLE h) : handle(h) {}
~AutoHandle() {
if (handle)
CloseHandle(handle);
}
operator HANDLE() {
return handle;
}
AutoHandle &operator=(HANDLE h) {
handle = h;
return *this;
}
};
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment