xpcom/build/PoisonIOInterposerBase.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/xpcom/build/PoisonIOInterposerBase.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,150 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* vim:set ts=2 sw=2 sts=2 ci et: */
     1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#include "mozilla/Mutex.h"
    1.11 +#include "mozilla/Scoped.h"
    1.12 +
    1.13 +#include <algorithm>
    1.14 +#include <vector>
    1.15 +
    1.16 +#include "PoisonIOInterposer.h"
    1.17 +
    1.18 +// Auxiliary method to convert file descriptors to ids
    1.19 +#if defined(XP_WIN32)
    1.20 +#include <io.h>
    1.21 +inline intptr_t FileDescriptorToID(int aFd) {
    1.22 +  return _get_osfhandle(aFd);
    1.23 +}
    1.24 +#else
    1.25 +inline intptr_t FileDescriptorToID(int aFd) {
    1.26 +  return aFd;
    1.27 +}
    1.28 +#endif /* if not XP_WIN32 */
    1.29 +
    1.30 +using namespace mozilla;
    1.31 +
    1.32 +namespace {
    1.33 +struct DebugFilesAutoLockTraits {
    1.34 +  typedef PRLock *type;
    1.35 +  const static type empty() {
    1.36 +    return nullptr;
    1.37 +  }
    1.38 +  const static void release(type aL) {
    1.39 +    PR_Unlock(aL);
    1.40 +  }
    1.41 +};
    1.42 +
    1.43 +class DebugFilesAutoLock : public Scoped<DebugFilesAutoLockTraits> {
    1.44 +  static PRLock *Lock;
    1.45 +public:
    1.46 +  static void Clear();
    1.47 +  static PRLock *getDebugFileIDsLock() {
    1.48 +    // On windows this static is not thread safe, but we know that the first
    1.49 +    // call is from
    1.50 +    // * An early registration of a debug FD or
    1.51 +    // * The call to InitWritePoisoning.
    1.52 +    // Since the early debug FDs are logs created early in the main thread
    1.53 +    // and no writes are trapped before InitWritePoisoning, we are safe.
    1.54 +    if (!Lock) {
    1.55 +      Lock = PR_NewLock();
    1.56 +    }
    1.57 +
    1.58 +    // We have to use something lower level than a mutex. If we don't, we
    1.59 +    // can get recursive in here when called from logging a call to free.
    1.60 +    return Lock;
    1.61 +  }
    1.62 +
    1.63 +  DebugFilesAutoLock() :
    1.64 +    Scoped<DebugFilesAutoLockTraits>(getDebugFileIDsLock()) {
    1.65 +    PR_Lock(get());
    1.66 +  }
    1.67 +};
    1.68 +
    1.69 +PRLock *DebugFilesAutoLock::Lock;
    1.70 +void DebugFilesAutoLock::Clear() {
    1.71 +  MOZ_ASSERT(Lock != nullptr);
    1.72 +  Lock = nullptr;
    1.73 +}
    1.74 +
    1.75 +// Return a vector used to hold the IDs of the current debug files. On unix
    1.76 +// an ID is a file descriptor. On Windows it is a file HANDLE.
    1.77 +std::vector<intptr_t>* getDebugFileIDs() {
    1.78 +  PR_ASSERT_CURRENT_THREAD_OWNS_LOCK(DebugFilesAutoLock::getDebugFileIDsLock());
    1.79 +  // We have to use new as some write happen during static destructors
    1.80 +  // so an static std::vector might be destroyed while we still need it.
    1.81 +  static std::vector<intptr_t> *DebugFileIDs = new std::vector<intptr_t>();
    1.82 +  return DebugFileIDs;
    1.83 +}
    1.84 +
    1.85 +} // anonymous namespace
    1.86 +
    1.87 +namespace mozilla{
    1.88 +
    1.89 +// Auxiliary Method to test if a file descriptor is registered to be ignored
    1.90 +// by the poisoning IO interposer
    1.91 +bool IsDebugFile(intptr_t aFileID) {
    1.92 +  DebugFilesAutoLock lockedScope;
    1.93 +
    1.94 +  std::vector<intptr_t> &Vec = *getDebugFileIDs();
    1.95 +  return std::find(Vec.begin(), Vec.end(), aFileID) != Vec.end();
    1.96 +}
    1.97 +
    1.98 +// Clean-up for the registered debug files.
    1.99 +// We should probably make sure all debug files are unregistered instead.
   1.100 +// But as the poison IO interposer is used for late-write checks we're not
   1.101 +// disabling it at any point yet. So Really no need for this.
   1.102 +//
   1.103 +// void ClearDebugFileRegister() {
   1.104 +//   PRLock *Lock;
   1.105 +//   {
   1.106 +//     DebugFilesAutoLock lockedScope;
   1.107 +//     delete getDebugFileIDs();
   1.108 +//     Lock = DebugFilesAutoLock::getDebugFileIDsLock();
   1.109 +//     DebugFilesAutoLock::Clear();
   1.110 +//   }
   1.111 +//   PR_DestroyLock(Lock);
   1.112 +// }
   1.113 +
   1.114 +} // namespace mozilla
   1.115 +
   1.116 +extern "C" {
   1.117 +
   1.118 +  void MozillaRegisterDebugFD(int fd) {
   1.119 +    intptr_t fileId = FileDescriptorToID(fd);
   1.120 +    DebugFilesAutoLock lockedScope;
   1.121 +    std::vector<intptr_t> &Vec = *getDebugFileIDs();
   1.122 +    MOZ_ASSERT(std::find(Vec.begin(), Vec.end(), fileId) == Vec.end());
   1.123 +    Vec.push_back(fileId);
   1.124 +  }
   1.125 +
   1.126 +  void MozillaRegisterDebugFILE(FILE *f) {
   1.127 +    int fd = fileno(f);
   1.128 +    if (fd == 1 || fd == 2) {
   1.129 +      return;
   1.130 +    }
   1.131 +    MozillaRegisterDebugFD(fd);
   1.132 +  }
   1.133 +
   1.134 +  void MozillaUnRegisterDebugFD(int fd) {
   1.135 +    DebugFilesAutoLock lockedScope;
   1.136 +    intptr_t fileId = FileDescriptorToID(fd);
   1.137 +    std::vector<intptr_t> &Vec = *getDebugFileIDs();
   1.138 +    std::vector<intptr_t>::iterator i =
   1.139 +      std::find(Vec.begin(), Vec.end(), fileId);
   1.140 +    MOZ_ASSERT(i != Vec.end());
   1.141 +    Vec.erase(i);
   1.142 +  }
   1.143 +
   1.144 +  void MozillaUnRegisterDebugFILE(FILE *f) {
   1.145 +    int fd = fileno(f);
   1.146 +    if (fd == 1 || fd == 2) {
   1.147 +      return;
   1.148 +    }
   1.149 +    fflush(f);
   1.150 +    MozillaUnRegisterDebugFD(fd);
   1.151 +  }
   1.152 +
   1.153 +}
   1.154 \ No newline at end of file

mercurial