summaryrefslogtreecommitdiffstats
path: root/lib/System/Win32
diff options
context:
space:
mode:
Diffstat (limited to 'lib/System/Win32')
-rw-r--r--lib/System/Win32/DynamicLibrary.inc44
-rw-r--r--lib/System/Win32/Memory.inc7
-rw-r--r--lib/System/Win32/Path.inc30
-rw-r--r--lib/System/Win32/Process.inc10
-rw-r--r--lib/System/Win32/Program.inc130
-rw-r--r--lib/System/Win32/Signals.inc53
-rw-r--r--lib/System/Win32/TimeValue.inc2
7 files changed, 192 insertions, 84 deletions
diff --git a/lib/System/Win32/DynamicLibrary.inc b/lib/System/Win32/DynamicLibrary.inc
index aa04268..10e64aa 100644
--- a/lib/System/Win32/DynamicLibrary.inc
+++ b/lib/System/Win32/DynamicLibrary.inc
@@ -67,7 +67,6 @@ extern "C" {
PVOID UserContext)
#endif
{
- llvm::sys::SmartScopedWriter<true> Writer(&SymbolsLock);
// Ignore VC++ runtimes prior to 7.1. Somehow some of them get loaded
// into the process.
if (stricmp(ModuleName, "msvci70") != 0 &&
@@ -89,36 +88,9 @@ extern "C" {
}
}
-DynamicLibrary::DynamicLibrary() : handle(0) {
- SmartScopedWriter<true> Writer(&SymbolsLock);
- handle = GetModuleHandle(NULL);
- OpenedHandles.push_back((HMODULE)handle);
-}
-
-DynamicLibrary::~DynamicLibrary() {
- llvm::sys::SmartScopedWriter<true> Writer(&SymbolsLock);
- if (handle == 0)
- return;
-
- // GetModuleHandle() does not increment the ref count, so we must not free
- // the handle to the executable.
- if (handle != GetModuleHandle(NULL))
- FreeLibrary((HMODULE)handle);
- handle = 0;
-
- for (std::vector<HMODULE>::iterator I = OpenedHandles.begin(),
- E = OpenedHandles.end(); I != E; ++I) {
- if (*I == handle) {
- // Note: don't use the swap/pop_back trick here. Order is important.
- OpenedHandles.erase(I);
- }
- }
-}
-
bool DynamicLibrary::LoadLibraryPermanently(const char *filename,
std::string *ErrMsg) {
if (filename) {
- llvm::sys::SmartScopedWriter<true> Writer(&SymbolsLock);
HMODULE a_handle = LoadLibrary(filename);
if (a_handle == 0)
@@ -170,24 +142,22 @@ bool DynamicLibrary::LoadLibraryPermanently(const char *filename,
void* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) {
// First check symbols added via AddSymbol().
- SymbolsLock.reader_acquire();
- std::map<std::string, void *>::iterator I = symbols.find(symbolName);
- std::map<std::string, void *>::iterator E = symbols.end();
- SymbolsLock.reader_release();
- if (I != E)
- return I->second;
+ if (ExplicitSymbols) {
+ std::map<std::string, void *>::iterator I =
+ ExplicitSymbols->find(symbolName);
+ std::map<std::string, void *>::iterator E = ExplicitSymbols->end();
+ if (I != E)
+ return I->second;
+ }
// Now search the libraries.
- SymbolsLock.writer_acquire();
for (std::vector<HMODULE>::iterator I = OpenedHandles.begin(),
E = OpenedHandles.end(); I != E; ++I) {
FARPROC ptr = GetProcAddress((HMODULE)*I, symbolName);
if (ptr) {
- SymbolsLock.writer_release();
return (void *) ptr;
}
}
- SymbolsLock.writer_release();
#if defined(__MINGW32__)
{
diff --git a/lib/System/Win32/Memory.inc b/lib/System/Win32/Memory.inc
index 5e5cf7a..7611ecd 100644
--- a/lib/System/Win32/Memory.inc
+++ b/lib/System/Win32/Memory.inc
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "Win32.h"
+#include "llvm/Support/DataTypes.h"
#include "llvm/System/Process.h"
namespace llvm {
@@ -23,13 +24,13 @@ using namespace sys;
//=== and must not be UNIX code
//===----------------------------------------------------------------------===//
-MemoryBlock Memory::AllocateRWX(unsigned NumBytes,
+MemoryBlock Memory::AllocateRWX(size_t NumBytes,
const MemoryBlock *NearBlock,
std::string *ErrMsg) {
if (NumBytes == 0) return MemoryBlock();
- static const long pageSize = Process::GetPageSize();
- unsigned NumPages = (NumBytes+pageSize-1)/pageSize;
+ static const size_t pageSize = Process::GetPageSize();
+ size_t NumPages = (NumBytes+pageSize-1)/pageSize;
//FIXME: support NearBlock if ever needed on Win64.
diff --git a/lib/System/Win32/Path.inc b/lib/System/Win32/Path.inc
index 683c94b..46b965f 100644
--- a/lib/System/Win32/Path.inc
+++ b/lib/System/Win32/Path.inc
@@ -125,9 +125,30 @@ Path::isValid() const {
return true;
}
+void Path::makeAbsolute() {
+ TCHAR FullPath[MAX_PATH + 1] = {0};
+ LPTSTR FilePart = NULL;
+
+ DWORD RetLength = ::GetFullPathNameA(path.c_str(),
+ sizeof(FullPath)/sizeof(FullPath[0]),
+ FullPath, &FilePart);
+
+ if (0 == RetLength) {
+ // FIXME: Report the error GetLastError()
+ assert(0 && "Unable to make absolute path!");
+ } else if (RetLength > MAX_PATH) {
+ // FIXME: Report too small buffer (needed RetLength bytes).
+ assert(0 && "Unable to make absolute path!");
+ } else {
+ path = FullPath;
+ }
+}
+
bool
Path::isAbsolute(const char *NameStart, unsigned NameLen) {
assert(NameStart);
+ // FIXME: This does not handle correctly an absolute path starting from
+ // a drive letter or in UNC format.
switch (NameLen) {
case 0:
return false;
@@ -135,12 +156,15 @@ Path::isAbsolute(const char *NameStart, unsigned NameLen) {
case 2:
return NameStart[0] == '/';
default:
- return NameStart[0] == '/' || (NameStart[1] == ':' && NameStart[2] == '/');
+ return (NameStart[0] == '/' || (NameStart[1] == ':' && NameStart[2] == '/')) ||
+ (NameStart[0] == '\\' || (NameStart[1] == ':' && NameStart[2] == '\\'));
}
}
bool
Path::isAbsolute() const {
+ // FIXME: This does not handle correctly an absolute path starting from
+ // a drive letter or in UNC format.
switch (path.length()) {
case 0:
return false;
@@ -784,8 +808,8 @@ CopyFile(const sys::Path &Dest, const sys::Path &Src, std::string* ErrMsg) {
// Can't use CopyFile macro defined in Windows.h because it would mess up the
// above line. We use the expansion it would have in a non-UNICODE build.
if (!::CopyFileA(Src.c_str(), Dest.c_str(), false))
- return MakeErrMsg(ErrMsg, "Can't copy '" + Src.toString() +
- "' to '" + Dest.toString() + "': ");
+ return MakeErrMsg(ErrMsg, "Can't copy '" + Src.str() +
+ "' to '" + Dest.str() + "': ");
return false;
}
diff --git a/lib/System/Win32/Process.inc b/lib/System/Win32/Process.inc
index cfbe33c..feb0806 100644
--- a/lib/System/Win32/Process.inc
+++ b/lib/System/Win32/Process.inc
@@ -120,15 +120,19 @@ void Process::PreventCoreFiles() {
}
bool Process::StandardInIsUserInput() {
- return GetFileType((HANDLE)_get_osfhandle(0)) == FILE_TYPE_CHAR;
+ return FileDescriptorIsDisplayed(0);
}
bool Process::StandardOutIsDisplayed() {
- return GetFileType((HANDLE)_get_osfhandle(1)) == FILE_TYPE_CHAR;
+ return FileDescriptorIsDisplayed(1);
}
bool Process::StandardErrIsDisplayed() {
- return GetFileType((HANDLE)_get_osfhandle(2)) == FILE_TYPE_CHAR;
+ return FileDescriptorIsDisplayed(2);
+}
+
+bool Process::FileDescriptorIsDisplayed(int fd) {
+ return GetFileType((HANDLE)_get_osfhandle(fd)) == FILE_TYPE_CHAR;
}
unsigned Process::StandardOutColumns() {
diff --git a/lib/System/Win32/Program.inc b/lib/System/Win32/Program.inc
index 49086b8..a69826f 100644
--- a/lib/System/Win32/Program.inc
+++ b/lib/System/Win32/Program.inc
@@ -22,9 +22,32 @@
//=== and must not be UNIX code
//===----------------------------------------------------------------------===//
+namespace {
+ struct Win32ProcessInfo {
+ HANDLE hProcess;
+ DWORD dwProcessId;
+ };
+}
+
namespace llvm {
using namespace sys;
+Program::Program() : Data_(0) {}
+
+Program::~Program() {
+ if (Data_) {
+ Win32ProcessInfo* wpi = reinterpret_cast<Win32ProcessInfo*>(Data_);
+ CloseHandle(wpi->hProcess);
+ delete wpi;
+ Data_ = 0;
+ }
+}
+
+unsigned Program::GetPid() const {
+ Win32ProcessInfo* wpi = reinterpret_cast<Win32ProcessInfo*>(Data_);
+ return wpi->dwProcessId;
+}
+
// This function just uses the PATH environment variable to find the program.
Path
Program::FindProgramByName(const std::string& progName) {
@@ -82,7 +105,7 @@ static HANDLE RedirectIO(const Path *path, int fd, std::string* ErrMsg) {
if (path->isEmpty())
fname = "NUL";
else
- fname = path->toString().c_str();
+ fname = path->c_str();
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
@@ -109,29 +132,41 @@ static HANDLE RedirectIO(const Path *path, int fd, std::string* ErrMsg) {
DWORD cbJobObjectInfoLength);
#endif
-int
-Program::ExecuteAndWait(const Path& path,
- const char** args,
- const char** envp,
- const Path** redirects,
- unsigned secondsToWait,
- unsigned memoryLimit,
- std::string* ErrMsg) {
+/// ArgNeedsQuotes - Check whether argument needs to be quoted when calling
+/// CreateProcess.
+static bool ArgNeedsQuotes(const char *Str) {
+ return Str[0] == '\0' || strchr(Str, ' ') != 0;
+}
+
+bool
+Program::Execute(const Path& path,
+ const char** args,
+ const char** envp,
+ const Path** redirects,
+ unsigned memoryLimit,
+ std::string* ErrMsg) {
+ if (Data_) {
+ Win32ProcessInfo* wpi = reinterpret_cast<Win32ProcessInfo*>(Data_);
+ CloseHandle(wpi->hProcess);
+ delete wpi;
+ Data_ = 0;
+ }
+
if (!path.canExecute()) {
if (ErrMsg)
*ErrMsg = "program not executable";
- return -1;
+ return false;
}
// Windows wants a command line, not an array of args, to pass to the new
// process. We have to concatenate them all, while quoting the args that
- // have embedded spaces.
+ // have embedded spaces (or are empty).
// First, determine the length of the command line.
unsigned len = 0;
for (unsigned i = 0; args[i]; i++) {
len += strlen(args[i]) + 1;
- if (strchr(args[i], ' '))
+ if (ArgNeedsQuotes(args[i]))
len += 2;
}
@@ -142,7 +177,7 @@ Program::ExecuteAndWait(const Path& path,
for (unsigned i = 0; args[i]; i++) {
const char *arg = args[i];
size_t len = strlen(arg);
- bool needsQuoting = strchr(arg, ' ') != 0;
+ bool needsQuoting = ArgNeedsQuotes(arg);
if (needsQuoting)
*p++ = '"';
memcpy(p, arg, len);
@@ -195,13 +230,13 @@ Program::ExecuteAndWait(const Path& path,
si.hStdInput = RedirectIO(redirects[0], 0, ErrMsg);
if (si.hStdInput == INVALID_HANDLE_VALUE) {
MakeErrMsg(ErrMsg, "can't redirect stdin");
- return -1;
+ return false;
}
si.hStdOutput = RedirectIO(redirects[1], 1, ErrMsg);
if (si.hStdOutput == INVALID_HANDLE_VALUE) {
CloseHandle(si.hStdInput);
MakeErrMsg(ErrMsg, "can't redirect stdout");
- return -1;
+ return false;
}
if (redirects[1] && redirects[2] && *(redirects[1]) == *(redirects[2])) {
// If stdout and stderr should go to the same place, redirect stderr
@@ -216,7 +251,7 @@ Program::ExecuteAndWait(const Path& path,
CloseHandle(si.hStdInput);
CloseHandle(si.hStdOutput);
MakeErrMsg(ErrMsg, "can't redirect stderr");
- return -1;
+ return false;
}
}
}
@@ -237,16 +272,18 @@ Program::ExecuteAndWait(const Path& path,
CloseHandle(si.hStdError);
// Now return an error if the process didn't get created.
- if (!rc)
- {
+ if (!rc) {
SetLastError(err);
MakeErrMsg(ErrMsg, std::string("Couldn't execute program '") +
- path.toString() + "'");
- return -1;
+ path.str() + "'");
+ return false;
}
+ Win32ProcessInfo* wpi = new Win32ProcessInfo;
+ wpi->hProcess = pi.hProcess;
+ wpi->dwProcessId = pi.dwProcessId;
+ Data_ = wpi;
// 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.
@@ -270,39 +307,68 @@ Program::ExecuteAndWait(const Path& path,
MakeErrMsg(ErrMsg, std::string("Unable to set memory limit"));
TerminateProcess(pi.hProcess, 1);
WaitForSingleObject(pi.hProcess, INFINITE);
- return -1;
+ return false;
}
}
- // Wait for it to terminate.
+ return true;
+}
+
+int
+Program::Wait(unsigned secondsToWait,
+ std::string* ErrMsg) {
+ if (Data_ == 0) {
+ MakeErrMsg(ErrMsg, "Process not started!");
+ return -1;
+ }
+
+ Win32ProcessInfo* wpi = reinterpret_cast<Win32ProcessInfo*>(Data_);
+ HANDLE hProcess = wpi->hProcess;
+
+ // Wait for the process to terminate.
DWORD millisecondsToWait = INFINITE;
if (secondsToWait > 0)
millisecondsToWait = secondsToWait * 1000;
- if (WaitForSingleObject(pi.hProcess, millisecondsToWait) == WAIT_TIMEOUT) {
- if (!TerminateProcess(pi.hProcess, 1)) {
- MakeErrMsg(ErrMsg, std::string("Failed to terminate timed-out program '")
- + path.toString() + "'");
+ if (WaitForSingleObject(hProcess, millisecondsToWait) == WAIT_TIMEOUT) {
+ if (!TerminateProcess(hProcess, 1)) {
+ MakeErrMsg(ErrMsg, "Failed to terminate timed-out program.");
return -1;
}
- WaitForSingleObject(pi.hProcess, INFINITE);
+ WaitForSingleObject(hProcess, INFINITE);
}
// Get its exit status.
DWORD status;
- rc = GetExitCodeProcess(pi.hProcess, &status);
- err = GetLastError();
+ BOOL rc = GetExitCodeProcess(hProcess, &status);
+ DWORD err = GetLastError();
if (!rc) {
SetLastError(err);
- MakeErrMsg(ErrMsg, std::string("Failed getting status for program '") +
- path.toString() + "'");
+ MakeErrMsg(ErrMsg, "Failed getting status for program.");
return -1;
}
return status;
}
+bool
+Program::Kill(std::string* ErrMsg) {
+ if (Data_ == 0) {
+ MakeErrMsg(ErrMsg, "Process not started!");
+ return true;
+ }
+
+ Win32ProcessInfo* wpi = reinterpret_cast<Win32ProcessInfo*>(Data_);
+ HANDLE hProcess = wpi->hProcess;
+ if (TerminateProcess(hProcess, 1) == 0) {
+ MakeErrMsg(ErrMsg, "The process couldn't be killed!");
+ return true;
+ }
+
+ return false;
+}
+
bool Program::ChangeStdinToBinary(){
int result = _setmode( _fileno(stdin), _O_BINARY );
return result == -1;
diff --git a/lib/System/Win32/Signals.inc b/lib/System/Win32/Signals.inc
index 3a8f77e..dba2218 100644
--- a/lib/System/Win32/Signals.inc
+++ b/lib/System/Win32/Signals.inc
@@ -43,6 +43,9 @@ static std::vector<llvm::sys::Path> *FilesToRemove = NULL;
static std::vector<std::pair<void(*)(void*), void*> > *CallBacksToRun = 0;
static bool RegisteredUnhandledExceptionFilter = false;
static bool CleanupExecuted = false;
+#ifdef _MSC_VER
+static bool ExitOnUnhandledExceptions = false;
+#endif
static PTOP_LEVEL_EXCEPTION_FILTER OldFilter = NULL;
// Windows creates a new thread to execute the console handler when an event
@@ -57,8 +60,38 @@ namespace llvm {
//=== and must not be UNIX code
//===----------------------------------------------------------------------===//
+#ifdef _MSC_VER
+/// CRTReportHook - Function called on a CRT debugging event.
+static int CRTReportHook(int ReportType, char *Message, int *Return) {
+ // Don't cause a DebugBreak() on return.
+ if (Return)
+ *Return = 0;
+
+ switch (ReportType) {
+ default:
+ case _CRT_ASSERT:
+ fprintf(stderr, "CRT assert: %s\n", Message);
+ // FIXME: Is there a way to just crash? Perhaps throw to the unhandled
+ // exception code? Perhaps SetErrorMode() handles this.
+ _exit(3);
+ break;
+ case _CRT_ERROR:
+ fprintf(stderr, "CRT error: %s\n", Message);
+ // FIXME: Is there a way to just crash? Perhaps throw to the unhandled
+ // exception code? Perhaps SetErrorMode() handles this.
+ _exit(3);
+ break;
+ case _CRT_WARN:
+ fprintf(stderr, "CRT warn: %s\n", Message);
+ break;
+ }
+
+ // Don't call _CrtDbgReport.
+ return TRUE;
+}
+#endif
-static void RegisterHandler() {
+static void RegisterHandler() {
if (RegisteredUnhandledExceptionFilter) {
EnterCriticalSection(&CriticalSection);
return;
@@ -76,6 +109,14 @@ static void RegisterHandler() {
OldFilter = SetUnhandledExceptionFilter(LLVMUnhandledExceptionFilter);
SetConsoleCtrlHandler(LLVMConsoleCtrlHandler, TRUE);
+ // Environment variable to disable any kind of crash dialog.
+#ifdef _MSC_VER
+ if (getenv("LLVM_DISABLE_CRT_DEBUG")) {
+ _CrtSetReportHook(CRTReportHook);
+ ExitOnUnhandledExceptions = true;
+ }
+#endif
+
// IMPORTANT NOTE: Caller must call LeaveCriticalSection(&CriticalSection) or
// else multi-threading problems will ensue.
}
@@ -136,10 +177,7 @@ static void Cleanup() {
if (FilesToRemove != NULL)
while (!FilesToRemove->empty()) {
- try {
- FilesToRemove->back().eraseFromDisk();
- } catch (...) {
- }
+ FilesToRemove->back().eraseFromDisk();
FilesToRemove->pop_back();
}
@@ -238,6 +276,11 @@ static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) {
assert(0 && "Crashed in LLVMUnhandledExceptionFilter");
}
+#ifdef _MSC_VER
+ if (ExitOnUnhandledExceptions)
+ _exit(-3);
+#endif
+
// Allow dialog box to pop up allowing choice to start debugger.
if (OldFilter)
return (*OldFilter)(ep);
diff --git a/lib/System/Win32/TimeValue.inc b/lib/System/Win32/TimeValue.inc
index 0ca87d4..e37f111 100644
--- a/lib/System/Win32/TimeValue.inc
+++ b/lib/System/Win32/TimeValue.inc
@@ -30,7 +30,7 @@ TimeValue TimeValue::now() {
return t;
}
-std::string TimeValue::toString() const {
+std::string TimeValue::str() const {
#ifdef __MINGW32__
// This ban may be lifted by either:
// (i) a future MinGW version other than 1.0 inherents the __time64_t type, or
OpenPOWER on IntegriCloud