mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 846298 - Misc cleanups to the write poisoning base/OS split. r=BenWa.
This commit is contained in:
parent
1934177bf8
commit
4a0c9499e8
@ -30,7 +30,43 @@
|
||||
#endif
|
||||
using namespace mozilla;
|
||||
|
||||
namespace mozilla {
|
||||
namespace {
|
||||
struct DebugFDAutoLockTraits {
|
||||
typedef PRLock *type;
|
||||
const static type empty() {
|
||||
return nullptr;
|
||||
}
|
||||
const static void release(type aL) {
|
||||
PR_Unlock(aL);
|
||||
}
|
||||
};
|
||||
|
||||
class DebugFDAutoLock : public Scoped<DebugFDAutoLockTraits> {
|
||||
static PRLock *Lock;
|
||||
public:
|
||||
static void Clear();
|
||||
static PRLock *getDebugFDsLock() {
|
||||
// On windows this static is not thread safe, but we know that the first
|
||||
// call is from
|
||||
// * An early registration of a debug FD or
|
||||
// * The call to InitWritePoisoning.
|
||||
// Since the early debug FDs are logs created early in the main thread
|
||||
// and no writes are trapped before InitWritePoisoning, we are safe.
|
||||
static bool Initialized = false;
|
||||
if (!Initialized) {
|
||||
Lock = PR_NewLock();
|
||||
Initialized = true;
|
||||
}
|
||||
|
||||
// We have to use something lower level than a mutex. If we don't, we
|
||||
// can get recursive in here when called from logging a call to free.
|
||||
return Lock;
|
||||
}
|
||||
|
||||
DebugFDAutoLock() : Scoped<DebugFDAutoLockTraits>(getDebugFDsLock()) {
|
||||
PR_Lock(get());
|
||||
}
|
||||
};
|
||||
|
||||
PRLock *DebugFDAutoLock::Lock;
|
||||
void DebugFDAutoLock::Clear() {
|
||||
@ -48,22 +84,6 @@ std::vector<int>& getDebugFDs() {
|
||||
return *DebugFDs;
|
||||
}
|
||||
|
||||
void InitWritePoisoning()
|
||||
{
|
||||
// Call to make sure it is initialized.
|
||||
DebugFDAutoLock::getDebugFDsLock();
|
||||
|
||||
nsCOMPtr<nsIFile> mozFile;
|
||||
NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(mozFile));
|
||||
if (mozFile) {
|
||||
nsAutoCString nativePath;
|
||||
nsresult rv = mozFile->GetNativePath(nativePath);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
sProfileDirectory = PL_strdup(nativePath.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This a wrapper over a file descriptor that provides a Printf method and
|
||||
// computes the sha1 of the data that passes through it.
|
||||
class SHA1Stream
|
||||
@ -107,6 +127,40 @@ static void RecordStackWalker(void *aPC, void *aSP, void *aClosure)
|
||||
stack->push_back(reinterpret_cast<uintptr_t>(aPC));
|
||||
}
|
||||
|
||||
|
||||
enum PoisonState {
|
||||
POISON_UNINITIALIZED = 0,
|
||||
POISON_ON,
|
||||
POISON_OFF
|
||||
};
|
||||
|
||||
// POISON_OFF has two consequences
|
||||
// * It prevents PoisonWrite from patching the write functions.
|
||||
// * If the patching has already been done, it prevents AbortOnBadWrite from
|
||||
// asserting. Note that not all writes use AbortOnBadWrite at this point
|
||||
// (aio_write for example), so disabling writes after patching doesn't
|
||||
// completely undo it.
|
||||
PoisonState sPoisoningState = POISON_UNINITIALIZED;
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
void InitWritePoisoning()
|
||||
{
|
||||
// Call to make sure it is initialized.
|
||||
DebugFDAutoLock::getDebugFDsLock();
|
||||
|
||||
nsCOMPtr<nsIFile> mozFile;
|
||||
NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(mozFile));
|
||||
if (mozFile) {
|
||||
nsAutoCString nativePath;
|
||||
nsresult rv = mozFile->GetNativePath(nativePath);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
sProfileDirectory = PL_strdup(nativePath.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ValidWriteAssert(bool ok)
|
||||
{
|
||||
if (gShutdownChecks == SCM_CRASH && !ok) {
|
||||
@ -207,20 +261,6 @@ bool ValidWriteAssert(bool ok)
|
||||
return false;
|
||||
}
|
||||
|
||||
enum PoisonState {
|
||||
POISON_UNINITIALIZED = 0,
|
||||
POISON_ON,
|
||||
POISON_OFF
|
||||
};
|
||||
|
||||
// POISON_OFF has two consequences
|
||||
// * It prevents PoisonWrite from patching the write functions.
|
||||
// * If the patching has already been done, it prevents AbortOnBadWrite from
|
||||
// asserting. Note that not all writes use AbortOnBadWrite at this point
|
||||
// (aio_write for example), so disabling writes after patching doesn't
|
||||
// completely undo it.
|
||||
PoisonState sPoisoningState = POISON_UNINITIALIZED;
|
||||
|
||||
void DisableWritePoisoning() {
|
||||
if (sPoisoningState != POISON_ON)
|
||||
return;
|
||||
@ -247,6 +287,13 @@ bool PoisonWriteEnabled()
|
||||
return sPoisoningState == POISON_ON;
|
||||
}
|
||||
|
||||
bool IsDebugFD(int fd) {
|
||||
DebugFDAutoLock lockedScope;
|
||||
|
||||
std::vector<int> &Vec = getDebugFDs();
|
||||
return std::find(Vec.begin(), Vec.end(), fd) != Vec.end();
|
||||
}
|
||||
|
||||
} // mozilla
|
||||
|
||||
extern "C" {
|
||||
|
@ -17,53 +17,9 @@
|
||||
#include "mozilla/Scoped.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
||||
struct DebugFDAutoLockTraits {
|
||||
typedef PRLock *type;
|
||||
const static type empty() {
|
||||
return nullptr;
|
||||
}
|
||||
const static void release(type aL) {
|
||||
PR_Unlock(aL);
|
||||
}
|
||||
};
|
||||
|
||||
class DebugFDAutoLock : public Scoped<DebugFDAutoLockTraits> {
|
||||
static PRLock *Lock;
|
||||
public:
|
||||
static void Clear();
|
||||
static PRLock *getDebugFDsLock() {
|
||||
// On windows this static is not thread safe, but we know that the first
|
||||
// call is from
|
||||
// * An early registration of a debug FD or
|
||||
// * The call to InitWritePoisoning.
|
||||
// Since the early debug FDs are logs created early in the main thread
|
||||
// and no writes are trapped before InitWritePoisoning, we are safe.
|
||||
static bool Initialized = false;
|
||||
if (!Initialized) {
|
||||
Lock = PR_NewLock();
|
||||
Initialized = true;
|
||||
}
|
||||
|
||||
// We have to use something lower level than a mutex. If we don't, we
|
||||
// can get recursive in here when called from logging a call to free.
|
||||
return Lock;
|
||||
}
|
||||
|
||||
DebugFDAutoLock() : Scoped<DebugFDAutoLockTraits>(getDebugFDsLock()) {
|
||||
PR_Lock(get());
|
||||
}
|
||||
};
|
||||
|
||||
bool PoisonWriteEnabled();
|
||||
bool ValidWriteAssert(bool ok);
|
||||
void BaseCleanup();
|
||||
// This method should always be called with the debugFDs lock.
|
||||
// Note: MSVC Local static is NOT thread safe
|
||||
// http://stackoverflow.com/questions/10585928/is-static-init-thread-safe-with-vc2010
|
||||
std::vector<int>& getDebugFDs();
|
||||
|
||||
bool IsDebugFD(int fd);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -175,14 +175,9 @@ void AbortOnBadWrite(int fd, const void *wbuf, size_t count) {
|
||||
if (IsIPCWrite(fd, buf))
|
||||
return;
|
||||
|
||||
{
|
||||
DebugFDAutoLock lockedScope;
|
||||
|
||||
// Debugging FDs are OK
|
||||
std::vector<int> &Vec = getDebugFDs();
|
||||
if (std::find(Vec.begin(), Vec.end(), fd) != Vec.end())
|
||||
if (IsDebugFD(fd))
|
||||
return;
|
||||
}
|
||||
|
||||
// For writev we pass NULL in wbuf. We should only get here from
|
||||
// dbm, and it uses write, so assert that we have wbuf.
|
||||
|
Loading…
Reference in New Issue
Block a user