Skip to content

Commit

Permalink
Support/Windows: Cleanup scoped handles.
Browse files Browse the repository at this point in the history
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@146362 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
Bigcheese committed Dec 12, 2011
1 parent 48b0bbf commit 1dd2ee7
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 59 deletions.
4 changes: 3 additions & 1 deletion lib/Support/PathV2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -753,7 +753,9 @@ error_code remove_all_r(StringRef path, file_type ft, uint32_t &count) {
if (ft == file_type::directory_file) {
// This code would be a lot better with exceptions ;/.
error_code ec;
for (directory_iterator i(path, ec), e; i != e; i.increment(ec)) {
directory_iterator i(path, ec);
if (ec) return ec;
for (directory_iterator e; i != e; i.increment(ec)) {
if (ec) return ec;
file_status st;
if (error_code ec = i->status(st)) return ec;
Expand Down
23 changes: 6 additions & 17 deletions lib/Support/Windows/PathV2.inc
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
//===----------------------------------------------------------------------===//

#include "Windows.h"
#include <wincrypt.h>
#include <fcntl.h>
#include <io.h>
#include <sys/stat.h>
Expand Down Expand Up @@ -112,14 +111,6 @@ namespace {
return success;
}

// Forwarder for ScopedHandle.
BOOL WINAPI CryptReleaseContext(HCRYPTPROV Provider) {
return ::CryptReleaseContext(Provider, 0);
}

typedef ScopedHandle<HCRYPTPROV, uintptr_t(-1),
BOOL (WINAPI*)(HCRYPTPROV), CryptReleaseContext>
ScopedCryptContext;
bool is_separator(const wchar_t value) {
switch (value) {
case L'\\':
Expand Down Expand Up @@ -372,7 +363,7 @@ error_code equivalent(const Twine &A, const Twine &B, bool &result) {
if (error_code ec = UTF8ToUTF16(a, wide_a)) return ec;
if (error_code ec = UTF8ToUTF16(b, wide_b)) return ec;

AutoHandle HandleB(
ScopedFileHandle HandleB(
::CreateFileW(wide_b.begin(),
0,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
Expand All @@ -381,7 +372,7 @@ error_code equivalent(const Twine &A, const Twine &B, bool &result) {
FILE_FLAG_BACKUP_SEMANTICS,
0));

AutoHandle HandleA(
ScopedFileHandle HandleA(
::CreateFileW(wide_a.begin(),
0,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
Expand All @@ -391,13 +382,11 @@ error_code equivalent(const Twine &A, const Twine &B, bool &result) {
0));

// If both handles are invalid, it's an error.
if (HandleA == INVALID_HANDLE_VALUE &&
HandleB == INVALID_HANDLE_VALUE)
if (!HandleA && !HandleB)
return windows_error(::GetLastError());

// If only one is invalid, it's false.
if (HandleA == INVALID_HANDLE_VALUE &&
HandleB == INVALID_HANDLE_VALUE) {
if (!HandleA || !HandleB) {
result = false;
return success;
}
Expand Down Expand Up @@ -488,15 +477,15 @@ error_code status(const Twine &path, file_status &result) {

// Handle reparse points.
if (attr & FILE_ATTRIBUTE_REPARSE_POINT) {
AutoHandle h(
ScopedFileHandle h(
::CreateFileW(path_utf16.begin(),
0, // Attributes only.
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
0));
if (h == INVALID_HANDLE_VALUE)
if (!h)
goto handle_status_error;
}

Expand Down
6 changes: 3 additions & 3 deletions lib/Support/Windows/Program.inc
Original file line number Diff line number Diff line change
Expand Up @@ -299,14 +299,14 @@ Program::Execute(const Path& path,
Data_ = wpi;

// Make sure these get closed no matter what.
AutoHandle hThread(pi.hThread);
ScopedCommonHandle hThread(pi.hThread);

// Assign the process to a job if a memory limit is defined.
AutoHandle hJob(0);
ScopedJobHandle hJob;
if (memoryLimit != 0) {
hJob = CreateJobObject(0, 0);
bool success = false;
if (hJob != 0) {
if (hJob) {
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli;
memset(&jeli, 0, sizeof(jeli));
jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_PROCESS_MEMORY;
Expand Down
106 changes: 68 additions & 38 deletions lib/Support/Windows/Windows.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

#include "llvm/Config/config.h" // Get build system configuration settings
#include <windows.h>
#include <wincrypt.h>
#include <shlobj.h>
#include <cassert>
#include <string>
Expand All @@ -41,70 +42,99 @@ inline bool MakeErrMsg(std::string* ErrMsg, const std::string& prefix) {
return true;
}

class AutoHandle {
HANDLE handle;
template <typename HandleTraits>
class ScopedHandle {
typedef typename HandleTraits::handle_type handle_type;
handle_type Handle;

ScopedHandle(const ScopedHandle &other); // = delete;
void operator=(const ScopedHandle &other); // = delete;
public:
AutoHandle(HANDLE h) : handle(h) {}
ScopedHandle()
: Handle(HandleTraits::GetInvalid()) {}

explicit ScopedHandle(handle_type h)
: Handle(h) {}

~AutoHandle() {
if (handle)
CloseHandle(handle);
~ScopedHandle() {
if (HandleTraits::IsValid(Handle))
HandleTraits::Close(Handle);
}

operator HANDLE() {
return handle;
handle_type take() {
handle_type t = Handle;
Handle = HandleTraits::GetInvalid();
return t;
}

AutoHandle &operator=(HANDLE h) {
handle = h;
ScopedHandle &operator=(handle_type h) {
if (HandleTraits::IsValid(Handle))
HandleTraits::Close(Handle);
Handle = h;
return *this;
}

// True if Handle is valid.
operator bool() const {
return HandleTraits::IsValid(Handle) ? true : false;
}

operator handle_type() const {
return Handle;
}
};

template <class HandleType, uintptr_t InvalidHandle,
class DeleterType, DeleterType D>
class ScopedHandle {
HandleType Handle;
struct CommonHandleTraits {
typedef HANDLE handle_type;

public:
ScopedHandle() : Handle(InvalidHandle) {}
ScopedHandle(HandleType handle) : Handle(handle) {}
static handle_type GetInvalid() {
return INVALID_HANDLE_VALUE;
}

~ScopedHandle() {
if (Handle != HandleType(InvalidHandle))
D(Handle);
static void Close(handle_type h) {
::CloseHandle(h);
}

HandleType take() {
HandleType temp = Handle;
Handle = HandleType(InvalidHandle);
return temp;
static bool IsValid(handle_type h) {
return h != GetInvalid();
}
};

operator HandleType() const { return Handle; }
struct JobHandleTraits : CommonHandleTraits {
static handle_type GetInvalid() {
return NULL;
}
};

ScopedHandle &operator=(HandleType handle) {
Handle = handle;
return *this;
struct CryptContextTraits : CommonHandleTraits {
typedef HCRYPTPROV handle_type;

static handle_type GetInvalid() {
return 0;
}

typedef void (*unspecified_bool_type)();
static void unspecified_bool_true() {}
static void Close(handle_type h) {
::CryptReleaseContext(h, 0);
}

// True if Handle is valid.
operator unspecified_bool_type() const {
return Handle == HandleType(InvalidHandle) ? 0 : unspecified_bool_true;
static bool IsValid(handle_type h) {
return h != GetInvalid();
}
};

bool operator!() const {
return Handle == HandleType(InvalidHandle);
struct FindHandleTraits : CommonHandleTraits {
static void Close(handle_type h) {
::FindClose(h);
}
};

typedef ScopedHandle<HANDLE, uintptr_t(-1),
BOOL (WINAPI*)(HANDLE), ::FindClose>
ScopedFindHandle;
struct FileHandleTraits : CommonHandleTraits {};

typedef ScopedHandle<CommonHandleTraits> ScopedCommonHandle;
typedef ScopedHandle<FileHandleTraits> ScopedFileHandle;
typedef ScopedHandle<CryptContextTraits> ScopedCryptContext;
typedef ScopedHandle<FindHandleTraits> ScopedFindHandle;
typedef ScopedHandle<JobHandleTraits> ScopedJobHandle;

namespace llvm {
template <class T>
Expand Down

0 comments on commit 1dd2ee7

Please sign in to comment.