зеркало из https://github.com/mozilla/gecko-dev.git
Merge autoland to mozilla-central. a=merge
This commit is contained in:
Коммит
f637dc5cbd
|
@ -132,7 +132,7 @@ var Policies = {
|
|||
"Certificates": {
|
||||
onBeforeAddons(manager, param) {
|
||||
if ("ImportEnterpriseRoots" in param) {
|
||||
setAndLockPref("security.enterprise_roots.enabled", true);
|
||||
setAndLockPref("security.enterprise_roots.enabled", param.ImportEnterpriseRoots);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
@ -227,9 +227,9 @@ var Policies = {
|
|||
},
|
||||
|
||||
"DisableBuiltinPDFViewer": {
|
||||
onBeforeUIStartup(manager, param) {
|
||||
onBeforeAddons(manager, param) {
|
||||
if (param) {
|
||||
manager.disallowFeature("PDF.js");
|
||||
setAndLockPref("pdfjs.disabled", true);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
@ -744,6 +744,7 @@ var Policies = {
|
|||
method: newEngine.Method,
|
||||
suggestURL: newEngine.SuggestURLTemplate,
|
||||
extensionID: "set-via-policy",
|
||||
queryCharset: "UTF-8",
|
||||
};
|
||||
try {
|
||||
Services.search.addEngineWithDetails(newEngine.Name,
|
||||
|
|
|
@ -37,7 +37,6 @@ support-files =
|
|||
[browser_policy_disable_fxaccounts.js]
|
||||
skip-if = (verify && debug && (os == 'mac'))
|
||||
[browser_policy_disable_masterpassword.js]
|
||||
[browser_policy_disable_pdfjs.js]
|
||||
[browser_policy_disable_pocket.js]
|
||||
[browser_policy_disable_popup_blocker.js]
|
||||
[browser_policy_disable_privatebrowsing.js]
|
||||
|
|
|
@ -53,6 +53,11 @@ const POLICIES_TESTS = [
|
|||
},
|
||||
},
|
||||
|
||||
// POLICY: DisableBuiltinPDFViewer
|
||||
{
|
||||
policies: { "DisableBuiltinPDFViewer": true },
|
||||
lockedPrefs: { "pdfjs.disabled": true },
|
||||
},
|
||||
|
||||
// POLICY: DisableFormHistory
|
||||
{
|
||||
|
@ -113,7 +118,7 @@ const POLICIES_TESTS = [
|
|||
},
|
||||
},
|
||||
|
||||
// POLICY: Certificates
|
||||
// POLICY: Certificates (true)
|
||||
{
|
||||
policies: {
|
||||
"Certificates": {
|
||||
|
@ -125,6 +130,18 @@ const POLICIES_TESTS = [
|
|||
},
|
||||
},
|
||||
|
||||
// POLICY: Certificates (false)
|
||||
{
|
||||
policies: {
|
||||
"Certificates": {
|
||||
"ImportEnterpriseRoots": false,
|
||||
},
|
||||
},
|
||||
lockedPrefs: {
|
||||
"security.enterprise_roots.enabled": false,
|
||||
},
|
||||
},
|
||||
|
||||
// POLICY: InstallAddons.Default (block addon installs)
|
||||
{
|
||||
policies: {
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
const {PdfJs} = ChromeUtils.import("resource://pdf.js/PdfJs.jsm", {});
|
||||
|
||||
add_task(async function test_disable_pdfjs() {
|
||||
is(PdfJs.enabled, true, "PDFjs should be enabled before policy runs");
|
||||
|
||||
await setupPolicyEngineWithJson({
|
||||
"policies": {
|
||||
"DisableBuiltinPDFViewer": true,
|
||||
},
|
||||
});
|
||||
|
||||
is(PdfJs.enabled, false, "PDFjs should be disabled after policy runs");
|
||||
});
|
|
@ -23,6 +23,7 @@ function promiseLocaleChanged() {
|
|||
}
|
||||
|
||||
add_task(async function test_requested_locale() {
|
||||
let originalLocales = Services.locale.requestedLocales;
|
||||
let localePromise = promiseLocaleChanged();
|
||||
await setupPolicyEngineWithJson({
|
||||
"policies": {
|
||||
|
@ -30,4 +31,5 @@ add_task(async function test_requested_locale() {
|
|||
},
|
||||
});
|
||||
await localePromise;
|
||||
Services.locale.requestedLocales = originalLocales;
|
||||
});
|
||||
|
|
|
@ -3248,7 +3248,6 @@ class PDFHandlerInfoWrapper extends InternalHandlerInfoWrapper {
|
|||
}
|
||||
|
||||
get enabled() {
|
||||
return !Services.prefs.getBoolPref(PREF_PDFJS_DISABLED) &&
|
||||
Services.policies.isAllowed("PDF.js");
|
||||
return !Services.prefs.getBoolPref(PREF_PDFJS_DISABLED);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,8 +10,10 @@ ac_add_options --enable-optimize
|
|||
ac_add_options --enable-clang-plugin
|
||||
|
||||
. $topsrcdir/build/win32/mozconfig.vs-latest
|
||||
# Regardless of what mozconfig.vs-latest sets, clang-plugin builds need to use
|
||||
# the Microsoft linker until at least bugs 1414287 and 1427808 are resolved.
|
||||
|
||||
# Regardless of what mozconfig.vs-latest sets, lld-link that comes with the old
|
||||
# clang version used for static analysis fails to link multiple things. So
|
||||
# until bug 1427808 is resolved, use the Microsoft linker.
|
||||
export LINKER=link
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
|
|
@ -11,8 +11,10 @@ ac_add_options --enable-debug
|
|||
ac_add_options --enable-clang-plugin
|
||||
|
||||
. $topsrcdir/build/win32/mozconfig.vs-latest
|
||||
# Regardless of what mozconfig.vs-latest sets, clang-plugin builds need to use
|
||||
# the Microsoft linker until at least bugs 1414287 and 1427808 are resolved.
|
||||
|
||||
# Regardless of what mozconfig.vs-latest sets, lld-link that comes with the old
|
||||
# clang version used for static analysis fails to link multiple things. So
|
||||
# until bug 1427808 is resolved, use the Microsoft linker.
|
||||
export LINKER=link
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
|
|
@ -3,3 +3,6 @@
|
|||
export CC="cl.exe"
|
||||
export CXX="cl.exe"
|
||||
export LINKER="link.exe"
|
||||
|
||||
export HOST_CC=${VSPATH}/VC/bin/Hostx64/x64/cl.exe
|
||||
export HOST_CXX=${VSPATH}/VC/bin/Hostx64/x64/cl.exe
|
||||
|
|
|
@ -3,3 +3,6 @@
|
|||
export CC="cl.exe"
|
||||
export CXX="cl.exe"
|
||||
export LINKER="link.exe"
|
||||
|
||||
export HOST_CC=${VSPATH}/VC/bin/Hostx64/x64/cl.exe
|
||||
export HOST_CXX=${VSPATH}/VC/bin/Hostx64/x64/cl.exe
|
||||
|
|
|
@ -268,10 +268,6 @@ var PdfJs = {
|
|||
* @return {boolean} Whether or not it's enabled.
|
||||
*/
|
||||
get enabled() {
|
||||
if (!Services.policies.isAllowed("PDF.js")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Services.prefs.getBoolPref(PREF_ENABLED_CACHE_INITIALIZED, false)) {
|
||||
// If we just updated, and the cache hasn't been initialized, then we
|
||||
// can't assume a default state, and need to synchronously initialize
|
||||
|
|
|
@ -42,19 +42,23 @@ left instead of right. -->
|
|||
<!ENTITY closeTabs.label "Close Tabs">
|
||||
<!ENTITY closeTabs.accesskey "S">
|
||||
<!ENTITY pinSelectedTabs.label "Pin Tabs">
|
||||
<!-- Pin Tab and Pin Selected Tabs have the same accesskey
|
||||
but will never be visible at the same time. -->
|
||||
<!-- LOCALIZATION NOTE(pinTab.accesskey, pinSelectedTabs.accesskey,
|
||||
unpinTab.accesskey, unpinSelectedTabs.accesskey): These share the
|
||||
same accesskey but will never be visible at the same time. -->
|
||||
<!ENTITY pinSelectedTabs.accesskey "P">
|
||||
<!ENTITY unpinSelectedTabs.label "Unpin Tabs">
|
||||
<!-- Unpin Tab and Unpin Selected Tabs have the same accesskey
|
||||
but will never be visible at the same time. -->
|
||||
<!ENTITY unpinSelectedTabs.accesskey "b">
|
||||
<!-- LOCALIZATION NOTE(pinTab.accesskey, pinSelectedTabs.accesskey,
|
||||
unpinTab.accesskey, unpinSelectedTabs.accesskey): These share the
|
||||
same accesskey but will never be visible at the same time. -->
|
||||
<!ENTITY unpinSelectedTabs.accesskey "p">
|
||||
<!-- LOCALIZATION NOTE(reloadTab.label, reloadTabs.label): have the same accesskey
|
||||
but will never be visible at the same time. -->
|
||||
<!ENTITY reloadTabs.label "Reload Tabs">
|
||||
<!ENTITY reloadTabs.accesskey "R">
|
||||
<!ENTITY bookmarkSelectedTabs.label "Bookmark Tabs…">
|
||||
<!ENTITY bookmarkSelectedTabs.accesskey "k">
|
||||
<!-- LOCALIZATION NOTE(bookmarkTab.accesskey, bookmarkSelectedTabs.accesskey):
|
||||
These items have the same accesskey but will never be visible at the same time. -->
|
||||
<!ENTITY bookmarkSelectedTabs.accesskey "B">
|
||||
|
||||
<!-- LOCALIZATION NOTE (pinTab.label, unpinTab.label): "Pin" is being
|
||||
used as a metaphor for expressing the fact that these tabs are "pinned" to the
|
||||
|
@ -62,9 +66,15 @@ left edge of the tabstrip. Really we just want the string to express the idea
|
|||
that this is a lightweight and reversible action that keeps your tab where you
|
||||
can reach it easily. -->
|
||||
<!ENTITY pinTab.label "Pin Tab">
|
||||
<!-- LOCALIZATION NOTE(pinTab.accesskey, pinSelectedTabs.accesskey,
|
||||
unpinTab.accesskey, unpinSelectedTabs.accesskey): These share the
|
||||
same accesskey but will never be visible at the same time. -->
|
||||
<!ENTITY pinTab.accesskey "P">
|
||||
<!ENTITY unpinTab.label "Unpin Tab">
|
||||
<!ENTITY unpinTab.accesskey "b">
|
||||
<!-- LOCALIZATION NOTE(pinTab.accesskey, pinSelectedTabs.accesskey,
|
||||
unpinTab.accesskey, unpinSelectedTabs.accesskey): These share the
|
||||
same accesskey but will never be visible at the same time. -->
|
||||
<!ENTITY unpinTab.accesskey "p">
|
||||
<!ENTITY sendPageToDevice.label "Send Page to Device">
|
||||
<!ENTITY sendPageToDevice.accesskey "n">
|
||||
<!ENTITY sendLinkToDevice.label "Send Link to Device">
|
||||
|
@ -84,7 +94,9 @@ These two items have the same accesskey but will never be visible at the same ti
|
|||
<!ENTITY reopenInContainer.label "Reopen in Container">
|
||||
<!ENTITY reopenInContainer.accesskey "e">
|
||||
<!ENTITY bookmarkTab.label "Bookmark Tab">
|
||||
<!ENTITY bookmarkTab.accesskey "T">
|
||||
<!-- LOCALIZATION NOTE(bookmarkTab.accesskey, bookmarkSelectedTabs.accesskey):
|
||||
These items have the same accesskey but will never be visible at the same time. -->
|
||||
<!ENTITY bookmarkTab.accesskey "B">
|
||||
<!ENTITY undoCloseTab.label "Undo Close Tab">
|
||||
<!ENTITY undoCloseTab.accesskey "U">
|
||||
<!ENTITY closeTab.label "Close Tab">
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
{
|
||||
"llvm_revision": "317840",
|
||||
"stages": "3",
|
||||
"build_libcxx": false,
|
||||
"build_type": "Release",
|
||||
"assertions": false,
|
||||
"llvm_repo": "https://llvm.org/svn/llvm-project/llvm/trunk",
|
||||
"clang_repo": "https://llvm.org/svn/llvm-project/cfe/trunk",
|
||||
"lld_repo": "https://llvm.org/svn/llvm-project/lld/trunk",
|
||||
"compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/trunk",
|
||||
"libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/trunk",
|
||||
"python_path": "c:/mozilla-build/python/python.exe",
|
||||
"cc": "cl.exe",
|
||||
"cxx": "cl.exe",
|
||||
"patches": [
|
||||
"r318309.patch",
|
||||
"r320462.patch",
|
||||
"msvc-host-x64.patch",
|
||||
"aarch64-vastart-checking.patch",
|
||||
"loosen-msvc-detection.patch"
|
||||
]
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
When looking for a linker, 32-bit clang-cl.exe wants to use the 32-bit-native link.exe located in Hostx86/x86, but this executable does not exist in our releng package, because we only use 64-bit-host toolchains.
|
||||
|
||||
This patch makes clang-cl use the Hostx64/x86 linker instead. Ideally we wouldn't be using 32-bit clang-cl.exe in the first place. Bug 1414287 is on file to do so and remove this hack.
|
||||
|
||||
diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp
|
||||
--- a/clang/lib/Driver/ToolChains/MSVC.cpp
|
||||
+++ b/clang/lib/Driver/ToolChains/MSVC.cpp
|
||||
@@ -817,8 +816,7 @@
|
||||
switch (Type) {
|
||||
case SubDirectoryType::Bin:
|
||||
if (VSLayout == ToolsetLayout::VS2017OrNewer) {
|
||||
- const bool HostIsX64 =
|
||||
- llvm::Triple(llvm::sys::getProcessTriple()).isArch64Bit();
|
||||
+ const bool HostIsX64 = true;
|
||||
const char *const HostName = HostIsX64 ? "HostX64" : "HostX86";
|
||||
llvm::sys::path::append(Path, "bin", HostName, SubdirName);
|
||||
} else { // OlderVS or DevDivInternal
|
|
@ -132,6 +132,13 @@ def search_path(mozilla_dir, packages_txt):
|
|||
except Exception:
|
||||
pass
|
||||
|
||||
if package[0] in ('windows', '!windows'):
|
||||
for_win = not package[0].startswith('!')
|
||||
is_win = sys.platform == 'win32'
|
||||
if is_win == for_win:
|
||||
for path in handle_package(package[1:]):
|
||||
yield path
|
||||
|
||||
if package[0] == 'packages.txt':
|
||||
assert len(package) == 2
|
||||
for p in search_path(mozilla_dir, package[1]):
|
||||
|
|
|
@ -22,14 +22,16 @@ mozilla.pth:third_party/python/gyp/pylib
|
|||
mozilla.pth:third_party/python/python-hglib
|
||||
mozilla.pth:third_party/python/pluggy
|
||||
mozilla.pth:third_party/python/jsmin
|
||||
optional:setup.py:third_party/python/psutil:build_ext:--inplace
|
||||
mozilla.pth:third_party/python/psutil
|
||||
!windows:optional:setup.py:third_party/python/psutil:build_ext:--inplace
|
||||
!windows:mozilla.pth:third_party/python/psutil
|
||||
windows:mozilla.pth:third_party/python/psutil-cp27-none-win_amd64
|
||||
mozilla.pth:third_party/python/pylru
|
||||
mozilla.pth:third_party/python/which
|
||||
mozilla.pth:third_party/python/pystache
|
||||
mozilla.pth:third_party/python/pyyaml/lib
|
||||
mozilla.pth:third_party/python/requests
|
||||
mozilla.pth:third_party/python/requests-unixsocket
|
||||
mozilla.pth:third_party/python/scandir
|
||||
mozilla.pth:third_party/python/slugid
|
||||
mozilla.pth:third_party/python/py
|
||||
mozilla.pth:third_party/python/pytest/src
|
||||
|
|
|
@ -9,7 +9,7 @@ if [ -d "${VSPATH}" ]; then
|
|||
export WINDOWSSDKDIR="${VSWINPATH}/SDK"
|
||||
export WIN32_REDIST_DIR="${VSPATH}/VC/redist/x86/Microsoft.VC141.CRT"
|
||||
export WIN_UCRT_REDIST_DIR="${VSPATH}/SDK/Redist/ucrt/DLLs/x86"
|
||||
export WIN_DIA_SDK_BIN_DIR="${VSPATH}/DIA SDK/bin"
|
||||
export WIN_DIA_SDK_BIN_DIR="${VSPATH}/DIA SDK/bin/amd64"
|
||||
|
||||
export PATH="${VSPATH}/VC/bin/Hostx86/x86:${VSPATH}/VC/bin/Hostx64/x86:${VSPATH}/VC/bin/Hostx64/x64:${VSPATH}/SDK/bin/10.0.17134.0/x64:${WIN_DIA_SDK_BIN_DIR}:${PATH}"
|
||||
export PATH="${VSPATH}/VC/redist/x86/Microsoft.VC141.CRT:${VSPATH}/SDK/Redist/ucrt/DLLs/x86:${PATH}"
|
||||
|
@ -21,6 +21,9 @@ if [ -d "${VSPATH}" ]; then
|
|||
export WIN64_LIB="${VSPATH}/VC/lib/x64:${VSPATH}/VC/atlmfc/lib/x64:${VSPATH}/SDK/Lib/10.0.17134.0/ucrt/x64:${VSPATH}/SDK/Lib/10.0.17134.0/um/x64:${VSPATH}/DIA SDK/lib/amd64"
|
||||
fi
|
||||
|
||||
ac_add_options --target=i686-pc-mingw32
|
||||
ac_add_options --host=x86_64-pc-mingw32
|
||||
|
||||
. $topsrcdir/build/mozconfig.vs-common
|
||||
|
||||
mk_export_correct_style WINDOWSSDKDIR
|
||||
|
|
|
@ -201,6 +201,13 @@ HOST_CFLAGS = $(COMPUTED_HOST_CFLAGS) $(_DEPEND_CFLAGS)
|
|||
HOST_CXXFLAGS = $(COMPUTED_HOST_CXXFLAGS) $(_DEPEND_CFLAGS)
|
||||
HOST_C_LDFLAGS = $(COMPUTED_HOST_C_LDFLAGS)
|
||||
HOST_CXX_LDFLAGS = $(COMPUTED_HOST_CXX_LDFLAGS)
|
||||
# Win32 Cross-builds on win64 need to override LIB when invoking the linker,
|
||||
# which we do for rust through cargo-linker.bat, so we abuse it here.
|
||||
# Ideally, we'd empty LIB and pass -LIBPATH options to the linker somehow but
|
||||
# we don't have this in place for rust, so...
|
||||
ifdef WIN64_CARGO_LINKER
|
||||
HOST_LINKER = $(topobjdir)/build/win64/cargo-linker.bat
|
||||
endif
|
||||
|
||||
ifdef MOZ_LTO
|
||||
ifeq (Darwin,$(OS_TARGET))
|
||||
|
|
|
@ -7966,208 +7966,199 @@ nsContentUtils::TransferableToIPCTransferable(nsITransferable* aTransferable,
|
|||
MOZ_ASSERT((aChild && !aParent) || (!aChild && aParent));
|
||||
|
||||
if (aTransferable) {
|
||||
nsCOMPtr<nsIArray> flavorList;
|
||||
aTransferable->FlavorsTransferableCanExport(getter_AddRefs(flavorList));
|
||||
if (flavorList) {
|
||||
uint32_t flavorCount = 0;
|
||||
flavorList->GetLength(&flavorCount);
|
||||
for (uint32_t j = 0; j < flavorCount; ++j) {
|
||||
nsCOMPtr<nsISupportsCString> flavor = do_QueryElementAt(flavorList, j);
|
||||
if (!flavor) {
|
||||
nsTArray<nsCString> flavorList;
|
||||
aTransferable->FlavorsTransferableCanExport(flavorList);
|
||||
|
||||
for (uint32_t j = 0; j < flavorList.Length(); ++j) {
|
||||
nsCString& flavorStr = flavorList[j];
|
||||
if (!flavorStr.Length()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupports> data;
|
||||
uint32_t dataLen = 0;
|
||||
aTransferable->GetTransferData(flavorStr.get(), getter_AddRefs(data), &dataLen);
|
||||
|
||||
nsCOMPtr<nsISupportsString> text = do_QueryInterface(data);
|
||||
nsCOMPtr<nsISupportsCString> ctext = do_QueryInterface(data);
|
||||
if (text) {
|
||||
nsAutoString dataAsString;
|
||||
text->GetData(dataAsString);
|
||||
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
|
||||
item->flavor() = flavorStr;
|
||||
item->data() = dataAsString;
|
||||
} else if (ctext) {
|
||||
nsAutoCString dataAsString;
|
||||
ctext->GetData(dataAsString);
|
||||
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
|
||||
item->flavor() = flavorStr;
|
||||
|
||||
Shmem dataAsShmem = ConvertToShmem(aChild, aParent, dataAsString);
|
||||
if (!dataAsShmem.IsReadable() || !dataAsShmem.Size<char>()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsAutoCString flavorStr;
|
||||
flavor->GetData(flavorStr);
|
||||
if (!flavorStr.Length()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupports> data;
|
||||
uint32_t dataLen = 0;
|
||||
aTransferable->GetTransferData(flavorStr.get(), getter_AddRefs(data), &dataLen);
|
||||
|
||||
nsCOMPtr<nsISupportsString> text = do_QueryInterface(data);
|
||||
nsCOMPtr<nsISupportsCString> ctext = do_QueryInterface(data);
|
||||
if (text) {
|
||||
nsAutoString dataAsString;
|
||||
text->GetData(dataAsString);
|
||||
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
|
||||
item->flavor() = flavorStr;
|
||||
item->data() = dataAsString;
|
||||
} else if (ctext) {
|
||||
nsAutoCString dataAsString;
|
||||
ctext->GetData(dataAsString);
|
||||
item->data() = dataAsShmem;
|
||||
} else {
|
||||
// Images to be pasted on the clipboard are nsIInputStreams
|
||||
nsCOMPtr<nsIInputStream> stream(do_QueryInterface(data));
|
||||
if (stream) {
|
||||
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
|
||||
item->flavor() = flavorStr;
|
||||
|
||||
Shmem dataAsShmem = ConvertToShmem(aChild, aParent, dataAsString);
|
||||
if (!dataAsShmem.IsReadable() || !dataAsShmem.Size<char>()) {
|
||||
nsCString imageData;
|
||||
NS_ConsumeStream(stream, UINT32_MAX, imageData);
|
||||
|
||||
Shmem imageDataShmem = ConvertToShmem(aChild, aParent, imageData);
|
||||
if (!imageDataShmem.IsReadable() || !imageDataShmem.Size<char>()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
item->data() = dataAsShmem;
|
||||
item->data() = imageDataShmem;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Images to be placed on the clipboard are imgIContainers.
|
||||
nsCOMPtr<imgIContainer> image(do_QueryInterface(data));
|
||||
if (image) {
|
||||
RefPtr<mozilla::gfx::SourceSurface> surface =
|
||||
image->GetFrame(imgIContainer::FRAME_CURRENT,
|
||||
imgIContainer::FLAG_SYNC_DECODE);
|
||||
if (!surface) {
|
||||
continue;
|
||||
}
|
||||
RefPtr<mozilla::gfx::DataSourceSurface> dataSurface =
|
||||
surface->GetDataSurface();
|
||||
if (!dataSurface) {
|
||||
continue;
|
||||
}
|
||||
size_t length;
|
||||
int32_t stride;
|
||||
IShmemAllocator* allocator = aChild ? static_cast<IShmemAllocator*>(aChild)
|
||||
: static_cast<IShmemAllocator*>(aParent);
|
||||
Maybe<Shmem> surfaceData = GetSurfaceData(dataSurface, &length, &stride,
|
||||
allocator);
|
||||
|
||||
if (surfaceData.isNothing()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
|
||||
item->flavor() = flavorStr;
|
||||
// Turn item->data() into an nsCString prior to accessing it.
|
||||
item->data() = surfaceData.ref();
|
||||
|
||||
IPCDataTransferImage& imageDetails = item->imageDetails();
|
||||
mozilla::gfx::IntSize size = dataSurface->GetSize();
|
||||
imageDetails.width() = size.width;
|
||||
imageDetails.height() = size.height;
|
||||
imageDetails.stride() = stride;
|
||||
imageDetails.format() = dataSurface->GetFormat();
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Otherwise, handle this as a file.
|
||||
nsCOMPtr<BlobImpl> blobImpl;
|
||||
nsCOMPtr<nsIFile> file = do_QueryInterface(data);
|
||||
if (file) {
|
||||
// If we can send this over as a blob, do so. Otherwise, we're
|
||||
// responding to a sync message and the child can't process the blob
|
||||
// constructor before processing our response, which would crash. In
|
||||
// that case, hope that the caller is nsClipboardProxy::GetData,
|
||||
// called from editor and send over images as raw data.
|
||||
if (aInSyncMessage) {
|
||||
nsAutoCString type;
|
||||
if (IsFileImage(file, type)) {
|
||||
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
|
||||
item->flavor() = type;
|
||||
nsAutoCString data;
|
||||
SlurpFileToString(file, data);
|
||||
|
||||
Shmem dataAsShmem = ConvertToShmem(aChild, aParent, data);
|
||||
item->data() = dataAsShmem;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (aParent) {
|
||||
bool isDir = false;
|
||||
if (NS_SUCCEEDED(file->IsDirectory(&isDir)) && isDir) {
|
||||
nsAutoString path;
|
||||
if (NS_WARN_IF(NS_FAILED(file->GetPath(path)))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RefPtr<FileSystemSecurity> fss = FileSystemSecurity::GetOrCreate();
|
||||
fss->GrantAccessToContentProcess(aParent->ChildID(), path);
|
||||
}
|
||||
}
|
||||
|
||||
blobImpl = new FileBlobImpl(file);
|
||||
|
||||
IgnoredErrorResult rv;
|
||||
|
||||
// Ensure that file data is cached no that the content process
|
||||
// has this data available to it when passed over:
|
||||
blobImpl->GetSize(rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
blobImpl->GetLastModified(rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// Images to be pasted on the clipboard are nsIInputStreams
|
||||
nsCOMPtr<nsIInputStream> stream(do_QueryInterface(data));
|
||||
if (stream) {
|
||||
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
|
||||
item->flavor() = flavorStr;
|
||||
|
||||
nsCString imageData;
|
||||
NS_ConsumeStream(stream, UINT32_MAX, imageData);
|
||||
|
||||
Shmem imageDataShmem = ConvertToShmem(aChild, aParent, imageData);
|
||||
if (!imageDataShmem.IsReadable() || !imageDataShmem.Size<char>()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
item->data() = imageDataShmem;
|
||||
if (aInSyncMessage) {
|
||||
// Can't do anything.
|
||||
continue;
|
||||
}
|
||||
blobImpl = do_QueryInterface(data);
|
||||
}
|
||||
if (blobImpl) {
|
||||
IPCDataTransferData data;
|
||||
IPCBlob ipcBlob;
|
||||
|
||||
// Images to be placed on the clipboard are imgIContainers.
|
||||
nsCOMPtr<imgIContainer> image(do_QueryInterface(data));
|
||||
if (image) {
|
||||
RefPtr<mozilla::gfx::SourceSurface> surface =
|
||||
image->GetFrame(imgIContainer::FRAME_CURRENT,
|
||||
imgIContainer::FLAG_SYNC_DECODE);
|
||||
if (!surface) {
|
||||
continue;
|
||||
}
|
||||
RefPtr<mozilla::gfx::DataSourceSurface> dataSurface =
|
||||
surface->GetDataSurface();
|
||||
if (!dataSurface) {
|
||||
continue;
|
||||
}
|
||||
size_t length;
|
||||
int32_t stride;
|
||||
IShmemAllocator* allocator = aChild ? static_cast<IShmemAllocator*>(aChild)
|
||||
: static_cast<IShmemAllocator*>(aParent);
|
||||
Maybe<Shmem> surfaceData = GetSurfaceData(dataSurface, &length, &stride,
|
||||
allocator);
|
||||
|
||||
if (surfaceData.isNothing()) {
|
||||
// If we failed to create the blob actor, then this blob probably
|
||||
// can't get the file size for the underlying file, ignore it for
|
||||
// now. TODO pass this through anyway.
|
||||
if (aChild) {
|
||||
nsresult rv = IPCBlobUtils::Serialize(blobImpl, aChild, ipcBlob);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
data = ipcBlob;
|
||||
} else if (aParent) {
|
||||
nsresult rv = IPCBlobUtils::Serialize(blobImpl, aParent, ipcBlob);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
data = ipcBlob;
|
||||
}
|
||||
|
||||
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
|
||||
item->flavor() = flavorStr;
|
||||
item->data() = data;
|
||||
} else {
|
||||
// This is a hack to support kFilePromiseMime.
|
||||
// On Windows there just needs to be an entry for it,
|
||||
// and for OSX we need to create
|
||||
// nsContentAreaDragDropDataProvider as nsIFlavorDataProvider.
|
||||
if (flavorStr.EqualsLiteral(kFilePromiseMime)) {
|
||||
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
|
||||
item->flavor() = flavorStr;
|
||||
// Turn item->data() into an nsCString prior to accessing it.
|
||||
item->data() = surfaceData.ref();
|
||||
|
||||
IPCDataTransferImage& imageDetails = item->imageDetails();
|
||||
mozilla::gfx::IntSize size = dataSurface->GetSize();
|
||||
imageDetails.width() = size.width;
|
||||
imageDetails.height() = size.height;
|
||||
imageDetails.stride() = stride;
|
||||
imageDetails.format() = dataSurface->GetFormat();
|
||||
|
||||
item->data() = NS_ConvertUTF8toUTF16(flavorStr);
|
||||
} else if (!data) {
|
||||
// Empty element, transfer only the flavor
|
||||
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
|
||||
item->flavor() = flavorStr;
|
||||
item->data() = nsString();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Otherwise, handle this as a file.
|
||||
nsCOMPtr<BlobImpl> blobImpl;
|
||||
nsCOMPtr<nsIFile> file = do_QueryInterface(data);
|
||||
if (file) {
|
||||
// If we can send this over as a blob, do so. Otherwise, we're
|
||||
// responding to a sync message and the child can't process the blob
|
||||
// constructor before processing our response, which would crash. In
|
||||
// that case, hope that the caller is nsClipboardProxy::GetData,
|
||||
// called from editor and send over images as raw data.
|
||||
if (aInSyncMessage) {
|
||||
nsAutoCString type;
|
||||
if (IsFileImage(file, type)) {
|
||||
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
|
||||
item->flavor() = type;
|
||||
nsAutoCString data;
|
||||
SlurpFileToString(file, data);
|
||||
|
||||
Shmem dataAsShmem = ConvertToShmem(aChild, aParent, data);
|
||||
item->data() = dataAsShmem;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (aParent) {
|
||||
bool isDir = false;
|
||||
if (NS_SUCCEEDED(file->IsDirectory(&isDir)) && isDir) {
|
||||
nsAutoString path;
|
||||
if (NS_WARN_IF(NS_FAILED(file->GetPath(path)))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RefPtr<FileSystemSecurity> fss = FileSystemSecurity::GetOrCreate();
|
||||
fss->GrantAccessToContentProcess(aParent->ChildID(), path);
|
||||
}
|
||||
}
|
||||
|
||||
blobImpl = new FileBlobImpl(file);
|
||||
|
||||
IgnoredErrorResult rv;
|
||||
|
||||
// Ensure that file data is cached no that the content process
|
||||
// has this data available to it when passed over:
|
||||
blobImpl->GetSize(rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
blobImpl->GetLastModified(rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (aInSyncMessage) {
|
||||
// Can't do anything.
|
||||
continue;
|
||||
}
|
||||
blobImpl = do_QueryInterface(data);
|
||||
}
|
||||
if (blobImpl) {
|
||||
IPCDataTransferData data;
|
||||
IPCBlob ipcBlob;
|
||||
|
||||
// If we failed to create the blob actor, then this blob probably
|
||||
// can't get the file size for the underlying file, ignore it for
|
||||
// now. TODO pass this through anyway.
|
||||
if (aChild) {
|
||||
nsresult rv = IPCBlobUtils::Serialize(blobImpl, aChild, ipcBlob);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
data = ipcBlob;
|
||||
} else if (aParent) {
|
||||
nsresult rv = IPCBlobUtils::Serialize(blobImpl, aParent, ipcBlob);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
data = ipcBlob;
|
||||
}
|
||||
|
||||
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
|
||||
item->flavor() = flavorStr;
|
||||
item->data() = data;
|
||||
} else {
|
||||
// This is a hack to support kFilePromiseMime.
|
||||
// On Windows there just needs to be an entry for it,
|
||||
// and for OSX we need to create
|
||||
// nsContentAreaDragDropDataProvider as nsIFlavorDataProvider.
|
||||
if (flavorStr.EqualsLiteral(kFilePromiseMime)) {
|
||||
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
|
||||
item->flavor() = flavorStr;
|
||||
item->data() = NS_ConvertUTF8toUTF16(flavorStr);
|
||||
} else if (!data) {
|
||||
// Empty element, transfer only the flavor
|
||||
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
|
||||
item->flavor() = flavorStr;
|
||||
item->data() = nsString();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ UNIFIED_SOURCES += [
|
|||
'Intervals.cpp',
|
||||
'json.cpp',
|
||||
'Justifier.cpp',
|
||||
'NameTable.cpp',
|
||||
'Pass.cpp',
|
||||
'Position.cpp',
|
||||
'Segment.cpp',
|
||||
|
@ -53,12 +54,6 @@ UNIFIED_SOURCES += [
|
|||
'UtfCodec.cpp',
|
||||
]
|
||||
|
||||
# Excluded from UNIFIED_SOURCES because <cmath> from other files breaks it,
|
||||
# see bug 1272647.
|
||||
SOURCES += [
|
||||
'NameTable.cpp',
|
||||
]
|
||||
|
||||
# tell graphite2 not to export symbols, we'll be linking it directly with
|
||||
# thebes
|
||||
DEFINES['GRAPHITE2_STATIC'] = True
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
skip-if = (verify && debug && (os == 'win'))
|
||||
[test_group_touchevents-3.html]
|
||||
skip-if = (verify && debug && (os == 'win'))
|
||||
[test_group_touchevents-4.html]
|
||||
skip-if = (verify && debug && (os == 'win'))
|
||||
[test_group_wheelevents.html]
|
||||
skip-if = (toolkit == 'android') # wheel events not supported on mobile
|
||||
[test_group_zoom.html]
|
||||
|
|
|
@ -38,7 +38,7 @@ var subtests = [
|
|||
["apz.test.fails_with_native_injection", isWindows],
|
||||
["dom.event.default_to_passive_touch_listeners", true]]},
|
||||
|
||||
// Add new subtests to test_group_touch_events-3.html, not this file.
|
||||
// Add new subtests to test_group_touch_events-4.html, not this file.
|
||||
];
|
||||
|
||||
if (isApzEnabled()) {
|
||||
|
|
|
@ -23,11 +23,8 @@ var subtests = [
|
|||
// Tests that touch-action CSS properties are handled in APZ without waiting
|
||||
// on the main-thread, when possible
|
||||
{'file': 'helper_touch_action_regions.html', 'prefs': touch_action_prefs},
|
||||
// touch-action tests with :active::after CSS property
|
||||
{'file': 'helper_bug1473108.html'},
|
||||
// Add new subtests here. If this starts timing out because it's taking too
|
||||
// long, create a test_group_touchevents-4.html file. Refer to 1423011#c57
|
||||
// for more details.
|
||||
|
||||
// Add new subtests to test_group_touch_events-4.html, not this file.
|
||||
];
|
||||
|
||||
if (isApzEnabled()) {
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Various touch tests that spawn in new windows (4)</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
var subtests = [
|
||||
// touch-action tests with :active::after CSS property
|
||||
{'file': 'helper_bug1473108.html'},
|
||||
// Add new subtests here. If this starts timing out because it's taking too
|
||||
// long, create a test_group_touchevents-5.html file. Refer to 1423011#c57
|
||||
// for more details.
|
||||
];
|
||||
|
||||
if (isApzEnabled()) {
|
||||
ok(window.TouchEvent, "Check if TouchEvent is supported (it should be, the test harness forces it on everywhere)");
|
||||
if (getPlatform() == "android") {
|
||||
// This has a lot of subtests, and Android emulators are slow.
|
||||
SimpleTest.requestLongerTimeout(2);
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
window.onload = function() {
|
||||
runSubtestsSeriallyInFreshWindows(subtests)
|
||||
.then(SimpleTest.finish, SimpleTest.finish);
|
||||
};
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
|
@ -27,7 +27,7 @@ var subtests = [
|
|||
{'file': 'helper_scrollto_tap.html?true', 'prefs': [["apz.paint_skipping.enabled", true]], 'dp_suppression': false},
|
||||
{'file': 'helper_scrollto_tap.html?false', 'prefs': [["apz.paint_skipping.enabled", false]], 'dp_suppression': false},
|
||||
|
||||
// Add new subtests to test_group_touch_events-3.html, not this file.
|
||||
// Add new subtests to test_group_touch_events-4.html, not this file.
|
||||
];
|
||||
|
||||
if (isApzEnabled()) {
|
||||
|
|
|
@ -437,6 +437,14 @@ struct BlobCommand {
|
|||
tile_size: Option<TileSize>,
|
||||
}
|
||||
|
||||
struct Job {
|
||||
request: BlobImageRequest,
|
||||
descriptor: BlobImageDescriptor,
|
||||
commands: Arc<BlobImageData>,
|
||||
dirty_rect: Option<DeviceUintRect>,
|
||||
tile_size: Option<TileSize>,
|
||||
}
|
||||
|
||||
/// Rasterizes gecko blob images.
|
||||
struct Moz2dBlobRasterizer {
|
||||
/// Pool of rasterizers.
|
||||
|
@ -447,17 +455,9 @@ struct Moz2dBlobRasterizer {
|
|||
|
||||
impl AsyncBlobImageRasterizer for Moz2dBlobRasterizer {
|
||||
|
||||
fn rasterize(&mut self, requests: &[BlobImageParams], _low_priority: bool) -> Vec<(BlobImageRequest, BlobImageResult)> {
|
||||
fn rasterize(&mut self, requests: &[BlobImageParams], low_priority: bool) -> Vec<(BlobImageRequest, BlobImageResult)> {
|
||||
// All we do here is spin up our workers to callback into gecko to replay the drawing commands.
|
||||
|
||||
struct Job {
|
||||
request: BlobImageRequest,
|
||||
descriptor: BlobImageDescriptor,
|
||||
commands: Arc<BlobImageData>,
|
||||
dirty_rect: Option<DeviceUintRect>,
|
||||
tile_size: Option<TileSize>,
|
||||
}
|
||||
|
||||
let requests: Vec<Job> = requests.into_iter().map(|params| {
|
||||
let command = &self.blob_commands[¶ms.request.key];
|
||||
let blob = Arc::clone(&command.data);
|
||||
|
@ -470,46 +470,66 @@ impl AsyncBlobImageRasterizer for Moz2dBlobRasterizer {
|
|||
}
|
||||
}).collect();
|
||||
|
||||
self.workers.install(|| {
|
||||
requests.into_par_iter().map(|item| {
|
||||
let descriptor = item.descriptor;
|
||||
let buf_size = (descriptor.size.width
|
||||
* descriptor.size.height
|
||||
* descriptor.format.bytes_per_pixel()) as usize;
|
||||
// If we don't have a lot of blobs it is probably not worth the initial cost
|
||||
// of installing work on rayon's thread pool so we do it serially on this thread.
|
||||
let should_parallelize = if low_priority {
|
||||
requests.len() > 2
|
||||
} else {
|
||||
// For high priority requests we don't "risk" the potential priority inversion of
|
||||
// dispatching to a thread pool full of low priority jobs unless it is really
|
||||
// appealing.
|
||||
requests.len() > 4
|
||||
};
|
||||
|
||||
let mut output = vec![0u8; buf_size];
|
||||
|
||||
let result = unsafe {
|
||||
if wr_moz2d_render_cb(
|
||||
ByteSlice::new(&item.commands[..]),
|
||||
descriptor.size.width,
|
||||
descriptor.size.height,
|
||||
descriptor.format,
|
||||
item.tile_size.as_ref(),
|
||||
item.request.tile.as_ref(),
|
||||
item.dirty_rect.as_ref(),
|
||||
MutByteSlice::new(output.as_mut_slice()),
|
||||
) {
|
||||
Ok(RasterizedBlobImage {
|
||||
rasterized_rect: item.dirty_rect.unwrap_or(
|
||||
DeviceUintRect {
|
||||
origin: DeviceUintPoint::origin(),
|
||||
size: descriptor.size,
|
||||
}
|
||||
),
|
||||
data: Arc::new(output),
|
||||
})
|
||||
} else {
|
||||
panic!("Moz2D replay problem");
|
||||
}
|
||||
};
|
||||
|
||||
(item.request, result)
|
||||
}).collect()
|
||||
})
|
||||
if should_parallelize {
|
||||
// Parallel version synchronously installs a job on the thread pool which will
|
||||
// try to do the work in parallel.
|
||||
// This thread is blocked until the thread pool is done doing the work.
|
||||
self.workers.install(||{
|
||||
requests.into_par_iter().map(rasterize_blob).collect()
|
||||
})
|
||||
} else {
|
||||
requests.into_iter().map(rasterize_blob).collect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn rasterize_blob(job: Job) -> (BlobImageRequest, BlobImageResult) {
|
||||
let descriptor = job.descriptor;
|
||||
let buf_size = (descriptor.size.width
|
||||
* descriptor.size.height
|
||||
* descriptor.format.bytes_per_pixel()) as usize;
|
||||
|
||||
let mut output = vec![0u8; buf_size];
|
||||
|
||||
let result = unsafe {
|
||||
if wr_moz2d_render_cb(
|
||||
ByteSlice::new(&job.commands[..]),
|
||||
descriptor.size.width,
|
||||
descriptor.size.height,
|
||||
descriptor.format,
|
||||
job.tile_size.as_ref(),
|
||||
job.request.tile.as_ref(),
|
||||
job.dirty_rect.as_ref(),
|
||||
MutByteSlice::new(output.as_mut_slice()),
|
||||
) {
|
||||
Ok(RasterizedBlobImage {
|
||||
rasterized_rect: job.dirty_rect.unwrap_or(
|
||||
DeviceUintRect {
|
||||
origin: DeviceUintPoint::origin(),
|
||||
size: descriptor.size,
|
||||
}
|
||||
),
|
||||
data: Arc::new(output),
|
||||
})
|
||||
} else {
|
||||
panic!("Moz2D replay problem");
|
||||
}
|
||||
};
|
||||
|
||||
(job.request, result)
|
||||
}
|
||||
|
||||
impl BlobImageHandler for Moz2dBlobImageHandler {
|
||||
fn add(&mut self, key: ImageKey, data: Arc<BlobImageData>, tile_size: Option<TileSize>) {
|
||||
{
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
setJitCompilerOption("jit.enable-tracelogger", 1);
|
||||
try {
|
||||
(function(b, foreign, p) {
|
||||
"use asm"
|
||||
|
|
|
@ -411,7 +411,7 @@ BaselineCacheIRCompiler::emitGuardSpecificAtom()
|
|||
masm.loadPtr(atomAddr, scratch);
|
||||
masm.passABIArg(scratch);
|
||||
masm.passABIArg(str);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, EqualStringsHelper));
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, EqualStringsHelperPure));
|
||||
masm.mov(ReturnReg, scratch);
|
||||
|
||||
LiveRegisterSet ignore;
|
||||
|
@ -497,7 +497,7 @@ BaselineCacheIRCompiler::emitGuardHasGetterSetter()
|
|||
masm.passABIArg(obj);
|
||||
masm.loadPtr(shapeAddr, scratch2);
|
||||
masm.passABIArg(scratch2);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, ObjectHasGetterSetter));
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, ObjectHasGetterSetterPure));
|
||||
masm.mov(ReturnReg, scratch1);
|
||||
masm.PopRegsInMask(volatileRegs);
|
||||
|
||||
|
@ -1077,7 +1077,7 @@ BaselineCacheIRCompiler::emitAddAndStoreSlotShared(CacheOp op)
|
|||
// We have to (re)allocate dynamic slots. Do this first, as it's the
|
||||
// only fallible operation here. This simplifies the callTypeUpdateIC
|
||||
// call below: it does not have to worry about saving registers used by
|
||||
// failure paths. Note that growSlotsDontReportOOM is fallible but does
|
||||
// failure paths. Note that growSlotsPure is fallible but does
|
||||
// not GC.
|
||||
Address numNewSlotsAddr = stubAddress(reader.stubOffset());
|
||||
|
||||
|
@ -1095,7 +1095,7 @@ BaselineCacheIRCompiler::emitAddAndStoreSlotShared(CacheOp op)
|
|||
masm.passABIArg(obj);
|
||||
masm.load32(numNewSlotsAddr, scratch2);
|
||||
masm.passABIArg(scratch2);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, NativeObject::growSlotsDontReportOOM));
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, NativeObject::growSlotsPure));
|
||||
masm.mov(ReturnReg, scratch1);
|
||||
|
||||
LiveRegisterSet ignore;
|
||||
|
@ -1426,7 +1426,7 @@ BaselineCacheIRCompiler::emitStoreDenseElementHole()
|
|||
masm.loadJSContext(scratch);
|
||||
masm.passABIArg(scratch);
|
||||
masm.passABIArg(obj);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, NativeObject::addDenseElementDontReportOOM));
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, NativeObject::addDenseElementPure));
|
||||
masm.mov(ReturnReg, scratch);
|
||||
|
||||
masm.PopRegsInMask(save);
|
||||
|
@ -1566,7 +1566,7 @@ BaselineCacheIRCompiler::emitArrayPush()
|
|||
masm.loadJSContext(scratch);
|
||||
masm.passABIArg(scratch);
|
||||
masm.passABIArg(obj);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, NativeObject::addDenseElementDontReportOOM));
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, NativeObject::addDenseElementPure));
|
||||
masm.mov(ReturnReg, scratch);
|
||||
|
||||
masm.PopRegsInMask(save);
|
||||
|
|
|
@ -1965,7 +1965,7 @@ CacheIRCompiler::emitGuardAndGetNumberFromString()
|
|||
masm.passABIArg(scratch);
|
||||
masm.passABIArg(str);
|
||||
masm.passABIArg(output.payloadOrValueReg());
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, StringToNumberDontReportOOM));
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, StringToNumberPure));
|
||||
masm.mov(ReturnReg, scratch);
|
||||
|
||||
LiveRegisterSet ignore;
|
||||
|
@ -1975,16 +1975,16 @@ CacheIRCompiler::emitGuardAndGetNumberFromString()
|
|||
Label ok;
|
||||
masm.branchIfTrueBool(scratch, &ok);
|
||||
{
|
||||
// OOM path, recovered by StringToNumberDontReportOOM.
|
||||
// OOM path, recovered by StringToNumberPure.
|
||||
//
|
||||
// Use addToStackPtr instead of freeStack as freeStack tracks stack height
|
||||
// flow-insensitively, and using it twice would confuse the stack height
|
||||
// tracking.
|
||||
// tracking.
|
||||
masm.addToStackPtr(Imm32(sizeof(double)));
|
||||
masm.jump(failure->label());
|
||||
}
|
||||
masm.bind(&ok);
|
||||
|
||||
|
||||
masm.loadDouble(Address(output.payloadOrValueReg(), 0), FloatReg0);
|
||||
masm.boxDouble(FloatReg0, output, FloatReg0);
|
||||
masm.freeStack(sizeof(double));
|
||||
|
@ -3803,7 +3803,7 @@ CacheIRCompiler::emitCallObjectHasSparseElementResult()
|
|||
masm.passABIArg(obj);
|
||||
masm.passABIArg(index);
|
||||
masm.passABIArg(scratch2);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, HasNativeElement));
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, HasNativeElementPure));
|
||||
masm.mov(ReturnReg, scratch1);
|
||||
masm.PopRegsInMask(volatileRegs);
|
||||
|
||||
|
@ -3950,9 +3950,9 @@ CacheIRCompiler::emitMegamorphicLoadSlotResult()
|
|||
masm.passABIArg(scratch2);
|
||||
masm.passABIArg(scratch3);
|
||||
if (handleMissing) {
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, (GetNativeDataProperty<true>)));
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, (GetNativeDataPropertyPure<true>)));
|
||||
} else {
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, (GetNativeDataProperty<false>)));
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, (GetNativeDataPropertyPure<false>)));
|
||||
}
|
||||
masm.mov(ReturnReg, scratch2);
|
||||
masm.PopRegsInMask(volatileRegs);
|
||||
|
@ -4001,9 +4001,9 @@ CacheIRCompiler::emitMegamorphicStoreSlot()
|
|||
masm.passABIArg(scratch2);
|
||||
masm.passABIArg(val.scratchReg());
|
||||
if (needsTypeBarrier) {
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, (SetNativeDataProperty<true>)));
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, (SetNativeDataPropertyPure<true>)));
|
||||
} else {
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, (SetNativeDataProperty<false>)));
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, (SetNativeDataPropertyPure<false>)));
|
||||
}
|
||||
masm.mov(ReturnReg, scratch1);
|
||||
masm.PopRegsInMask(volatileRegs);
|
||||
|
@ -4059,7 +4059,7 @@ CacheIRCompiler::emitCallInt32ToString() {
|
|||
masm.loadJSContext(result);
|
||||
masm.passABIArg(result);
|
||||
masm.passABIArg(input);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, (js::Int32ToStringHelper)));
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, (js::Int32ToStringHelperPure)));
|
||||
|
||||
masm.mov(ReturnReg, result);
|
||||
masm.PopRegsInMask(volatileRegs);
|
||||
|
@ -4090,7 +4090,7 @@ CacheIRCompiler::emitCallNumberToString() {
|
|||
masm.loadJSContext(result);
|
||||
masm.passABIArg(result);
|
||||
masm.passABIArg(FloatReg0, MoveOp::DOUBLE);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, (js::NumberToStringHelper)));
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, (js::NumberToStringHelperPure)));
|
||||
|
||||
masm.mov(ReturnReg, result);
|
||||
masm.PopRegsInMask(volatileRegs);
|
||||
|
|
|
@ -6917,7 +6917,7 @@ CodeGenerator::visitCreateArgumentsObject(LCreateArgumentsObject* lir)
|
|||
|
||||
// Try to allocate an arguments object. This will leave the reserved
|
||||
// slots uninitialized, so it's important we don't GC until we
|
||||
// initialize these slots in ArgumentsObject::finishForIon.
|
||||
// initialize these slots in ArgumentsObject::finishForIonPure.
|
||||
Label failure;
|
||||
TemplateObject templateObject(templateObj);
|
||||
masm.createGCObject(objTemp, temp, templateObject, gc::DefaultHeap, &failure,
|
||||
|
@ -6933,7 +6933,7 @@ CodeGenerator::visitCreateArgumentsObject(LCreateArgumentsObject* lir)
|
|||
masm.passABIArg(callObj);
|
||||
masm.passABIArg(objTemp);
|
||||
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, ArgumentsObject::finishForIon));
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, ArgumentsObject::finishForIonPure));
|
||||
masm.branchTestPtr(Assembler::Zero, ReturnReg, ReturnReg, &failure);
|
||||
|
||||
// Discard saved callObj on the stack.
|
||||
|
|
|
@ -834,7 +834,7 @@ IonCacheIRCompiler::emitGuardSpecificAtom()
|
|||
masm.movePtr(ImmGCPtr(atom), scratch);
|
||||
masm.passABIArg(scratch);
|
||||
masm.passABIArg(str);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, EqualStringsHelper));
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, EqualStringsHelperPure));
|
||||
masm.mov(ReturnReg, scratch);
|
||||
|
||||
LiveRegisterSet ignore;
|
||||
|
@ -916,7 +916,7 @@ IonCacheIRCompiler::emitGuardHasGetterSetter()
|
|||
masm.passABIArg(obj);
|
||||
masm.movePtr(ImmGCPtr(shape), scratch2);
|
||||
masm.passABIArg(scratch2);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, ObjectHasGetterSetter));
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, ObjectHasGetterSetterPure));
|
||||
masm.mov(ReturnReg, scratch1);
|
||||
masm.PopRegsInMask(volatileRegs);
|
||||
|
||||
|
@ -1606,7 +1606,7 @@ IonCacheIRCompiler::emitAddAndStoreSlotShared(CacheOp op)
|
|||
|
||||
if (op == CacheOp::AllocateAndStoreDynamicSlot) {
|
||||
// We have to (re)allocate dynamic slots. Do this first, as it's the
|
||||
// only fallible operation here. Note that growSlotsDontReportOOM is
|
||||
// only fallible operation here. Note that growSlotsPure is
|
||||
// fallible but does not GC.
|
||||
int32_t numNewSlots = int32StubField(reader.stubOffset());
|
||||
MOZ_ASSERT(numNewSlots > 0);
|
||||
|
@ -1620,7 +1620,7 @@ IonCacheIRCompiler::emitAddAndStoreSlotShared(CacheOp op)
|
|||
masm.passABIArg(obj);
|
||||
masm.move32(Imm32(numNewSlots), scratch2.ref());
|
||||
masm.passABIArg(scratch2.ref());
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, NativeObject::growSlotsDontReportOOM));
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, NativeObject::growSlotsPure));
|
||||
masm.mov(ReturnReg, scratch1);
|
||||
|
||||
LiveRegisterSet ignore;
|
||||
|
@ -1955,7 +1955,7 @@ IonCacheIRCompiler::emitStoreDenseElementHole()
|
|||
masm.loadJSContext(scratch1);
|
||||
masm.passABIArg(scratch1);
|
||||
masm.passABIArg(obj);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, NativeObject::addDenseElementDontReportOOM));
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, NativeObject::addDenseElementPure));
|
||||
masm.mov(ReturnReg, scratch1);
|
||||
|
||||
masm.PopRegsInMask(save);
|
||||
|
|
|
@ -1601,7 +1601,7 @@ CallNativeSetter(JSContext* cx, HandleFunction callee, HandleObject obj, HandleV
|
|||
}
|
||||
|
||||
bool
|
||||
EqualStringsHelper(JSString* str1, JSString* str2)
|
||||
EqualStringsHelperPure(JSString* str1, JSString* str2)
|
||||
{
|
||||
// IC code calls this directly so we shouldn't GC.
|
||||
AutoUnsafeCallWithABI unsafe;
|
||||
|
@ -1632,7 +1632,7 @@ CheckIsCallable(JSContext* cx, HandleValue v, CheckIsCallableKind kind)
|
|||
|
||||
template <bool HandleMissing>
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
GetNativeDataProperty(JSContext* cx, NativeObject* obj, jsid id, Value* vp)
|
||||
GetNativeDataPropertyPure(JSContext* cx, NativeObject* obj, jsid id, Value* vp)
|
||||
{
|
||||
// Fast path used by megamorphic IC stubs. Unlike our other property
|
||||
// lookup paths, this is optimized to be as fast as possible for simple
|
||||
|
@ -1677,18 +1677,18 @@ GetNativeDataProperty(JSContext* cx, NativeObject* obj, jsid id, Value* vp)
|
|||
|
||||
template <bool HandleMissing>
|
||||
bool
|
||||
GetNativeDataProperty(JSContext* cx, JSObject* obj, PropertyName* name, Value* vp)
|
||||
GetNativeDataPropertyPure(JSContext* cx, JSObject* obj, PropertyName* name, Value* vp)
|
||||
{
|
||||
// Condition checked by caller.
|
||||
MOZ_ASSERT(obj->isNative());
|
||||
return GetNativeDataProperty<HandleMissing>(cx, &obj->as<NativeObject>(), NameToId(name), vp);
|
||||
return GetNativeDataPropertyPure<HandleMissing>(cx, &obj->as<NativeObject>(), NameToId(name), vp);
|
||||
}
|
||||
|
||||
template bool
|
||||
GetNativeDataProperty<true>(JSContext* cx, JSObject* obj, PropertyName* name, Value* vp);
|
||||
GetNativeDataPropertyPure<true>(JSContext* cx, JSObject* obj, PropertyName* name, Value* vp);
|
||||
|
||||
template bool
|
||||
GetNativeDataProperty<false>(JSContext* cx, JSObject* obj, PropertyName* name, Value* vp);
|
||||
GetNativeDataPropertyPure<false>(JSContext* cx, JSObject* obj, PropertyName* name, Value* vp);
|
||||
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
ValueToAtomOrSymbolPure(JSContext* cx, Value& idVal, jsid* id)
|
||||
|
@ -1741,7 +1741,7 @@ GetNativeDataPropertyByValuePure(JSContext* cx, JSObject* obj, Value* vp)
|
|||
}
|
||||
|
||||
Value* res = vp + 1;
|
||||
return GetNativeDataProperty<HandleMissing>(cx, &obj->as<NativeObject>(), id, res);
|
||||
return GetNativeDataPropertyPure<HandleMissing>(cx, &obj->as<NativeObject>(), id, res);
|
||||
}
|
||||
|
||||
template bool
|
||||
|
@ -1752,7 +1752,7 @@ GetNativeDataPropertyByValuePure<false>(JSContext* cx, JSObject* obj, Value* vp)
|
|||
|
||||
template <bool NeedsTypeBarrier>
|
||||
bool
|
||||
SetNativeDataProperty(JSContext* cx, JSObject* obj, PropertyName* name, Value* val)
|
||||
SetNativeDataPropertyPure(JSContext* cx, JSObject* obj, PropertyName* name, Value* val)
|
||||
{
|
||||
AutoUnsafeCallWithABI unsafe;
|
||||
|
||||
|
@ -1778,13 +1778,13 @@ SetNativeDataProperty(JSContext* cx, JSObject* obj, PropertyName* name, Value* v
|
|||
}
|
||||
|
||||
template bool
|
||||
SetNativeDataProperty<true>(JSContext* cx, JSObject* obj, PropertyName* name, Value* val);
|
||||
SetNativeDataPropertyPure<true>(JSContext* cx, JSObject* obj, PropertyName* name, Value* val);
|
||||
|
||||
template bool
|
||||
SetNativeDataProperty<false>(JSContext* cx, JSObject* obj, PropertyName* name, Value* val);
|
||||
SetNativeDataPropertyPure<false>(JSContext* cx, JSObject* obj, PropertyName* name, Value* val);
|
||||
|
||||
bool
|
||||
ObjectHasGetterSetter(JSContext* cx, JSObject* objArg, Shape* propShape)
|
||||
ObjectHasGetterSetterPure(JSContext* cx, JSObject* objArg, Shape* propShape)
|
||||
{
|
||||
AutoUnsafeCallWithABI unsafe;
|
||||
|
||||
|
@ -1893,7 +1893,7 @@ HasNativeDataPropertyPure<false>(JSContext* cx, JSObject* obj, Value* vp);
|
|||
|
||||
|
||||
bool
|
||||
HasNativeElement(JSContext* cx, NativeObject* obj, int32_t index, Value* vp)
|
||||
HasNativeElementPure(JSContext* cx, NativeObject* obj, int32_t index, Value* vp)
|
||||
{
|
||||
AutoUnsafeCallWithABI unsafe;
|
||||
|
||||
|
|
|
@ -917,14 +917,14 @@ CallNativeSetter(JSContext* cx, HandleFunction callee, HandleObject obj,
|
|||
HandleValue rhs);
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
EqualStringsHelper(JSString* str1, JSString* str2);
|
||||
EqualStringsHelperPure(JSString* str1, JSString* str2);
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
CheckIsCallable(JSContext* cx, HandleValue v, CheckIsCallableKind kind);
|
||||
|
||||
template <bool HandleMissing>
|
||||
bool
|
||||
GetNativeDataProperty(JSContext* cx, JSObject* obj, PropertyName* name, Value* vp);
|
||||
GetNativeDataPropertyPure(JSContext* cx, JSObject* obj, PropertyName* name, Value* vp);
|
||||
|
||||
template <bool HandleMissing>
|
||||
bool
|
||||
|
@ -935,14 +935,14 @@ bool
|
|||
HasNativeDataPropertyPure(JSContext* cx, JSObject* obj, Value* vp);
|
||||
|
||||
bool
|
||||
HasNativeElement(JSContext* cx, NativeObject* obj, int32_t index, Value* vp);
|
||||
HasNativeElementPure(JSContext* cx, NativeObject* obj, int32_t index, Value* vp);
|
||||
|
||||
template <bool NeedsTypeBarrier>
|
||||
bool
|
||||
SetNativeDataProperty(JSContext* cx, JSObject* obj, PropertyName* name, Value* val);
|
||||
SetNativeDataPropertyPure(JSContext* cx, JSObject* obj, PropertyName* name, Value* val);
|
||||
|
||||
bool
|
||||
ObjectHasGetterSetter(JSContext* cx, JSObject* obj, Shape* propShape);
|
||||
ObjectHasGetterSetterPure(JSContext* cx, JSObject* obj, Shape* propShape);
|
||||
|
||||
JSString*
|
||||
TypeOfObject(JSObject* obj, JSRuntime* rt);
|
||||
|
|
|
@ -228,6 +228,8 @@ class JSAPITest
|
|||
message += msg;
|
||||
|
||||
if (JS_IsExceptionPending(cx)) {
|
||||
message += " -- ";
|
||||
|
||||
js::gc::AutoSuppressGC gcoff(cx);
|
||||
JS::RootedValue v(cx);
|
||||
JS_GetPendingException(cx, &v);
|
||||
|
|
|
@ -6608,11 +6608,6 @@ JS_SetGlobalJitCompilerOption(JSContext* cx, JSJitCompilerOption opt, uint32_t v
|
|||
case JSJITCOMPILER_TRACK_OPTIMIZATIONS:
|
||||
jit::JitOptions.disableOptimizationTracking = !value;
|
||||
break;
|
||||
#ifdef JS_TRACE_LOGGING
|
||||
case JSJITCOMPILER_ENABLE_TRACELOGGER:
|
||||
jit::JitOptions.enableTraceLogger = !!value;
|
||||
break;
|
||||
#endif
|
||||
case JSJITCOMPILER_SPECTRE_INDEX_MASKING:
|
||||
jit::JitOptions.spectreIndexMasking = !!value;
|
||||
break;
|
||||
|
|
|
@ -2741,21 +2741,21 @@ JS_SetArrayLength(JSContext* cx, JS::Handle<JSObject*> obj, uint32_t length);
|
|||
namespace JS {
|
||||
|
||||
/**
|
||||
* Returns true and sets |*isMap| indicating whether |obj| is an Map object
|
||||
* or a wrapper around one, otherwise returns false on failure.
|
||||
* On success, returns true, setting |*isMap| to true if |obj| is a Map object
|
||||
* or a wrapper around one, or to false if not. Returns false on failure.
|
||||
*
|
||||
* This method returns true with |*isMap == false| when passed a proxy whose
|
||||
* target is an Map, or when passed a revoked proxy.
|
||||
* This method returns true with |*isMap == false| when passed an ES6 proxy
|
||||
* whose target is a Map, or when passed a revoked proxy.
|
||||
*/
|
||||
extern JS_PUBLIC_API(bool)
|
||||
IsMapObject(JSContext* cx, JS::HandleObject obj, bool* isMap);
|
||||
|
||||
/**
|
||||
* Returns true and sets |*isSet| indicating whether |obj| is an Set object
|
||||
* or a wrapper around one, otherwise returns false on failure.
|
||||
* On success, returns true, setting |*isSet| to true if |obj| is a Set object
|
||||
* or a wrapper around one, or to false if not. Returns false on failure.
|
||||
*
|
||||
* This method returns true with |*isSet == false| when passed a proxy whose
|
||||
* target is an Set, or when passed a revoked proxy.
|
||||
* This method returns true with |*isSet == false| when passed an ES6 proxy
|
||||
* whose target is a Set, or when passed a revoked proxy.
|
||||
*/
|
||||
extern JS_PUBLIC_API(bool)
|
||||
IsSetObject(JSContext* cx, JS::HandleObject obj, bool* isSet);
|
||||
|
@ -4283,11 +4283,12 @@ extern JS_PUBLIC_API(JSObject*)
|
|||
JS_NewDateObject(JSContext* cx, int year, int mon, int mday, int hour, int min, int sec);
|
||||
|
||||
/**
|
||||
* Returns true and sets |*isDate| indicating whether |obj| is a Date object or
|
||||
* a wrapper around one, otherwise returns false on failure.
|
||||
* On success, returns true, setting |*isDate| to true if |obj| is a Date
|
||||
* object or a wrapper around one, or to false if not. Returns false on
|
||||
* failure.
|
||||
*
|
||||
* This method returns true with |*isDate == false| when passed a proxy whose
|
||||
* target is a Date, or when passed a revoked proxy.
|
||||
* This method returns true with |*isDate == false| when passed an ES6 proxy
|
||||
* whose target is a Date, or when passed a revoked proxy.
|
||||
*/
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_ObjectIsDate(JSContext* cx, JS::HandleObject obj, bool* isDate);
|
||||
|
@ -4327,11 +4328,12 @@ JS_ExecuteRegExpNoStatics(JSContext* cx, JS::HandleObject reobj, char16_t* chars
|
|||
size_t* indexp, bool test, JS::MutableHandleValue rval);
|
||||
|
||||
/**
|
||||
* Returns true and sets |*isRegExp| indicating whether |obj| is a RegExp
|
||||
* object or a wrapper around one, otherwise returns false on failure.
|
||||
* On success, returns true, setting |*isRegExp| to true if |obj| is a RegExp
|
||||
* object or a wrapper around one, or to false if not. Returns false on
|
||||
* failure.
|
||||
*
|
||||
* This method returns true with |*isRegExp == false| when passed a proxy whose
|
||||
* target is a RegExp, or when passed a revoked proxy.
|
||||
* This method returns true with |*isRegExp == false| when passed an ES6 proxy
|
||||
* whose target is a RegExp, or when passed a revoked proxy.
|
||||
*/
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_ObjectIsRegExp(JSContext* cx, JS::HandleObject obj, bool* isRegExp);
|
||||
|
@ -4515,7 +4517,6 @@ JS_SetOffthreadIonCompilationEnabled(JSContext* cx, bool enabled);
|
|||
Register(FULL_DEBUG_CHECKS, "jit.full-debug-checks") \
|
||||
Register(JUMP_THRESHOLD, "jump-threshold") \
|
||||
Register(TRACK_OPTIMIZATIONS, "jit.track-optimizations") \
|
||||
Register(ENABLE_TRACELOGGER, "jit.enable-tracelogger") \
|
||||
Register(SIMULATOR_ALWAYS_INTERRUPT, "simulator.always-interrupt") \
|
||||
Register(SPECTRE_INDEX_MASKING, "spectre.index-masking") \
|
||||
Register(SPECTRE_OBJECT_MITIGATIONS_BARRIERS, "spectre.object-mitigations.barriers") \
|
||||
|
|
|
@ -720,7 +720,7 @@ template JSFlatString*
|
|||
js::Int32ToString<NoGC>(JSContext* cx, int32_t si);
|
||||
|
||||
JSFlatString*
|
||||
js::Int32ToStringHelper(JSContext* cx, int32_t si)
|
||||
js::Int32ToStringHelperPure(JSContext* cx, int32_t si)
|
||||
{
|
||||
AutoUnsafeCallWithABI unsafe;
|
||||
JSFlatString* res = Int32ToString<NoGC>(cx, si);
|
||||
|
@ -1530,7 +1530,7 @@ template JSString*
|
|||
js::NumberToString<NoGC>(JSContext* cx, double d);
|
||||
|
||||
JSString*
|
||||
js::NumberToStringHelper(JSContext* cx, double d)
|
||||
js::NumberToStringHelperPure(JSContext* cx, double d)
|
||||
{
|
||||
AutoUnsafeCallWithABI unsafe;
|
||||
JSString* res = NumberToString<NoGC>(cx, d);
|
||||
|
@ -1714,7 +1714,7 @@ js::StringToNumber(JSContext* cx, JSString* str, double* result)
|
|||
}
|
||||
|
||||
bool
|
||||
js::StringToNumberDontReportOOM(JSContext* cx, JSString* str, double* result)
|
||||
js::StringToNumberPure(JSContext* cx, JSString* str, double* result)
|
||||
{
|
||||
// IC Code calls this directly.
|
||||
AutoUnsafeCallWithABI unsafe;
|
||||
|
|
|
@ -61,7 +61,7 @@ extern JSString*
|
|||
NumberToString(JSContext* cx, double d);
|
||||
|
||||
extern JSString*
|
||||
NumberToStringHelper(JSContext* cx, double d);
|
||||
NumberToStringHelperPure(JSContext* cx, double d);
|
||||
|
||||
extern JSAtom*
|
||||
NumberToAtom(JSContext* cx, double d);
|
||||
|
@ -71,7 +71,7 @@ extern JSFlatString*
|
|||
Int32ToString(JSContext* cx, int32_t i);
|
||||
|
||||
extern JSFlatString*
|
||||
Int32ToStringHelper(JSContext* cx, int32_t i);
|
||||
Int32ToStringHelperPure(JSContext* cx, int32_t i);
|
||||
|
||||
extern JSAtom*
|
||||
Int32ToAtom(JSContext* cx, int32_t si);
|
||||
|
@ -199,7 +199,7 @@ extern MOZ_MUST_USE bool
|
|||
StringToNumber(JSContext* cx, JSString* str, double* result);
|
||||
|
||||
extern MOZ_MUST_USE bool
|
||||
StringToNumberDontReportOOM(JSContext* cx, JSString* str, double* result);
|
||||
StringToNumberPure(JSContext* cx, JSString* str, double* result);
|
||||
|
||||
/* ES5 9.3 ToNumber, overwriting *vp with the appropriate number value. */
|
||||
MOZ_ALWAYS_INLINE MOZ_MUST_USE bool
|
||||
|
|
|
@ -10521,9 +10521,6 @@ main(int argc, char** argv, char** envp)
|
|||
|| !op.addBoolOption('\0', "no-async-stacks", "Disable async stacks")
|
||||
|| !op.addMultiStringOption('\0', "dll", "LIBRARY", "Dynamically load LIBRARY")
|
||||
|| !op.addBoolOption('\0', "suppress-minidump", "Suppress crash minidumps")
|
||||
#ifdef JS_TRACE_LOGGING
|
||||
|| !op.addBoolOption('\0', "enable-tracelogger","Enable Trace Logging")
|
||||
#endif
|
||||
)
|
||||
{
|
||||
return EXIT_FAILURE;
|
||||
|
@ -10587,12 +10584,6 @@ main(int argc, char** argv, char** envp)
|
|||
js::NoteIntentionalCrash();
|
||||
}
|
||||
|
||||
#ifdef JS_TRACE_LOGGING
|
||||
if (op.getBoolOption("enable-tracelogger")) {
|
||||
jit::JitOptions.enableTraceLogger = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!InitSharedObjectMailbox()) {
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -385,8 +385,8 @@ ArgumentsObject::createForIon(JSContext* cx, jit::JitFrameLayout* frame, HandleO
|
|||
}
|
||||
|
||||
/* static */ ArgumentsObject*
|
||||
ArgumentsObject::finishForIon(JSContext* cx, jit::JitFrameLayout* frame,
|
||||
JSObject* scopeChain, ArgumentsObject* obj)
|
||||
ArgumentsObject::finishForIonPure(JSContext* cx, jit::JitFrameLayout* frame,
|
||||
JSObject* scopeChain, ArgumentsObject* obj)
|
||||
{
|
||||
// JIT code calls this directly (no callVM), because it's faster, so we're
|
||||
// not allowed to GC in here.
|
||||
|
|
|
@ -210,7 +210,7 @@ class ArgumentsObject : public NativeObject
|
|||
* Allocate ArgumentsData and fill reserved slots after allocating an
|
||||
* ArgumentsObject in Ion code.
|
||||
*/
|
||||
static ArgumentsObject* finishForIon(JSContext* cx, jit::JitFrameLayout* frame,
|
||||
static ArgumentsObject* finishForIonPure(JSContext* cx, jit::JitFrameLayout* frame,
|
||||
JSObject* scopeChain, ArgumentsObject* obj);
|
||||
|
||||
static ArgumentsObject* createTemplateObject(JSContext* cx, bool mapped);
|
||||
|
|
|
@ -465,7 +465,7 @@ NativeObject::growSlots(JSContext* cx, uint32_t oldCount, uint32_t newCount)
|
|||
}
|
||||
|
||||
/* static */ bool
|
||||
NativeObject::growSlotsDontReportOOM(JSContext* cx, NativeObject* obj, uint32_t newCount)
|
||||
NativeObject::growSlotsPure(JSContext* cx, NativeObject* obj, uint32_t newCount)
|
||||
{
|
||||
// IC code calls this directly.
|
||||
AutoUnsafeCallWithABI unsafe;
|
||||
|
@ -478,7 +478,7 @@ NativeObject::growSlotsDontReportOOM(JSContext* cx, NativeObject* obj, uint32_t
|
|||
}
|
||||
|
||||
/* static */ bool
|
||||
NativeObject::addDenseElementDontReportOOM(JSContext* cx, NativeObject* obj)
|
||||
NativeObject::addDenseElementPure(JSContext* cx, NativeObject* obj)
|
||||
{
|
||||
// IC code calls this directly.
|
||||
AutoUnsafeCallWithABI unsafe;
|
||||
|
|
|
@ -834,14 +834,14 @@ class NativeObject : public ShapedObject
|
|||
* This method is static because it's called from JIT code. On OOM, returns
|
||||
* false without leaving a pending exception on the context.
|
||||
*/
|
||||
static bool growSlotsDontReportOOM(JSContext* cx, NativeObject* obj, uint32_t newCount);
|
||||
static bool growSlotsPure(JSContext* cx, NativeObject* obj, uint32_t newCount);
|
||||
|
||||
/*
|
||||
* Like growSlotsDontReportOOM but for dense elements. This will return
|
||||
* Like growSlotsPure but for dense elements. This will return
|
||||
* false if we failed to allocate a dense element for some reason (OOM, too
|
||||
* many dense elements, non-writable array length, etc).
|
||||
*/
|
||||
static bool addDenseElementDontReportOOM(JSContext* cx, NativeObject* obj);
|
||||
static bool addDenseElementPure(JSContext* cx, NativeObject* obj);
|
||||
|
||||
bool hasDynamicSlots() const { return !!slots_; }
|
||||
|
||||
|
|
|
@ -674,6 +674,7 @@ TraceLoggerThread::startEvent(uint32_t id)
|
|||
mozilla::Maybe<uint32_t> line = p->line();
|
||||
mozilla::Maybe<uint32_t> column = p->column();
|
||||
graph->addTextId(otherId, filename, line, column);
|
||||
p->release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1004,6 +1005,7 @@ TraceLoggerThreadState::init()
|
|||
}
|
||||
if (strstr(options, "EnableGraphFile")) {
|
||||
graphFileEnabled = true;
|
||||
jit::JitOptions.enableTraceLogger = true;
|
||||
}
|
||||
if (strstr(options, "Errors")) {
|
||||
spewErrors = true;
|
||||
|
@ -1254,7 +1256,7 @@ JS::StartTraceLogger(JSContext *cx)
|
|||
|
||||
LockGuard<Mutex> guard(traceLoggerState->lock);
|
||||
traceLoggerState->enableTextIdsForProfiler();
|
||||
JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_ENABLE_TRACELOGGER, true);
|
||||
jit::JitOptions.enableTraceLogger = true;
|
||||
|
||||
// Reset the start time to profile start so it aligns with sampling.
|
||||
traceLoggerState->startupTime = rdtsc();
|
||||
|
@ -1273,7 +1275,7 @@ JS::StopTraceLogger(JSContext *cx)
|
|||
|
||||
LockGuard<Mutex> guard(traceLoggerState->lock);
|
||||
traceLoggerState->disableTextIdsForProfiler();
|
||||
JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_ENABLE_TRACELOGGER, false);
|
||||
jit::JitOptions.enableTraceLogger = false;
|
||||
if (cx->traceLogger) {
|
||||
cx->traceLogger->disable();
|
||||
}
|
||||
|
|
|
@ -101,19 +101,16 @@ skip-if = os == 'win' || os == 'mac' || (os == 'linux' && !debug) # bug 1131110,
|
|||
[test_exnstack.xul]
|
||||
[test_expandosharing.xul]
|
||||
[test_exposeInDerived.xul]
|
||||
[test_getweakmapkeys.xul]
|
||||
[test_localstorage_with_nsEp.xul]
|
||||
[test_matches.xul]
|
||||
[test_nodelists.xul]
|
||||
[test_nsScriptErrorWithStack.html]
|
||||
[test_onGarbageCollection.html]
|
||||
[test_paris_weakmap_keys.xul]
|
||||
[test_precisegc.xul]
|
||||
[test_sandboxImport.xul]
|
||||
[test_scriptSettings.xul]
|
||||
[test_weakmap_keys_preserved.xul]
|
||||
[test_weakmap_keys_preserved2.xul]
|
||||
[test_weakmaps.xul]
|
||||
[test_weakref.xul]
|
||||
[test_windowProxyDeadWrapper.html]
|
||||
[test_wrappers.xul]
|
||||
|
|
|
@ -101,9 +101,12 @@ support-files =
|
|||
# The JS test component we use below is only available in debug builds.
|
||||
[test_getWebIDLCaller.html]
|
||||
skip-if = (debug == false)
|
||||
[test_getweakmapkeys.html]
|
||||
[test_paris_weakmap_keys.html]
|
||||
[test_nac.xhtml]
|
||||
[test_nukeContentWindow.html]
|
||||
[test_sameOriginPolicy.html]
|
||||
[test_sandbox_fetch.html]
|
||||
support-files =
|
||||
../../../../dom/tests/mochitest/fetch/test_fetch_basic.js
|
||||
[test_weakmaps.html]
|
||||
|
|
|
@ -1,35 +1,27 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=688277
|
||||
-->
|
||||
<window title="Mozilla Bug "
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
|
||||
<!-- test results are displayed in the html:body -->
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id="
|
||||
target="_blank">Mozilla Bug 688277</a>
|
||||
</body>
|
||||
|
||||
<!-- test code goes here -->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Tests for nondeterministicGetWeakMapKeys</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
/** Test for Bug 688277 **/
|
||||
|
||||
/* Fail gracefully if junk is passed in. */
|
||||
is(ChromeUtils.nondeterministicGetWeakMapKeys(11), undefined,
|
||||
is(SpecialPowers.nondeterministicGetWeakMapKeys(11), undefined,
|
||||
"nondeterministicGetWeakMapKeys should return undefined for non-objects");
|
||||
is(ChromeUtils.nondeterministicGetWeakMapKeys({}), undefined,
|
||||
is(SpecialPowers.nondeterministicGetWeakMapKeys({}), undefined,
|
||||
"nondeterministicGetWeakMapKeys should return undefined for non-weakmap objects");
|
||||
is(ChromeUtils.nondeterministicGetWeakMapKeys(null), undefined,
|
||||
is(SpecialPowers.nondeterministicGetWeakMapKeys(null), undefined,
|
||||
"nondeterministicGetWeakMapKeys should return undefined for null");
|
||||
|
||||
/* return an empty array for an empty WeakMap */
|
||||
let mempty = new WeakMap();
|
||||
is(ChromeUtils.nondeterministicGetWeakMapKeys(mempty).length, 0,
|
||||
is(SpecialPowers.nondeterministicGetWeakMapKeys(mempty).length, 0,
|
||||
"nondeterministicGetWeakMapKeys should return empty array for empty weakmap");
|
||||
|
||||
/* Test freeing/nonfreeing. */
|
||||
|
@ -50,8 +42,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=688277
|
|||
|
||||
add_elements();
|
||||
|
||||
Cu.schedulePreciseGC(function () {
|
||||
let keys = ChromeUtils.nondeterministicGetWeakMapKeys(m);
|
||||
SpecialPowers.exactGC(function () {
|
||||
let keys = SpecialPowers.nondeterministicGetWeakMapKeys(m);
|
||||
is(liveKeys.length, 1, "Wrong number of live keys.");
|
||||
is(keys.length, 1, "Should have one weak map key.");
|
||||
is(m.get(keys[0]), "live1", "live1 should be live");
|
||||
|
@ -59,7 +51,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=688277
|
|||
});
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
]]>
|
||||
</script>
|
||||
</window>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
</body>
|
||||
</html>
|
|
@ -1,26 +1,22 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=777385
|
||||
-->
|
||||
<window title="Mozilla Bug 777385"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<div></div>
|
||||
<div id="mydivname"></div>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
|
||||
<!-- test results are displayed in the html:body -->
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id="
|
||||
target="_blank">Mozilla Bug 777385</a>
|
||||
</body>
|
||||
|
||||
<!-- test code goes here -->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Tests for WebIDL objects as weak map keys</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
|
||||
/** Test for Bug 777385 **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// We wait to run this until the load event because it needs to access an element.
|
||||
function go() {
|
||||
|
||||
let live_map = new WeakMap;
|
||||
|
||||
let get_div_style = function () {
|
||||
|
@ -72,14 +68,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=777385
|
|||
|
||||
/* Set up for running precise GC/CC then check the results. */
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.exactGC(function () {
|
||||
SpecialPowers.forceCC();
|
||||
SpecialPowers.forceGC();
|
||||
SpecialPowers.forceGC();
|
||||
|
||||
Cu.schedulePreciseGC(function () {
|
||||
SpecialPowers.DOMWindowUtils.cycleCollect();
|
||||
SpecialPowers.DOMWindowUtils.garbageCollect();
|
||||
SpecialPowers.DOMWindowUtils.garbageCollect();
|
||||
|
||||
is(ChromeUtils.nondeterministicGetWeakMapKeys(live_map).length, 2,
|
||||
is(SpecialPowers.nondeterministicGetWeakMapKeys(live_map).length, 2,
|
||||
"Live nsISupports new DOM bindings wrappercached native weak map key should not be removed.");
|
||||
|
||||
is(live_map.get(get_div_style()), 12345, "Live map should have live style with right value after GC.");
|
||||
|
@ -88,6 +82,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=777385
|
|||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
]]>
|
||||
}
|
||||
</script>
|
||||
</window>
|
||||
</head>
|
||||
<div></div>
|
||||
<div id="mydivname"></div>
|
||||
<body onload="go()";>
|
||||
<p id="display"></p>
|
||||
</body>
|
||||
</html>
|
|
@ -1,24 +1,21 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=668855
|
||||
-->
|
||||
<window title="Mozilla Bug "
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
|
||||
<!-- test results are displayed in the html:body -->
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id="
|
||||
target="_blank">Mozilla Bug 668855</a>
|
||||
</body>
|
||||
|
||||
<!-- test code goes here -->
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test Cross-Compartment DOM WeakMaps</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
/** Test for Bug 668855 **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// We wait to run this until the load event because it needs to access an element.
|
||||
function go() {
|
||||
|
||||
/* Create a weak reference, with a single-element weak map. */
|
||||
let make_weak_ref = function (obj) {
|
||||
let m = new WeakMap;
|
||||
|
@ -28,7 +25,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=668855
|
|||
|
||||
/* Check to see if a weak reference is dead. */
|
||||
let weak_ref_dead = function (r) {
|
||||
return ChromeUtils.nondeterministicGetWeakMapKeys(r).length == 0;
|
||||
return SpecialPowers.nondeterministicGetWeakMapKeys(r).length == 0;
|
||||
}
|
||||
|
||||
/* Deterministically grab an arbitrary DOM element. */
|
||||
|
@ -128,7 +125,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=668855
|
|||
"Live key should have the same value in live map.");
|
||||
is(live_map.get(black_key).my_key, 'live_black',
|
||||
"Black key should have the same value in live map.");
|
||||
is(ChromeUtils.nondeterministicGetWeakMapKeys(live_map).length, 2,
|
||||
is(SpecialPowers.nondeterministicGetWeakMapKeys(live_map).length, 2,
|
||||
"Live map should have two entries.");
|
||||
|
||||
// check the live black map
|
||||
|
@ -136,8 +133,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=668855
|
|||
"Live key should have the same value in black map.");
|
||||
is(black_map.get(black_key).my_key, 'black_black',
|
||||
"Black key should have the same value in black map.");
|
||||
is(ChromeUtils.nondeterministicGetWeakMapKeys(black_map).length, 2,
|
||||
"Black map should have two entries.");
|
||||
is(SpecialPowers.nondeterministicGetWeakMapKeys(black_map).length, 2,
|
||||
"Black map should have two entries.");
|
||||
|
||||
};
|
||||
|
||||
|
@ -166,7 +163,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=668855
|
|||
all_ok = all_ok && k.count == i;
|
||||
dom = chainm.get(k).d.firstChild;
|
||||
};
|
||||
ok(all_ok, "Count was invalid on a key in chained weak map entries.");
|
||||
ok(all_ok, "Count was invalid on a key in chained weak map entries.");
|
||||
};
|
||||
|
||||
nested_cc_maps();
|
||||
|
@ -229,27 +226,25 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=668855
|
|||
|
||||
/* set up for running precise GC/CC then checking the results */
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
Cu.schedulePreciseGC(function () {
|
||||
SpecialPowers.DOMWindowUtils.cycleCollect();
|
||||
SpecialPowers.DOMWindowUtils.garbageCollect();
|
||||
SpecialPowers.DOMWindowUtils.garbageCollect();
|
||||
SpecialPowers.exactGC(function () {
|
||||
SpecialPowers.forceCC();
|
||||
SpecialPowers.forceGC();
|
||||
SpecialPowers.forceGC();
|
||||
|
||||
ok(weak_ref_dead(weakref), "Garbage gray cycle should be collected.");
|
||||
|
||||
check_nested_cc_maps();
|
||||
|
||||
is(ChromeUtils.nondeterministicGetWeakMapKeys(garbage_map).length, 0, "Chained garbage weak map entries should not leak.");
|
||||
is(SpecialPowers.nondeterministicGetWeakMapKeys(garbage_map).length, 0, "Chained garbage weak map entries should not leak.");
|
||||
|
||||
check_basic_unit();
|
||||
|
||||
// fixed by Bug 680937
|
||||
is(ChromeUtils.nondeterministicGetWeakMapKeys(wn_garbage_map).length, 0,
|
||||
is(SpecialPowers.nondeterministicGetWeakMapKeys(wn_garbage_map).length, 0,
|
||||
"Chained garbage WN weak map entries should not leak.");
|
||||
|
||||
// fixed by Bug 680937
|
||||
is(ChromeUtils.nondeterministicGetWeakMapKeys(wn_live_map).length, 1,
|
||||
is(SpecialPowers.nondeterministicGetWeakMapKeys(wn_live_map).length, 1,
|
||||
"Live weak map wrapped native key should not be removed.");
|
||||
|
||||
ok(wn_live_map.has(get_live_dom()), "Live map should have live dom.");
|
||||
|
@ -257,6 +252,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=668855
|
|||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
]]>
|
||||
}
|
||||
</script>
|
||||
</window>
|
||||
</head>
|
||||
<div></div>
|
||||
<div id="mydivname"></div>
|
||||
<body onload="go()";>
|
||||
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=668855" target="_blank">Mozilla Bug 668855</a>
|
||||
<p id="display"></p>
|
||||
</body>
|
||||
</html>
|
|
@ -468,13 +468,16 @@ ImageLoader::LoadImage(nsIURI* aURI,
|
|||
return;
|
||||
}
|
||||
|
||||
if (sImages->Contains(aImage->LoadID())) {
|
||||
// This css::URLValue has already been loaded.
|
||||
return;
|
||||
}
|
||||
ImageTableEntry* entry;
|
||||
|
||||
ImageTableEntry* entry = new ImageTableEntry();
|
||||
sImages->Put(aImage->LoadID(), entry);
|
||||
{
|
||||
auto lookup = sImages->LookupForAdd(aImage->LoadID());
|
||||
if (lookup) {
|
||||
// This css::URLValue has already been loaded.
|
||||
return;
|
||||
}
|
||||
entry = lookup.OrInsert([]() { return new ImageTableEntry(); });
|
||||
}
|
||||
|
||||
if (!aURI) {
|
||||
return;
|
||||
|
|
|
@ -81,13 +81,6 @@ nsCSSValue::nsCSSValue(nsCSSValue::Array* aValue, nsCSSUnit aUnit)
|
|||
mValue.mArray->AddRef();
|
||||
}
|
||||
|
||||
nsCSSValue::nsCSSValue(SharedFontList* aValue)
|
||||
: mUnit(eCSSUnit_FontFamilyList)
|
||||
{
|
||||
mValue.mFontFamilyList = aValue;
|
||||
mValue.mFontFamilyList->AddRef();
|
||||
}
|
||||
|
||||
nsCSSValue::nsCSSValue(const nsCSSValue& aCopy)
|
||||
: mUnit(aCopy.mUnit)
|
||||
{
|
||||
|
@ -117,9 +110,6 @@ nsCSSValue::nsCSSValue(const nsCSSValue& aCopy)
|
|||
mValue.mList = aCopy.mValue.mList;
|
||||
mValue.mList->AddRef();
|
||||
}
|
||||
else if (eCSSUnit_ListDep == mUnit) {
|
||||
mValue.mListDependent = aCopy.mValue.mListDependent;
|
||||
}
|
||||
else if (eCSSUnit_SharedList == mUnit) {
|
||||
mValue.mSharedList = aCopy.mValue.mSharedList;
|
||||
mValue.mSharedList->AddRef();
|
||||
|
@ -128,13 +118,6 @@ nsCSSValue::nsCSSValue(const nsCSSValue& aCopy)
|
|||
mValue.mPairList = aCopy.mValue.mPairList;
|
||||
mValue.mPairList->AddRef();
|
||||
}
|
||||
else if (eCSSUnit_PairListDep == mUnit) {
|
||||
mValue.mPairListDependent = aCopy.mValue.mPairListDependent;
|
||||
}
|
||||
else if (eCSSUnit_FontFamilyList == mUnit) {
|
||||
mValue.mFontFamilyList = aCopy.mValue.mFontFamilyList;
|
||||
mValue.mFontFamilyList->AddRef();
|
||||
}
|
||||
else if (eCSSUnit_AtomIdent == mUnit) {
|
||||
mValue.mAtom = aCopy.mValue.mAtom;
|
||||
mValue.mAtom->AddRef();
|
||||
|
@ -168,12 +151,6 @@ nsCSSValue::operator=(nsCSSValue&& aOther)
|
|||
|
||||
bool nsCSSValue::operator==(const nsCSSValue& aOther) const
|
||||
{
|
||||
MOZ_ASSERT(mUnit != eCSSUnit_ListDep &&
|
||||
aOther.mUnit != eCSSUnit_ListDep &&
|
||||
mUnit != eCSSUnit_PairListDep &&
|
||||
aOther.mUnit != eCSSUnit_PairListDep,
|
||||
"don't use operator== with dependent lists");
|
||||
|
||||
if (mUnit == aOther.mUnit) {
|
||||
if (mUnit <= eCSSUnit_DummyInherit) {
|
||||
return true;
|
||||
|
@ -201,10 +178,6 @@ bool nsCSSValue::operator==(const nsCSSValue& aOther) const
|
|||
return nsCSSValuePairList::Equal(mValue.mPairList,
|
||||
aOther.mValue.mPairList);
|
||||
}
|
||||
else if (eCSSUnit_FontFamilyList == mUnit) {
|
||||
return mValue.mFontFamilyList->mNames ==
|
||||
aOther.mValue.mFontFamilyList->mNames;
|
||||
}
|
||||
else if (eCSSUnit_AtomIdent == mUnit) {
|
||||
return mValue.mAtom == aOther.mValue.mAtom;
|
||||
}
|
||||
|
@ -294,8 +267,6 @@ void nsCSSValue::DoReset()
|
|||
DO_RELEASE(mSharedList);
|
||||
} else if (eCSSUnit_PairList == mUnit) {
|
||||
DO_RELEASE(mPairList);
|
||||
} else if (eCSSUnit_FontFamilyList == mUnit) {
|
||||
DO_RELEASE(mFontFamilyList);
|
||||
} else if (eCSSUnit_AtomIdent == mUnit) {
|
||||
DO_RELEASE(mAtom);
|
||||
}
|
||||
|
@ -592,10 +563,6 @@ nsCSSValue::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
|||
case eCSSUnit_Function:
|
||||
case eCSSUnit_Calc:
|
||||
case eCSSUnit_Calc_Plus:
|
||||
case eCSSUnit_Calc_Minus:
|
||||
case eCSSUnit_Calc_Times_L:
|
||||
case eCSSUnit_Calc_Times_R:
|
||||
case eCSSUnit_Calc_Divided:
|
||||
break;
|
||||
|
||||
// Pair
|
||||
|
@ -608,10 +575,6 @@ nsCSSValue::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
|||
n += mValue.mList->SizeOfIncludingThis(aMallocSizeOf);
|
||||
break;
|
||||
|
||||
// ListDep: not measured because it's non-owning.
|
||||
case eCSSUnit_ListDep:
|
||||
break;
|
||||
|
||||
// SharedList
|
||||
case eCSSUnit_SharedList:
|
||||
// Makes more sense not to measure, since it most cases the list
|
||||
|
@ -623,17 +586,6 @@ nsCSSValue::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
|||
n += mValue.mPairList->SizeOfIncludingThis(aMallocSizeOf);
|
||||
break;
|
||||
|
||||
// PairListDep: not measured because it's non-owning.
|
||||
case eCSSUnit_PairListDep:
|
||||
break;
|
||||
|
||||
case eCSSUnit_FontFamilyList:
|
||||
// The SharedFontList is a refcounted object, but is unique per
|
||||
// declaration. We don't measure the references from computed
|
||||
// values.
|
||||
n += mValue.mFontFamilyList->SizeOfIncludingThis(aMallocSizeOf);
|
||||
break;
|
||||
|
||||
// Atom is always shared, and thus should not be counted.
|
||||
case eCSSUnit_AtomIdent:
|
||||
break;
|
||||
|
|
|
@ -295,22 +295,12 @@ enum nsCSSUnit {
|
|||
// Plus, Minus, Times_* and Divided have arrays with exactly 2
|
||||
// elements. a + b + c + d is grouped as ((a + b) + c) + d
|
||||
eCSSUnit_Calc_Plus = 31, // (nsCSSValue::Array*) + node within calc()
|
||||
eCSSUnit_Calc_Minus = 32, // (nsCSSValue::Array*) - within calc
|
||||
eCSSUnit_Calc_Times_L = 33, // (nsCSSValue::Array*) num * val within calc
|
||||
eCSSUnit_Calc_Times_R = 34, // (nsCSSValue::Array*) val * num within calc
|
||||
eCSSUnit_Calc_Divided = 35, // (nsCSSValue::Array*) / within calc
|
||||
|
||||
eCSSUnit_Pair = 50, // (nsCSSValuePair*) pair of values
|
||||
eCSSUnit_List = 53, // (nsCSSValueList*) list of values
|
||||
eCSSUnit_ListDep = 54, // (nsCSSValueList*) same as List
|
||||
// but does not own the list
|
||||
eCSSUnit_SharedList = 55, // (nsCSSValueSharedList*) same as list
|
||||
// but reference counted and shared
|
||||
eCSSUnit_PairList = 56, // (nsCSSValuePairList*) list of value pairs
|
||||
eCSSUnit_PairListDep = 57, // (nsCSSValuePairList*) same as PairList
|
||||
// but does not own the list
|
||||
|
||||
eCSSUnit_FontFamilyList = 58, // (SharedFontList*) value
|
||||
|
||||
// Atom units
|
||||
eCSSUnit_AtomIdent = 60, // (nsAtom*) for its string as an identifier
|
||||
|
@ -385,7 +375,6 @@ public:
|
|||
nsCSSValue(float aValue, nsCSSUnit aUnit);
|
||||
nsCSSValue(const nsString& aValue, nsCSSUnit aUnit);
|
||||
nsCSSValue(Array* aArray, nsCSSUnit aUnit);
|
||||
explicit nsCSSValue(mozilla::SharedFontList* aValue);
|
||||
nsCSSValue(const nsCSSValue& aCopy);
|
||||
nsCSSValue(nsCSSValue&& aOther)
|
||||
: mUnit(aOther.mUnit)
|
||||
|
@ -450,12 +439,12 @@ public:
|
|||
bool IsTimeUnit() const
|
||||
{ return eCSSUnit_Seconds <= mUnit && mUnit <= eCSSUnit_Milliseconds; }
|
||||
bool IsCalcUnit() const
|
||||
{ return eCSSUnit_Calc <= mUnit && mUnit <= eCSSUnit_Calc_Divided; }
|
||||
{ return eCSSUnit_Calc <= mUnit && mUnit <= eCSSUnit_Calc_Plus; }
|
||||
|
||||
bool UnitHasStringValue() const
|
||||
{ return eCSSUnit_String <= mUnit && mUnit <= eCSSUnit_Element; }
|
||||
bool UnitHasArrayValue() const
|
||||
{ return eCSSUnit_Array <= mUnit && mUnit <= eCSSUnit_Calc_Divided; }
|
||||
{ return eCSSUnit_Array <= mUnit && mUnit <= eCSSUnit_Calc_Plus; }
|
||||
|
||||
int32_t GetIntValue() const
|
||||
{
|
||||
|
@ -524,15 +513,6 @@ public:
|
|||
return mValue.mSharedList;
|
||||
}
|
||||
|
||||
mozilla::NotNull<mozilla::SharedFontList*> GetFontFamilyListValue() const
|
||||
{
|
||||
MOZ_ASSERT(mUnit == eCSSUnit_FontFamilyList,
|
||||
"not a font family list value");
|
||||
NS_ASSERTION(mValue.mFontFamilyList != nullptr,
|
||||
"font family list value should never be null");
|
||||
return mozilla::WrapNotNull(mValue.mFontFamilyList);
|
||||
}
|
||||
|
||||
// bodies of these are below
|
||||
inline nsCSSValuePair& GetPairValue();
|
||||
inline const nsCSSValuePair& GetPairValue() const;
|
||||
|
@ -585,7 +565,6 @@ public:
|
|||
// converts the nscoord to pixels
|
||||
void SetIntegerCoordValue(nscoord aCoord);
|
||||
void SetArrayValue(nsCSSValue::Array* aArray, nsCSSUnit aUnit);
|
||||
void SetFontFamilyListValue(already_AddRefed<mozilla::SharedFontList> aFontListValue);
|
||||
void SetPairValue(const nsCSSValuePair* aPair);
|
||||
void SetPairValue(const nsCSSValue& xValue, const nsCSSValue& yValue);
|
||||
void SetSharedListValue(nsCSSValueSharedList* aList);
|
||||
|
@ -604,9 +583,6 @@ public:
|
|||
static already_AddRefed<nsStringBuffer>
|
||||
BufferFromString(const nsString& aValue);
|
||||
|
||||
// Convert the given Ident value into AtomIdent.
|
||||
void AtomizeIdentValue();
|
||||
|
||||
size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||
|
||||
static void
|
||||
|
@ -629,11 +605,8 @@ protected:
|
|||
Array* MOZ_OWNING_REF mArray;
|
||||
nsCSSValuePair_heap* MOZ_OWNING_REF mPair;
|
||||
nsCSSValueList_heap* MOZ_OWNING_REF mList;
|
||||
nsCSSValueList* mListDependent;
|
||||
nsCSSValueSharedList* MOZ_OWNING_REF mSharedList;
|
||||
nsCSSValuePairList_heap* MOZ_OWNING_REF mPairList;
|
||||
nsCSSValuePairList* mPairListDependent;
|
||||
mozilla::SharedFontList* MOZ_OWNING_REF mFontFamilyList;
|
||||
} mValue;
|
||||
};
|
||||
|
||||
|
@ -800,28 +773,18 @@ public:
|
|||
nsCSSValueList* mHead;
|
||||
};
|
||||
|
||||
// This has to be here so that the relationship between nsCSSValueList
|
||||
// and nsCSSValueList_heap is visible.
|
||||
inline nsCSSValueList*
|
||||
nsCSSValue::GetListValue()
|
||||
{
|
||||
if (mUnit == eCSSUnit_List)
|
||||
return mValue.mList;
|
||||
else {
|
||||
MOZ_ASSERT(mUnit == eCSSUnit_ListDep, "not a list value");
|
||||
return mValue.mListDependent;
|
||||
}
|
||||
MOZ_DIAGNOSTIC_ASSERT(mUnit == eCSSUnit_List, "not a list value");
|
||||
return mValue.mList;
|
||||
}
|
||||
|
||||
inline const nsCSSValueList*
|
||||
nsCSSValue::GetListValue() const
|
||||
{
|
||||
if (mUnit == eCSSUnit_List)
|
||||
return mValue.mList;
|
||||
else {
|
||||
MOZ_ASSERT(mUnit == eCSSUnit_ListDep, "not a list value");
|
||||
return mValue.mListDependent;
|
||||
}
|
||||
MOZ_DIAGNOSTIC_ASSERT(mUnit == eCSSUnit_List, "not a list value");
|
||||
return mValue.mList;
|
||||
}
|
||||
|
||||
struct nsCSSValuePair {
|
||||
|
@ -977,23 +940,15 @@ private:
|
|||
inline nsCSSValuePairList*
|
||||
nsCSSValue::GetPairListValue()
|
||||
{
|
||||
if (mUnit == eCSSUnit_PairList)
|
||||
return mValue.mPairList;
|
||||
else {
|
||||
MOZ_ASSERT (mUnit == eCSSUnit_PairListDep, "not a pairlist value");
|
||||
return mValue.mPairListDependent;
|
||||
}
|
||||
MOZ_DIAGNOSTIC_ASSERT(mUnit == eCSSUnit_PairList, "not a pairlist value");
|
||||
return mValue.mPairList;
|
||||
}
|
||||
|
||||
inline const nsCSSValuePairList*
|
||||
nsCSSValue::GetPairListValue() const
|
||||
{
|
||||
if (mUnit == eCSSUnit_PairList)
|
||||
return mValue.mPairList;
|
||||
else {
|
||||
MOZ_ASSERT (mUnit == eCSSUnit_PairListDep, "not a pairlist value");
|
||||
return mValue.mPairListDependent;
|
||||
}
|
||||
MOZ_DIAGNOSTIC_ASSERT(mUnit == eCSSUnit_PairList, "not a pairlist value");
|
||||
return mValue.mPairList;
|
||||
}
|
||||
|
||||
#endif /* nsCSSValue_h___ */
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
# vim: set shiftwidth=8 tabstop=8 autoindent noexpandtab copyindent:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
_DEST_DIR = $(DEPTH)/_tests/reftest
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
# copy harness and the reftest extension bits to $(_DEST_DIR)
|
||||
# This needs to happen after jar.mn handling from rules.mk included above.
|
||||
# The order of the :: rules ensures that.
|
||||
libs::
|
||||
(cd $(DIST)/xpi-stage && tar $(TAR_CREATE_FLAGS) - reftest) | (cd $(_DEST_DIR) && tar -xf -)
|
|
@ -313,8 +313,8 @@ class ReftestArgumentsParser(argparse.ArgumentParser):
|
|||
|
||||
if options.reftestExtensionPath is None:
|
||||
if self.build_obj is not None:
|
||||
reftestExtensionPath = os.path.join(self.build_obj.topobjdir, "_tests",
|
||||
"reftest", "reftest")
|
||||
reftestExtensionPath = os.path.join(self.build_obj.distdir,
|
||||
"xpi-stage", "reftest")
|
||||
else:
|
||||
reftestExtensionPath = os.path.join(here, "reftest")
|
||||
options.reftestExtensionPath = os.path.normpath(reftestExtensionPath)
|
||||
|
@ -322,8 +322,8 @@ class ReftestArgumentsParser(argparse.ArgumentParser):
|
|||
if (options.specialPowersExtensionPath is None and
|
||||
options.suite in ["crashtest", "jstestbrowser"]):
|
||||
if self.build_obj is not None:
|
||||
specialPowersExtensionPath = os.path.join(self.build_obj.topobjdir, "_tests",
|
||||
"reftest", "specialpowers")
|
||||
specialPowersExtensionPath = os.path.join(self.build_obj.distdir,
|
||||
"xpi-stage", "specialpowers")
|
||||
else:
|
||||
specialPowersExtensionPath = os.path.join(here, "specialpowers")
|
||||
options.specialPowersExtensionPath = os.path.normpath(specialPowersExtensionPath)
|
||||
|
|
|
@ -18,6 +18,12 @@ pref("toolkit.telemetry.eventping.enabled", false);
|
|||
|
||||
pref("geckoview.console.enabled", false);
|
||||
|
||||
#ifdef RELEASE_OR_BETA
|
||||
pref("geckoview.logging", "Warn");
|
||||
#else
|
||||
pref("geckoview.logging", "Debug");
|
||||
#endif
|
||||
|
||||
// Disable Web Push until we get it working
|
||||
pref("dom.push.enabled", false);
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
|||
ChromeUtils.import("resource://gre/modules/GeckoViewUtils.jsm");
|
||||
|
||||
/* global debug:false, warn:false */
|
||||
GeckoViewUtils.initLogging("GeckoView.ErrorPageEventHandler", this);
|
||||
GeckoViewUtils.initLogging("ErrorPageEventHandler", this);
|
||||
|
||||
ChromeUtils.defineModuleGetter(this, "SSLExceptions",
|
||||
"resource://gre/modules/SSLExceptions.jsm");
|
||||
|
|
|
@ -229,7 +229,7 @@ class ModuleInfo {
|
|||
if (aPhase.resource && !this._impl) {
|
||||
const scope = {};
|
||||
const global = ChromeUtils.import(aPhase.resource, scope);
|
||||
const tag = this._name.replace("GeckoView", "GeckoView.");
|
||||
const tag = this._name.replace("GeckoView", "");
|
||||
GeckoViewUtils.initLogging(tag, global);
|
||||
this._impl = new scope[this._name](this);
|
||||
}
|
||||
|
@ -308,7 +308,7 @@ function createBrowser() {
|
|||
}
|
||||
|
||||
function startup() {
|
||||
GeckoViewUtils.initLogging("GeckoView.XUL", window);
|
||||
GeckoViewUtils.initLogging("XUL", window);
|
||||
|
||||
const browser = createBrowser();
|
||||
ModuleManager.init(browser, [{
|
||||
|
|
|
@ -8,7 +8,7 @@ ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
|||
ChromeUtils.import("resource://gre/modules/GeckoViewUtils.jsm");
|
||||
|
||||
/* global debug:false, warn:false */
|
||||
GeckoViewUtils.initLogging("GeckoView.ExternalAppService", this);
|
||||
GeckoViewUtils.initLogging("ExternalAppService", this);
|
||||
|
||||
ChromeUtils.defineModuleGetter(this, "EventDispatcher",
|
||||
"resource://gre/modules/Messaging.jsm");
|
||||
|
|
|
@ -3,18 +3,19 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/GeckoViewUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
ActorManagerParent: "resource://gre/modules/ActorManagerParent.jsm",
|
||||
EventDispatcher: "resource://gre/modules/Messaging.jsm",
|
||||
FileSource: "resource://gre/modules/L10nRegistry.jsm",
|
||||
GeckoViewTelemetryController: "resource://gre/modules/GeckoViewTelemetryController.jsm",
|
||||
GeckoViewUtils: "resource://gre/modules/GeckoViewUtils.jsm",
|
||||
L10nRegistry: "resource://gre/modules/L10nRegistry.jsm",
|
||||
Services: "resource://gre/modules/Services.jsm",
|
||||
});
|
||||
|
||||
const {debug, warn} = GeckoViewUtils.initLogging("GeckoViewStartup", this);
|
||||
/* global debug:false, warn:false */
|
||||
GeckoViewUtils.initLogging("Startup", this);
|
||||
|
||||
function GeckoViewStartup() {
|
||||
}
|
||||
|
|
|
@ -705,7 +705,7 @@ public class SessionAccessibility {
|
|||
}
|
||||
|
||||
if (DEBUG) {
|
||||
Log.d(LOGTAG, "performAutoFill(" + id + ", " + value + ')');
|
||||
Log.d(LOGTAG, "performAutoFill(" + id + ')');
|
||||
}
|
||||
|
||||
final EventCallback callback = mAutoFillRoots.get(rootId);
|
||||
|
|
|
@ -536,8 +536,7 @@ public final class SessionTextInput {
|
|||
final CharSequence value = values.valueAt(i);
|
||||
|
||||
if (DEBUG) {
|
||||
Log.d(LOGTAG,
|
||||
"performAutoFill(" + id + ", " + values + ')');
|
||||
Log.d(LOGTAG, "performAutoFill(" + id + ')');
|
||||
}
|
||||
int rootId = id;
|
||||
for (int currentId = id; currentId != View.NO_ID; ) {
|
||||
|
|
|
@ -114,7 +114,7 @@ class GeckoViewAutoFill {
|
|||
this._eventDispatcher.dispatch("GeckoView:AddAutoFill", rootInfo, {
|
||||
onSuccess: responses => {
|
||||
// `responses` is an object with IDs as keys.
|
||||
debug `Performing auto-fill ${responses}`;
|
||||
debug `Performing auto-fill ${Object.keys(responses)}`;
|
||||
|
||||
const AUTOFILL_STATE = "-moz-autofill";
|
||||
const winUtils = window.windowUtils;
|
||||
|
|
|
@ -12,7 +12,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
|||
Services: "resource://gre/modules/Services.jsm"
|
||||
});
|
||||
|
||||
GeckoViewUtils.initLogging("GeckoViewConsole", this);
|
||||
GeckoViewUtils.initLogging("Console", this);
|
||||
|
||||
const LOG_EVENT_TOPIC = "console-api-log-event";
|
||||
|
||||
|
|
|
@ -8,12 +8,12 @@ var EXPORTED_SYMBOLS = ["GeckoViewContentModule"];
|
|||
|
||||
ChromeUtils.import("resource://gre/modules/GeckoViewUtils.jsm");
|
||||
|
||||
GeckoViewUtils.initLogging("GeckoView.Module.[C]", this);
|
||||
GeckoViewUtils.initLogging("Module[C]", this);
|
||||
|
||||
class GeckoViewContentModule {
|
||||
static initLogging(aModuleName) {
|
||||
this._moduleName = aModuleName;
|
||||
const tag = aModuleName.replace("GeckoView", "GeckoView.") + ".[C]";
|
||||
const tag = aModuleName.replace("GeckoView", "") + "[C]";
|
||||
return GeckoViewUtils.initLogging(tag, {});
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ var EXPORTED_SYMBOLS = ["GeckoViewModule"];
|
|||
|
||||
ChromeUtils.import("resource://gre/modules/GeckoViewUtils.jsm");
|
||||
|
||||
GeckoViewUtils.initLogging("GeckoView.Module", this);
|
||||
GeckoViewUtils.initLogging("Module", this);
|
||||
|
||||
class GeckoViewModule {
|
||||
constructor(aModuleInfo) {
|
||||
|
|
|
@ -23,7 +23,7 @@ XPCOMUtils.defineLazyGetter(this, "DebuggerServer", () => {
|
|||
return DebuggerServer;
|
||||
});
|
||||
|
||||
GeckoViewUtils.initLogging("GeckoView.RemoteDebugger", this);
|
||||
GeckoViewUtils.initLogging("RemoteDebugger", this);
|
||||
|
||||
var GeckoViewRemoteDebugger = {
|
||||
observe(aSubject, aTopic, aData) {
|
||||
|
|
|
@ -375,6 +375,8 @@ var GeckoViewUtils = {
|
|||
* @param aScope Scope to add the logging functions to.
|
||||
*/
|
||||
initLogging: function(aTag, aScope) {
|
||||
const tag = "GeckoView." + aTag.replace(/^GeckoView\.?/, "");
|
||||
|
||||
// Only provide two levels for simplicity.
|
||||
// For "info", use "debug" instead.
|
||||
// For "error", throw an actual JS error instead.
|
||||
|
@ -383,7 +385,7 @@ var GeckoViewUtils = {
|
|||
this._log(log.logger, level, strings, exprs);
|
||||
|
||||
XPCOMUtils.defineLazyGetter(log, "logger", _ => {
|
||||
const logger = Log.repository.getLogger(aTag);
|
||||
const logger = Log.repository.getLogger(tag);
|
||||
logger.parent = this.rootLogger;
|
||||
return logger;
|
||||
});
|
||||
|
@ -399,6 +401,7 @@ var GeckoViewUtils = {
|
|||
if (!this._rootLogger) {
|
||||
this._rootLogger = Log.repository.getLogger("GeckoView");
|
||||
this._rootLogger.addAppender(new AndroidAppender());
|
||||
this._rootLogger.manageLevelFromPref("geckoview.logging");
|
||||
}
|
||||
return this._rootLogger;
|
||||
},
|
||||
|
|
|
@ -409,7 +409,19 @@ ARCHIVE_FILES = {
|
|||
'testing/crashtest/crashtests.list',
|
||||
],
|
||||
'dest': 'reftest/tests',
|
||||
}
|
||||
},
|
||||
{
|
||||
'source': buildconfig.topobjdir,
|
||||
'base': 'dist/xpi-stage',
|
||||
'pattern': 'reftest/**',
|
||||
'dest': 'reftest'
|
||||
},
|
||||
{
|
||||
'source': buildconfig.topobjdir,
|
||||
'base': 'dist/xpi-stage',
|
||||
'pattern': 'specialpowers/**',
|
||||
'dest': 'reftest'
|
||||
},
|
||||
],
|
||||
'talos': [
|
||||
{
|
||||
|
|
|
@ -2702,6 +2702,9 @@ class Vendor(MachCommandBase):
|
|||
|
||||
@SubCommand('vendor', 'python',
|
||||
description='Vendor Python packages from pypi.org into third_party/python')
|
||||
@CommandArgument('--with-windows-wheel', action='store_true',
|
||||
help='Vendor a wheel for Windows along with the source package',
|
||||
default=False)
|
||||
@CommandArgument('packages', default=None, nargs='*', help='Packages to vendor. If omitted, packages and their dependencies defined in Pipfile.lock will be vendored. If Pipfile has been modified, then Pipfile.lock will be regenerated. Note that transient dependencies may be updated when running this command.')
|
||||
def vendor_python(self, **kwargs):
|
||||
from mozbuild.vendor_python import VendorPython
|
||||
|
|
|
@ -17,7 +17,7 @@ from mozpack.files import FileFinder
|
|||
|
||||
class VendorPython(MozbuildObject):
|
||||
|
||||
def vendor(self, packages=None):
|
||||
def vendor(self, packages=None, with_windows_wheel=False):
|
||||
self.populate_logger()
|
||||
self.log_manager.enable_unstructured()
|
||||
|
||||
|
@ -25,6 +25,8 @@ class VendorPython(MozbuildObject):
|
|||
self.topsrcdir, os.path.join('third_party', 'python'))
|
||||
|
||||
packages = packages or []
|
||||
if with_windows_wheel and len(packages) != 1:
|
||||
raise Exception('--with-windows-wheel is only supported for a single package!')
|
||||
|
||||
self._activate_virtualenv()
|
||||
pip_compile = os.path.join(self.virtualenv_manager.bin_path, 'pip-compile')
|
||||
|
@ -56,6 +58,21 @@ class VendorPython(MozbuildObject):
|
|||
'--dest', tmp,
|
||||
'--no-binary', ':all:',
|
||||
'--disable-pip-version-check'])
|
||||
if with_windows_wheel:
|
||||
# This is hardcoded to CPython 2.7 for win64, which is good
|
||||
# enough for what we need currently. If we need psutil for Python 3
|
||||
# in the future that coudl be added here as well.
|
||||
self.virtualenv_manager._run_pip([
|
||||
'download',
|
||||
'--dest', tmp,
|
||||
'--no-deps',
|
||||
'--only-binary', ':all:',
|
||||
'--platform', 'win_amd64',
|
||||
'--implementation', 'cp',
|
||||
'--python-version', '27',
|
||||
'--abi', 'none',
|
||||
'--disable-pip-version-check',
|
||||
packages[0]])
|
||||
self._extract(tmp, vendor_dir)
|
||||
|
||||
shutil.copyfile(tmpspec.name, spec)
|
||||
|
@ -83,8 +100,31 @@ class VendorPython(MozbuildObject):
|
|||
"""extract source distribution into vendor directory"""
|
||||
finder = FileFinder(src)
|
||||
for path, _ in finder.find('*'):
|
||||
# packages extract into package-version directory name and we strip the version
|
||||
tld = mozfile.extract(os.path.join(finder.base, path), dest)[0]
|
||||
target = os.path.join(dest, tld.rpartition('-')[0])
|
||||
mozfile.remove(target) # remove existing version of vendored package
|
||||
mozfile.move(tld, target)
|
||||
base, ext = os.path.splitext(path)
|
||||
if ext == '.whl':
|
||||
# Wheels would extract into a directory with the name of the package, but
|
||||
# we want the platform signifiers, minus the version number.
|
||||
# Wheel filenames look like:
|
||||
# {distribution}-{version}(-{build tag})?-{python tag}-{abi tag}-{platform tag}
|
||||
bits = base.split('-')
|
||||
|
||||
# Remove the version number.
|
||||
bits.pop(1)
|
||||
target = os.path.join(dest, '-'.join(bits))
|
||||
mozfile.remove(target) # remove existing version of vendored package
|
||||
os.mkdir(target)
|
||||
mozfile.extract(os.path.join(finder.base, path), target)
|
||||
else:
|
||||
# packages extract into package-version directory name and we strip the version
|
||||
tld = mozfile.extract(os.path.join(finder.base, path), dest)[0]
|
||||
target = os.path.join(dest, tld.rpartition('-')[0])
|
||||
mozfile.remove(target) # remove existing version of vendored package
|
||||
mozfile.move(tld, target)
|
||||
# If any files inside the vendored package were symlinks, turn them into normal files
|
||||
# because hg.mozilla.org forbids symlinks in the repository.
|
||||
link_finder = FileFinder(target)
|
||||
for _, f in link_finder.find('**'):
|
||||
if os.path.islink(f.path):
|
||||
link_target = os.path.realpath(f.path)
|
||||
os.unlink(f.path)
|
||||
shutil.copyfile(link_target, f.path)
|
||||
|
|
|
@ -254,6 +254,12 @@ class VirtualenvManager(object):
|
|||
search path. e.g. "objdir:build" will add $topobjdir/build to the
|
||||
search path.
|
||||
|
||||
windows -- This denotes that the action should only be taken when run
|
||||
on Windows.
|
||||
|
||||
!windows -- This denotes that the action should only be taken when run
|
||||
on non-Windows systems.
|
||||
|
||||
Note that the Python interpreter running this function should be the
|
||||
one from the virtualenv. If it is the system Python or if the
|
||||
environment is not configured properly, packages could be installed
|
||||
|
@ -323,6 +329,13 @@ class VirtualenvManager(object):
|
|||
file=self.log_handle)
|
||||
return False
|
||||
|
||||
if package[0] in ('windows', '!windows'):
|
||||
for_win = not package[0].startswith('!')
|
||||
is_win = sys.platform == 'win32'
|
||||
if is_win == for_win:
|
||||
handle_package(package[1:])
|
||||
return True
|
||||
|
||||
if package[0] == 'objdir':
|
||||
assert len(package) == 2
|
||||
path = os.path.join(self.topobjdir, package[1])
|
||||
|
|
|
@ -9,10 +9,15 @@ import os
|
|||
from mozpack import path as mozpath
|
||||
from mozpack.files import FileFinder
|
||||
|
||||
try:
|
||||
from os import scandir, walk
|
||||
except ImportError:
|
||||
from scandir import scandir, walk
|
||||
|
||||
|
||||
class FilterPath(object):
|
||||
"""Helper class to make comparing and matching file paths easier."""
|
||||
def __init__(self, path, exclude=None):
|
||||
def __init__(self, path):
|
||||
self.path = os.path.normpath(path)
|
||||
self._finder = None
|
||||
|
||||
|
@ -67,6 +72,63 @@ class FilterPath(object):
|
|||
return repr(self.path)
|
||||
|
||||
|
||||
def collapse(paths, base=None, dotfiles=False):
|
||||
"""Given an iterable of paths, collapse them into the smallest possible set
|
||||
of paths that contain the original set (without containing any extra paths).
|
||||
|
||||
For example, if directory 'a' contains two files b.txt and c.txt, calling:
|
||||
|
||||
collapse(['a/b.txt', 'a/c.txt'])
|
||||
|
||||
returns ['a']. But if a third file d.txt also exists, then it will return
|
||||
['a/b.txt', 'a/c.txt'] since ['a'] would also include that extra file.
|
||||
|
||||
:param paths: An iterable of paths (files and directories) to collapse.
|
||||
:returns: The smallest set of paths (files and directories) that contain
|
||||
the original set of paths and only the original set.
|
||||
"""
|
||||
if not paths:
|
||||
if not base:
|
||||
return []
|
||||
|
||||
# Need to test whether directory chain is empty. If it is then bubble
|
||||
# the base back up so that it counts as 'covered'.
|
||||
for _, _, names in walk(base):
|
||||
if names:
|
||||
return []
|
||||
return [base]
|
||||
|
||||
if not base:
|
||||
paths = map(mozpath.abspath, paths)
|
||||
base = mozpath.commonprefix(paths)
|
||||
|
||||
if not os.path.isdir(base):
|
||||
base = os.path.dirname(base)
|
||||
|
||||
covered = set()
|
||||
full = set()
|
||||
for entry in scandir(base):
|
||||
if not dotfiles and entry.name[0] == '.':
|
||||
continue
|
||||
|
||||
path = mozpath.normpath(entry.path)
|
||||
full.add(path)
|
||||
|
||||
if path in paths:
|
||||
# This path was explicitly specified, so just bubble it back up
|
||||
# without recursing down into it (if it was a directory).
|
||||
covered.add(path)
|
||||
elif entry.is_dir():
|
||||
new_paths = [p for p in paths if p.startswith(path)]
|
||||
covered.update(collapse(new_paths, base=path, dotfiles=dotfiles))
|
||||
|
||||
if full == covered:
|
||||
# Every file under this base was covered, so we can collapse them all
|
||||
# up into the base path.
|
||||
return [base]
|
||||
return covered
|
||||
|
||||
|
||||
def filterpaths(paths, linter, **lintargs):
|
||||
"""Filters a list of paths.
|
||||
|
||||
|
@ -143,7 +205,7 @@ def filterpaths(paths, linter, **lintargs):
|
|||
discard.add(path.join(p))
|
||||
|
||||
# Only pass paths we couldn't exclude here to the underlying linter
|
||||
lintargs['exclude'] = [f.path for f in discard]
|
||||
lintargs['exclude'] = collapse([f.path for f in discard])
|
||||
return [f.path for f in keep]
|
||||
|
||||
|
||||
|
|
|
@ -2,10 +2,11 @@
|
|||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import absolute_import, print_function
|
||||
|
||||
import os
|
||||
from copy import deepcopy
|
||||
from fnmatch import fnmatch
|
||||
|
||||
import mozunit
|
||||
import pytest
|
||||
|
@ -102,5 +103,29 @@ def test_filterpaths(filterpaths, test):
|
|||
assert_paths(paths, expected)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('paths,expected', [
|
||||
(['subdir1/*'], ['subdir1']),
|
||||
(['subdir2/*'], ['subdir2']),
|
||||
(['subdir1/*.*', 'subdir1/subdir3/*', 'subdir2/*'], ['subdir1', 'subdir2']),
|
||||
([root + '/*', 'subdir1/*.*', 'subdir1/subdir3/*', 'subdir2/*'], [root]),
|
||||
(['subdir1/b.py', 'subdir1/subdir3'], ['subdir1/b.py', 'subdir1/subdir3']),
|
||||
(['subdir1/b.py', 'subdir1/b.js'], ['subdir1/b.py', 'subdir1/b.js']),
|
||||
])
|
||||
def test_collapse(paths, expected):
|
||||
inputs = []
|
||||
for path in paths:
|
||||
base, name = os.path.split(path)
|
||||
if '*' in name:
|
||||
for n in os.listdir(base):
|
||||
if not fnmatch(n, name):
|
||||
continue
|
||||
inputs.append(os.path.join(base, n))
|
||||
else:
|
||||
inputs.append(path)
|
||||
|
||||
print("inputs: {}".format(inputs))
|
||||
assert_paths(pathutils.collapse(inputs), expected)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
mozunit.main()
|
||||
|
|
|
@ -60,7 +60,7 @@ impl nsCSSValue {
|
|||
pub unsafe fn array_unchecked(&self) -> &nsCSSValue_Array {
|
||||
debug_assert!(
|
||||
nsCSSUnit::eCSSUnit_Array as u32 <= self.mUnit as u32 &&
|
||||
self.mUnit as u32 <= nsCSSUnit::eCSSUnit_Calc_Divided as u32
|
||||
self.mUnit as u32 <= nsCSSUnit::eCSSUnit_Calc_Plus as u32
|
||||
);
|
||||
let array = *self.mValue.mArray.as_ref();
|
||||
debug_assert!(!array.is_null());
|
||||
|
|
|
@ -48,8 +48,8 @@ jobs:
|
|||
- builds/taskcluster_base_win32.py
|
||||
- builds/taskcluster_sub_win32/clang_debug.py
|
||||
toolchains:
|
||||
- win32-clang-cl-st-an
|
||||
- win32-rust
|
||||
- win64-clang-cl-st-an
|
||||
- win64-rust
|
||||
- win64-cbindgen
|
||||
- win64-sccache
|
||||
- win64-node
|
||||
|
@ -79,8 +79,8 @@ jobs:
|
|||
- builds/taskcluster_base_win32.py
|
||||
- builds/taskcluster_sub_win32/clang.py
|
||||
toolchains:
|
||||
- win32-clang-cl-st-an
|
||||
- win32-rust
|
||||
- win64-clang-cl-st-an
|
||||
- win64-rust
|
||||
- win64-cbindgen
|
||||
- win64-sccache
|
||||
- win64-node
|
||||
|
|
|
@ -111,6 +111,7 @@ mochitest-browser-chrome:
|
|||
by-test-platform:
|
||||
linux.*/debug: 16
|
||||
linux64-asan/opt: 16
|
||||
macosx64/debug: 12
|
||||
default: 7
|
||||
max-run-time:
|
||||
by-test-platform:
|
||||
|
|
|
@ -23,27 +23,6 @@ win64-clang-cl:
|
|||
- 'taskcluster/scripts/misc/build-clang-windows-helper64.sh'
|
||||
toolchain-artifact: public/build/clang.tar.bz2
|
||||
|
||||
win32-clang-cl-st-an:
|
||||
description: "Clang-cl static analysis toolchain build"
|
||||
treeherder:
|
||||
kind: build
|
||||
platform: toolchains/opt
|
||||
symbol: TW32(clang-cl-st-an)
|
||||
tier: 1
|
||||
worker-type: aws-provisioner-v1/gecko-{level}-b-win2012
|
||||
worker:
|
||||
max-run-time: 7200
|
||||
env:
|
||||
TOOLTOOL_MANIFEST: "browser/config/tooltool-manifests/win32/build-clang-cl.manifest"
|
||||
run:
|
||||
using: toolchain-script
|
||||
script: build-clang32-st-an-windows.sh
|
||||
resources:
|
||||
- 'build/build-clang/build-clang.py'
|
||||
- 'build/build-clang/clang-win32-st-an.json'
|
||||
- 'taskcluster/scripts/misc/build-clang-windows-helper32.sh'
|
||||
toolchain-artifact: public/build/clang.tar.bz2
|
||||
|
||||
win64-clang-cl-st-an:
|
||||
description: "Clang-cl static analysis toolchain build"
|
||||
treeherder:
|
||||
|
@ -209,30 +188,6 @@ win64-node:
|
|||
arguments: ['win64']
|
||||
toolchain-artifact: public/build/node.tar.bz2
|
||||
|
||||
win32-rust-1.29:
|
||||
description: "rust repack"
|
||||
treeherder:
|
||||
kind: build
|
||||
platform: toolchains/opt
|
||||
symbol: TW32(rust)
|
||||
tier: 1
|
||||
worker-type: aws-provisioner-v1/gecko-{level}-b-linux
|
||||
worker:
|
||||
docker-image: {in-tree: toolchain-build}
|
||||
max-run-time: 7200
|
||||
env:
|
||||
UPLOAD_DIR: artifacts
|
||||
run:
|
||||
using: toolchain-script
|
||||
script: repack_rust.py
|
||||
arguments: [
|
||||
'--channel', '1.29.0',
|
||||
'--host', 'i686-pc-windows-msvc',
|
||||
'--target', 'i686-pc-windows-msvc',
|
||||
]
|
||||
toolchain-alias: win32-rust
|
||||
toolchain-artifact: public/build/rustc.tar.bz2
|
||||
|
||||
mingw32-rust-1.29:
|
||||
description: "rust repack"
|
||||
treeherder:
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
source build/src/taskcluster/scripts/misc/build-clang-windows-helper32.sh clang-win32-st-an.json
|
|
@ -43,3 +43,4 @@ fail-if = true
|
|||
skip-if = toolkit == 'android' # we use the old manifest style on android
|
||||
fail-if = true
|
||||
[test_sanity_waitForCondition.html]
|
||||
[test_getweakmapkeys.html]
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for SpecialPowers.nondeterministicGetWeakMapKeys</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="content" class="testbody">
|
||||
<script type="text/javascript">
|
||||
var emptyMap = new WeakMap;
|
||||
is(SpecialPowers.nondeterministicGetWeakMapKeys(emptyMap).length, 0, "Empty map has no keys");
|
||||
var twoMap = new WeakMap;
|
||||
var x = {};
|
||||
var y = {};
|
||||
twoMap.set(x, 1);
|
||||
twoMap.set(y, 2);
|
||||
var twoMapKeys = SpecialPowers.nondeterministicGetWeakMapKeys(twoMap);
|
||||
is(twoMapKeys.length, 2, "Map with two things should have two keys");
|
||||
ok(twoMapKeys[0] == x || twoMapKeys[1] == x, "One of the keys should be x");
|
||||
ok(twoMapKeys[0] == y || twoMapKeys[1] == y, "One of the keys should be y");
|
||||
</script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -3,16 +3,4 @@
|
|||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
TEST_EXTENSIONS_DIR = $(DEPTH)/testing/specialpowers
|
||||
XPI_PKGNAME = specialpowers@mozilla.org
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
libs-preqs = \
|
||||
$(call mkdir_deps,$(TEST_EXTENSIONS_DIR)) \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(libs-preqs)
|
||||
(cd $(DIST)/xpi-stage && tar $(TAR_CREATE_FLAGS) - $(XPI_NAME)) | (cd $(TEST_EXTENSIONS_DIR) && tar -xf -)
|
||||
$(NSINSTALL) -D $(DEPTH)/_tests/reftest/specialpowers
|
||||
cp -RL $(DEPTH)/testing/specialpowers/specialpowers $(DEPTH)/_tests/reftest
|
||||
|
|
|
@ -1612,6 +1612,10 @@ SpecialPowersAPI.prototype = {
|
|||
Cu.schedulePreciseGC(genGCCallback(callback));
|
||||
},
|
||||
|
||||
nondeterministicGetWeakMapKeys(m) {
|
||||
return ChromeUtils.nondeterministicGetWeakMapKeys(m);
|
||||
},
|
||||
|
||||
getMemoryReports() {
|
||||
try {
|
||||
Cc["@mozilla.org/memory-reporter-manager;1"]
|
||||
|
|
|
@ -27,12 +27,18 @@ class WebPlatformTestsRunnerSetup(MozbuildObject):
|
|||
default_log_type = "mach"
|
||||
|
||||
def kwargs_common(self, kwargs):
|
||||
from mozrunner.devices.android_device import verify_android_device
|
||||
build_path = os.path.join(self.topobjdir, 'build')
|
||||
here = os.path.split(__file__)[0]
|
||||
tests_src_path = os.path.join(here, "tests")
|
||||
if build_path not in sys.path:
|
||||
sys.path.append(build_path)
|
||||
|
||||
if kwargs["product"] == "fennec":
|
||||
verify_android_device(self, install=True, verbose=False, xre=True)
|
||||
if kwargs["certutil_binary"] is None:
|
||||
kwargs["certutil_binary"] = os.path.join(os.environ.get('MOZ_HOST_BIN'), "certutil")
|
||||
|
||||
if kwargs["config"] is None:
|
||||
kwargs["config"] = os.path.join(self.topobjdir, '_tests', 'web-platform', 'wptrunner.local.ini')
|
||||
|
||||
|
|
472
third_party/python/psutil-cp27-none-win_amd64/psutil-5.4.3.dist-info/DESCRIPTION.rst
поставляемый
Normal file
472
third_party/python/psutil-cp27-none-win_amd64/psutil-5.4.3.dist-info/DESCRIPTION.rst
поставляемый
Normal file
|
@ -0,0 +1,472 @@
|
|||
.. image:: https://img.shields.io/travis/giampaolo/psutil/master.svg?maxAge=3600&label=Linux%20/%20OSX
|
||||
:target: https://travis-ci.org/giampaolo/psutil
|
||||
:alt: Linux tests (Travis)
|
||||
|
||||
.. image:: https://img.shields.io/appveyor/ci/giampaolo/psutil/master.svg?maxAge=3600&label=Windows
|
||||
:target: https://ci.appveyor.com/project/giampaolo/psutil
|
||||
:alt: Windows tests (Appveyor)
|
||||
|
||||
.. image:: https://coveralls.io/repos/github/giampaolo/psutil/badge.svg?branch=master
|
||||
:target: https://coveralls.io/github/giampaolo/psutil?branch=master
|
||||
:alt: Test coverage (coverall.io)
|
||||
|
||||
.. image:: https://readthedocs.org/projects/psutil/badge/?version=latest
|
||||
:target: http://psutil.readthedocs.io/en/latest/?badge=latest
|
||||
:alt: Documentation Status
|
||||
|
||||
.. image:: https://img.shields.io/pypi/v/psutil.svg?label=pypi
|
||||
:target: https://pypi.python.org/pypi/psutil/
|
||||
:alt: Latest version
|
||||
|
||||
.. image:: https://img.shields.io/github/stars/giampaolo/psutil.svg
|
||||
:target: https://github.com/giampaolo/psutil/
|
||||
:alt: Github stars
|
||||
|
||||
.. image:: https://img.shields.io/pypi/l/psutil.svg
|
||||
:target: https://pypi.python.org/pypi/psutil/
|
||||
:alt: License
|
||||
|
||||
===========
|
||||
Quick links
|
||||
===========
|
||||
|
||||
- `Home page <https://github.com/giampaolo/psutil>`_
|
||||
- `Install <https://github.com/giampaolo/psutil/blob/master/INSTALL.rst>`_
|
||||
- `Documentation <http://psutil.readthedocs.io>`_
|
||||
- `Download <https://pypi.python.org/pypi?:action=display&name=psutil#downloads>`_
|
||||
- `Forum <http://groups.google.com/group/psutil/topics>`_
|
||||
- `Blog <http://grodola.blogspot.com/search/label/psutil>`_
|
||||
- `Development guide <https://github.com/giampaolo/psutil/blob/master/DEVGUIDE.rst>`_
|
||||
- `What's new <https://github.com/giampaolo/psutil/blob/master/HISTORY.rst>`_
|
||||
|
||||
=======
|
||||
Summary
|
||||
=======
|
||||
|
||||
psutil (process and system utilities) is a cross-platform library for
|
||||
retrieving information on **running processes** and **system utilization**
|
||||
(CPU, memory, disks, network, sensors) in Python.
|
||||
It is useful mainly for **system monitoring**, **profiling and limiting process
|
||||
resources** and **management of running processes**.
|
||||
It implements many functionalities offered by UNIX command line tools such as:
|
||||
ps, top, lsof, netstat, ifconfig, who, df, kill, free, nice, ionice, iostat,
|
||||
iotop, uptime, pidof, tty, taskset, pmap.
|
||||
psutil currently supports the following platforms:
|
||||
|
||||
- **Linux**
|
||||
- **Windows**
|
||||
- **OSX**,
|
||||
- **FreeBSD, OpenBSD**, **NetBSD**
|
||||
- **Sun Solaris**
|
||||
- **AIX**
|
||||
|
||||
...both **32-bit** and **64-bit** architectures, with Python
|
||||
versions from **2.6 to 3.6**.
|
||||
`PyPy <http://pypy.org/>`__ is also known to work.
|
||||
|
||||
====================
|
||||
Example applications
|
||||
====================
|
||||
|
||||
+------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------+
|
||||
| .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/procinfo-small.png | .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/top-small.png |
|
||||
| :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/procinfo.png | :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/top.png |
|
||||
+------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------+
|
||||
| .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/procsmem-small.png | .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/pmap-small.png |
|
||||
| :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/procsmem.png | :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/pmap.png |
|
||||
+------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------+
|
||||
|
||||
Also see `scripts directory <https://github.com/giampaolo/psutil/tree/master/scripts>`__
|
||||
and `doc recipes <http://psutil.readthedocs.io/#recipes/>`__.
|
||||
|
||||
=====================
|
||||
Projects using psutil
|
||||
=====================
|
||||
|
||||
At the time of writing psutil has roughly
|
||||
`2.9 milion downloads <https://github.com/giampaolo/psutil/issues/1053#issuecomment-340166262>`__
|
||||
per month and there are over
|
||||
`6000 open source projects <https://libraries.io/pypi/psutil/dependent_repositories?page=1>`__
|
||||
on github which depend from psutil.
|
||||
Here's some I find particularly interesting:
|
||||
|
||||
- https://github.com/facebook/osquery/
|
||||
- https://github.com/nicolargo/glances
|
||||
- https://github.com/google/grr
|
||||
- https://github.com/Jahaja/psdash
|
||||
- https://github.com/ajenti/ajenti
|
||||
- https://github.com/home-assistant/home-assistant/
|
||||
|
||||
========
|
||||
Portings
|
||||
========
|
||||
|
||||
- Go: https://github.com/shirou/gopsutil
|
||||
- C: https://github.com/hamon-in/cpslib
|
||||
- Node: https://github.com/christkv/node-psutil
|
||||
- Rust: https://github.com/borntyping/rust-psutil
|
||||
- Ruby: https://github.com/spacewander/posixpsutil
|
||||
- Nim: https://github.com/johnscillieri/psutil-nim
|
||||
|
||||
==============
|
||||
Example usages
|
||||
==============
|
||||
|
||||
CPU
|
||||
===
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> import psutil
|
||||
>>> psutil.cpu_times()
|
||||
scputimes(user=3961.46, nice=169.729, system=2150.659, idle=16900.540, iowait=629.59, irq=0.0, softirq=19.42, steal=0.0, guest=0, nice=0.0)
|
||||
>>>
|
||||
>>> for x in range(3):
|
||||
... psutil.cpu_percent(interval=1)
|
||||
...
|
||||
4.0
|
||||
5.9
|
||||
3.8
|
||||
>>>
|
||||
>>> for x in range(3):
|
||||
... psutil.cpu_percent(interval=1, percpu=True)
|
||||
...
|
||||
[4.0, 6.9, 3.7, 9.2]
|
||||
[7.0, 8.5, 2.4, 2.1]
|
||||
[1.2, 9.0, 9.9, 7.2]
|
||||
>>>
|
||||
>>> for x in range(3):
|
||||
... psutil.cpu_times_percent(interval=1, percpu=False)
|
||||
...
|
||||
scputimes(user=1.5, nice=0.0, system=0.5, idle=96.5, iowait=1.5, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0)
|
||||
scputimes(user=1.0, nice=0.0, system=0.0, idle=99.0, iowait=0.0, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0)
|
||||
scputimes(user=2.0, nice=0.0, system=0.0, idle=98.0, iowait=0.0, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0)
|
||||
>>>
|
||||
>>> psutil.cpu_count()
|
||||
4
|
||||
>>> psutil.cpu_count(logical=False)
|
||||
2
|
||||
>>>
|
||||
>>> psutil.cpu_stats()
|
||||
scpustats(ctx_switches=20455687, interrupts=6598984, soft_interrupts=2134212, syscalls=0)
|
||||
>>>
|
||||
>>> psutil.cpu_freq()
|
||||
scpufreq(current=931.42925, min=800.0, max=3500.0)
|
||||
>>>
|
||||
|
||||
Memory
|
||||
======
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> import psutil
|
||||
>>> psutil.virtual_memory()
|
||||
svmem(total=10367352832, available=6472179712, percent=37.6, used=8186245120, free=2181107712, active=4748992512, inactive=2758115328, buffers=790724608, cached=3500347392, shared=787554304)
|
||||
>>> psutil.swap_memory()
|
||||
sswap(total=2097147904, used=296128512, free=1801019392, percent=14.1, sin=304193536, sout=677842944)
|
||||
>>>
|
||||
|
||||
Disks
|
||||
=====
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> import psutil
|
||||
>>> psutil.disk_partitions()
|
||||
[sdiskpart(device='/dev/sda1', mountpoint='/', fstype='ext4', opts='rw,nosuid'),
|
||||
sdiskpart(device='/dev/sda2', mountpoint='/home', fstype='ext, opts='rw')]
|
||||
>>>
|
||||
>>> psutil.disk_usage('/')
|
||||
sdiskusage(total=21378641920, used=4809781248, free=15482871808, percent=22.5)
|
||||
>>>
|
||||
>>> psutil.disk_io_counters(perdisk=False)
|
||||
sdiskio(read_count=719566, write_count=1082197, read_bytes=18626220032, write_bytes=24081764352, read_time=5023392, write_time=63199568, read_merged_count=619166, write_merged_count=812396, busy_time=4523412)
|
||||
>>>
|
||||
|
||||
Network
|
||||
=======
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> import psutil
|
||||
>>> psutil.net_io_counters(pernic=True)
|
||||
{'eth0': netio(bytes_sent=485291293, bytes_recv=6004858642, packets_sent=3251564, packets_recv=4787798, errin=0, errout=0, dropin=0, dropout=0),
|
||||
'lo': netio(bytes_sent=2838627, bytes_recv=2838627, packets_sent=30567, packets_recv=30567, errin=0, errout=0, dropin=0, dropout=0)}
|
||||
>>>
|
||||
>>> psutil.net_connections()
|
||||
[sconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=48776), raddr=addr(ip='93.186.135.91', port=80), status='ESTABLISHED', pid=1254),
|
||||
sconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=43761), raddr=addr(ip='72.14.234.100', port=80), status='CLOSING', pid=2987),
|
||||
sconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=60759), raddr=addr(ip='72.14.234.104', port=80), status='ESTABLISHED', pid=None),
|
||||
sconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=51314), raddr=addr(ip='72.14.234.83', port=443), status='SYN_SENT', pid=None)
|
||||
...]
|
||||
>>>
|
||||
>>> psutil.net_if_addrs()
|
||||
{'lo': [snic(family=<AddressFamily.AF_INET: 2>, address='127.0.0.1', netmask='255.0.0.0', broadcast='127.0.0.1', ptp=None),
|
||||
snic(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None, ptp=None),
|
||||
snic(family=<AddressFamily.AF_LINK: 17>, address='00:00:00:00:00:00', netmask=None, broadcast='00:00:00:00:00:00', ptp=None)],
|
||||
'wlan0': [snic(family=<AddressFamily.AF_INET: 2>, address='192.168.1.3', netmask='255.255.255.0', broadcast='192.168.1.255', ptp=None),
|
||||
snic(family=<AddressFamily.AF_INET6: 10>, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None, ptp=None),
|
||||
snic(family=<AddressFamily.AF_LINK: 17>, address='c4:85:08:45:06:41', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)]}
|
||||
>>>
|
||||
>>> psutil.net_if_stats()
|
||||
{'eth0': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=100, mtu=1500),
|
||||
'lo': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_UNKNOWN: 0>, speed=0, mtu=65536)}
|
||||
>>>
|
||||
|
||||
Sensors
|
||||
=======
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> import psutil
|
||||
>>> psutil.sensors_temperatures()
|
||||
{'acpitz': [shwtemp(label='', current=47.0, high=103.0, critical=103.0)],
|
||||
'asus': [shwtemp(label='', current=47.0, high=None, critical=None)],
|
||||
'coretemp': [shwtemp(label='Physical id 0', current=52.0, high=100.0, critical=100.0),
|
||||
shwtemp(label='Core 0', current=45.0, high=100.0, critical=100.0),
|
||||
shwtemp(label='Core 1', current=52.0, high=100.0, critical=100.0),
|
||||
shwtemp(label='Core 2', current=45.0, high=100.0, critical=100.0),
|
||||
shwtemp(label='Core 3', current=47.0, high=100.0, critical=100.0)]}
|
||||
>>>
|
||||
>>> psutil.sensors_fans()
|
||||
{'asus': [sfan(label='cpu_fan', current=3200)]}
|
||||
>>>
|
||||
>>> psutil.sensors_battery()
|
||||
sbattery(percent=93, secsleft=16628, power_plugged=False)
|
||||
>>>
|
||||
|
||||
Other system info
|
||||
=================
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> import psutil
|
||||
>>> psutil.users()
|
||||
[suser(name='giampaolo', terminal='pts/2', host='localhost', started=1340737536.0, pid=1352),
|
||||
suser(name='giampaolo', terminal='pts/3', host='localhost', started=1340737792.0, pid=1788)]
|
||||
>>>
|
||||
>>> psutil.boot_time()
|
||||
1365519115.0
|
||||
>>>
|
||||
|
||||
Process management
|
||||
==================
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> import psutil
|
||||
>>> psutil.pids()
|
||||
[1, 2, 3, 4, 5, 6, 7, 46, 48, 50, 51, 178, 182, 222, 223, 224, 268, 1215, 1216, 1220, 1221, 1243, 1244,
|
||||
1301, 1601, 2237, 2355, 2637, 2774, 3932, 4176, 4177, 4185, 4187, 4189, 4225, 4243, 4245, 4263, 4282,
|
||||
4306, 4311, 4312, 4313, 4314, 4337, 4339, 4357, 4358, 4363, 4383, 4395, 4408, 4433, 4443, 4445, 4446,
|
||||
5167, 5234, 5235, 5252, 5318, 5424, 5644, 6987, 7054, 7055, 7071]
|
||||
>>>
|
||||
>>> p = psutil.Process(7055)
|
||||
>>> p.name()
|
||||
'python'
|
||||
>>> p.exe()
|
||||
'/usr/bin/python'
|
||||
>>> p.cwd()
|
||||
'/home/giampaolo'
|
||||
>>> p.cmdline()
|
||||
['/usr/bin/python', 'main.py']
|
||||
>>>
|
||||
>>> p.pid
|
||||
7055
|
||||
>>> p.ppid()
|
||||
7054
|
||||
>>> p.parent()
|
||||
<psutil.Process(pid=7054, name='bash') at 140008329539408>
|
||||
>>> p.children()
|
||||
[<psutil.Process(pid=8031, name='python') at 14020832451977>,
|
||||
<psutil.Process(pid=8044, name='python') at 19229444921932>]
|
||||
>>>
|
||||
>>> p.status()
|
||||
'running'
|
||||
>>> p.username()
|
||||
'giampaolo'
|
||||
>>> p.create_time()
|
||||
1267551141.5019531
|
||||
>>> p.terminal()
|
||||
'/dev/pts/0'
|
||||
>>>
|
||||
>>> p.uids()
|
||||
puids(real=1000, effective=1000, saved=1000)
|
||||
>>> p.gids()
|
||||
pgids(real=1000, effective=1000, saved=1000)
|
||||
>>>
|
||||
>>> p.cpu_times()
|
||||
pcputimes(user=1.02, system=0.31, children_user=0.32, children_system=0.1)
|
||||
>>> p.cpu_percent(interval=1.0)
|
||||
12.1
|
||||
>>> p.cpu_affinity()
|
||||
[0, 1, 2, 3]
|
||||
>>> p.cpu_affinity([0, 1]) # set
|
||||
>>> p.cpu_num()
|
||||
1
|
||||
>>>
|
||||
>>> p.memory_info()
|
||||
pmem(rss=10915840, vms=67608576, shared=3313664, text=2310144, lib=0, data=7262208, dirty=0)
|
||||
>>> p.memory_full_info() # "real" USS memory usage (Linux, OSX, Win only)
|
||||
pfullmem(rss=10199040, vms=52133888, shared=3887104, text=2867200, lib=0, data=5967872, dirty=0, uss=6545408, pss=6872064, swap=0)
|
||||
>>> p.memory_percent()
|
||||
0.7823
|
||||
>>> p.memory_maps()
|
||||
[pmmap_grouped(path='/lib/x8664-linux-gnu/libutil-2.15.so', rss=32768, size=2125824, pss=32768, shared_clean=0, shared_dirty=0, private_clean=20480, private_dirty=12288, referenced=32768, anonymous=12288, swap=0),
|
||||
pmmap_grouped(path='/lib/x8664-linux-gnu/libc-2.15.so', rss=3821568, size=3842048, pss=3821568, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=3821568, referenced=3575808, anonymous=3821568, swap=0),
|
||||
pmmap_grouped(path='/lib/x8664-linux-gnu/libcrypto.so.0.1', rss=34124, rss=32768, size=2134016, pss=15360, shared_clean=24576, shared_dirty=0, private_clean=0, private_dirty=8192, referenced=24576, anonymous=8192, swap=0),
|
||||
pmmap_grouped(path='[heap]', rss=32768, size=139264, pss=32768, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=32768, referenced=32768, anonymous=32768, swap=0),
|
||||
pmmap_grouped(path='[stack]', rss=2465792, size=2494464, pss=2465792, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=2465792, referenced=2277376, anonymous=2465792, swap=0),
|
||||
...]
|
||||
>>>
|
||||
>>> p.io_counters()
|
||||
pio(read_count=478001, write_count=59371, read_bytes=700416, write_bytes=69632, read_chars=456232, write_chars=517543)
|
||||
>>>
|
||||
>>> p.open_files()
|
||||
[popenfile(path='/home/giampaolo/svn/psutil/setup.py', fd=3, position=0, mode='r', flags=32768),
|
||||
popenfile(path='/var/log/monitd', fd=4, position=235542, mode='a', flags=33793)]
|
||||
>>>
|
||||
>>> p.connections()
|
||||
[pconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=48776), raddr=addr(ip='93.186.135.91', port=80), status='ESTABLISHED'),
|
||||
pconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=43761), raddr=addr(ip='72.14.234.100', port=80), status='CLOSING'),
|
||||
pconn(fd=119, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=60759), raddr=addr(ip='72.14.234.104', port=80), status='ESTABLISHED'),
|
||||
pconn(fd=123, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=51314), raddr=addr(ip='72.14.234.83', port=443), status='SYN_SENT')]
|
||||
>>>
|
||||
>>> p.num_threads()
|
||||
4
|
||||
>>> p.num_fds()
|
||||
8
|
||||
>>> p.threads()
|
||||
[pthread(id=5234, user_time=22.5, system_time=9.2891),
|
||||
pthread(id=5235, user_time=0.0, system_time=0.0),
|
||||
pthread(id=5236, user_time=0.0, system_time=0.0),
|
||||
pthread(id=5237, user_time=0.0707, system_time=1.1)]
|
||||
>>>
|
||||
>>> p.num_ctx_switches()
|
||||
pctxsw(voluntary=78, involuntary=19)
|
||||
>>>
|
||||
>>> p.nice()
|
||||
0
|
||||
>>> p.nice(10) # set
|
||||
>>>
|
||||
>>> p.ionice(psutil.IOPRIO_CLASS_IDLE) # IO priority (Win and Linux only)
|
||||
>>> p.ionice()
|
||||
pionice(ioclass=<IOPriority.IOPRIO_CLASS_IDLE: 3>, value=0)
|
||||
>>>
|
||||
>>> p.rlimit(psutil.RLIMIT_NOFILE, (5, 5)) # set resource limits (Linux only)
|
||||
>>> p.rlimit(psutil.RLIMIT_NOFILE)
|
||||
(5, 5)
|
||||
>>>
|
||||
>>> p.environ()
|
||||
{'LC_PAPER': 'it_IT.UTF-8', 'SHELL': '/bin/bash', 'GREP_OPTIONS': '--color=auto',
|
||||
'XDG_CONFIG_DIRS': '/etc/xdg/xdg-ubuntu:/usr/share/upstart/xdg:/etc/xdg', 'COLORTERM': 'gnome-terminal',
|
||||
...}
|
||||
>>>
|
||||
>>> p.as_dict()
|
||||
{'status': 'running', 'num_ctx_switches': pctxsw(voluntary=63, involuntary=1), 'pid': 5457, ...}
|
||||
>>> p.is_running()
|
||||
True
|
||||
>>> p.suspend()
|
||||
>>> p.resume()
|
||||
>>>
|
||||
>>> p.terminate()
|
||||
>>> p.wait(timeout=3)
|
||||
0
|
||||
>>>
|
||||
>>> psutil.test()
|
||||
USER PID %CPU %MEM VSZ RSS TTY START TIME COMMAND
|
||||
root 1 0.0 0.0 24584 2240 Jun17 00:00 init
|
||||
root 2 0.0 0.0 0 0 Jun17 00:00 kthreadd
|
||||
root 3 0.0 0.0 0 0 Jun17 00:05 ksoftirqd/0
|
||||
...
|
||||
giampaolo 31475 0.0 0.0 20760 3024 /dev/pts/0 Jun19 00:00 python2.4
|
||||
giampaolo 31721 0.0 2.2 773060 181896 00:04 10:30 chrome
|
||||
root 31763 0.0 0.0 0 0 00:05 00:00 kworker/0:1
|
||||
>>>
|
||||
|
||||
Further process APIs
|
||||
====================
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> import psutil
|
||||
>>> for proc in psutil.process_iter(attrs=['pid', 'name']):
|
||||
... print(proc.info)
|
||||
...
|
||||
{'pid': 1, 'name': 'systemd'}
|
||||
{'pid': 2, 'name': 'kthreadd'}
|
||||
{'pid': 3, 'name': 'ksoftirqd/0'}
|
||||
...
|
||||
>>>
|
||||
>>> psutil.pid_exists(3)
|
||||
True
|
||||
>>>
|
||||
>>> def on_terminate(proc):
|
||||
... print("process {} terminated".format(proc))
|
||||
...
|
||||
>>> # waits for multiple processes to terminate
|
||||
>>> gone, alive = psutil.wait_procs(procs_list, timeout=3, callback=on_terminate)
|
||||
>>>
|
||||
|
||||
Popen wrapper:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> import psutil
|
||||
>>> from subprocess import PIPE
|
||||
>>> p = psutil.Popen(["/usr/bin/python", "-c", "print('hello')"], stdout=PIPE)
|
||||
>>> p.name()
|
||||
'python'
|
||||
>>> p.username()
|
||||
'giampaolo'
|
||||
>>> p.communicate()
|
||||
('hello\n', None)
|
||||
>>> p.wait(timeout=2)
|
||||
0
|
||||
>>>
|
||||
|
||||
Windows services
|
||||
================
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> list(psutil.win_service_iter())
|
||||
[<WindowsService(name='AeLookupSvc', display_name='Application Experience') at 38850096>,
|
||||
<WindowsService(name='ALG', display_name='Application Layer Gateway Service') at 38850128>,
|
||||
<WindowsService(name='APNMCP', display_name='Ask Update Service') at 38850160>,
|
||||
<WindowsService(name='AppIDSvc', display_name='Application Identity') at 38850192>,
|
||||
...]
|
||||
>>> s = psutil.win_service_get('alg')
|
||||
>>> s.as_dict()
|
||||
{'binpath': 'C:\\Windows\\System32\\alg.exe',
|
||||
'description': 'Provides support for 3rd party protocol plug-ins for Internet Connection Sharing',
|
||||
'display_name': 'Application Layer Gateway Service',
|
||||
'name': 'alg',
|
||||
'pid': None,
|
||||
'start_type': 'manual',
|
||||
'status': 'stopped',
|
||||
'username': 'NT AUTHORITY\\LocalService'}
|
||||
|
||||
Other samples
|
||||
=============
|
||||
|
||||
See `doc recipes <http://psutil.readthedocs.io/#recipes>`__.
|
||||
|
||||
======
|
||||
Author
|
||||
======
|
||||
|
||||
psutil was created and is maintained by
|
||||
`Giampaolo Rodola' <http://grodola.blogspot.com/p/about.html>`__.
|
||||
A lot of time and effort went into making psutil as it is right now.
|
||||
If you feel psutil is useful to you or your business and want to support its
|
||||
future development please consider donating me
|
||||
(`Giampaolo <http://grodola.blogspot.com/p/about.html>`__) some money.
|
||||
|
||||
.. image:: http://www.paypal.com/en_US/i/btn/x-click-but04.gif
|
||||
:target: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A9ZS7PKKRM3S8
|
||||
:alt: Donate via PayPal
|
||||
|
||||
Don't want to donate money? Then maybe you could `write me a recommendation on Linkedin <https://www.linkedin.com/in/grodola>`_.
|
||||
|
||||
|
524
third_party/python/psutil-cp27-none-win_amd64/psutil-5.4.3.dist-info/METADATA
поставляемый
Normal file
524
third_party/python/psutil-cp27-none-win_amd64/psutil-5.4.3.dist-info/METADATA
поставляемый
Normal file
|
@ -0,0 +1,524 @@
|
|||
Metadata-Version: 2.0
|
||||
Name: psutil
|
||||
Version: 5.4.3
|
||||
Summary: Cross-platform lib for process and system monitoring in Python.
|
||||
Home-page: https://github.com/giampaolo/psutil
|
||||
Author: Giampaolo Rodola
|
||||
Author-email: g.rodola@gmail.com
|
||||
License: BSD
|
||||
Keywords: ps,top,kill,free,lsof,netstat,nice,tty,ionice,uptime,taskmgr,process,df,iotop,iostat,ifconfig,taskset,who,pidof,pmap,smem,pstree,monitoring,ulimit,prlimit,smem
|
||||
Platform: Platform Independent
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Environment :: Console
|
||||
Classifier: Environment :: Win32 (MS Windows)
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: Intended Audience :: Information Technology
|
||||
Classifier: Intended Audience :: System Administrators
|
||||
Classifier: License :: OSI Approved :: BSD License
|
||||
Classifier: Operating System :: MacOS :: MacOS X
|
||||
Classifier: Operating System :: Microsoft :: Windows :: Windows NT/2000
|
||||
Classifier: Operating System :: Microsoft
|
||||
Classifier: Operating System :: OS Independent
|
||||
Classifier: Operating System :: POSIX :: BSD :: FreeBSD
|
||||
Classifier: Operating System :: POSIX :: BSD :: NetBSD
|
||||
Classifier: Operating System :: POSIX :: BSD :: OpenBSD
|
||||
Classifier: Operating System :: POSIX :: BSD
|
||||
Classifier: Operating System :: POSIX :: Linux
|
||||
Classifier: Operating System :: POSIX :: SunOS/Solaris
|
||||
Classifier: Operating System :: POSIX
|
||||
Classifier: Programming Language :: C
|
||||
Classifier: Programming Language :: Python :: 2
|
||||
Classifier: Programming Language :: Python :: 2.6
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.4
|
||||
Classifier: Programming Language :: Python :: 3.5
|
||||
Classifier: Programming Language :: Python :: 3.6
|
||||
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
||||
Classifier: Topic :: Software Development :: Libraries
|
||||
Classifier: Topic :: System :: Benchmark
|
||||
Classifier: Topic :: System :: Hardware
|
||||
Classifier: Topic :: System :: Monitoring
|
||||
Classifier: Topic :: System :: Networking :: Monitoring
|
||||
Classifier: Topic :: System :: Networking
|
||||
Classifier: Topic :: System :: Operating System
|
||||
Classifier: Topic :: System :: Systems Administration
|
||||
Classifier: Topic :: Utilities
|
||||
Provides-Extra: enum
|
||||
Requires-Dist: enum34; extra == 'enum'
|
||||
|
||||
.. image:: https://img.shields.io/travis/giampaolo/psutil/master.svg?maxAge=3600&label=Linux%20/%20OSX
|
||||
:target: https://travis-ci.org/giampaolo/psutil
|
||||
:alt: Linux tests (Travis)
|
||||
|
||||
.. image:: https://img.shields.io/appveyor/ci/giampaolo/psutil/master.svg?maxAge=3600&label=Windows
|
||||
:target: https://ci.appveyor.com/project/giampaolo/psutil
|
||||
:alt: Windows tests (Appveyor)
|
||||
|
||||
.. image:: https://coveralls.io/repos/github/giampaolo/psutil/badge.svg?branch=master
|
||||
:target: https://coveralls.io/github/giampaolo/psutil?branch=master
|
||||
:alt: Test coverage (coverall.io)
|
||||
|
||||
.. image:: https://readthedocs.org/projects/psutil/badge/?version=latest
|
||||
:target: http://psutil.readthedocs.io/en/latest/?badge=latest
|
||||
:alt: Documentation Status
|
||||
|
||||
.. image:: https://img.shields.io/pypi/v/psutil.svg?label=pypi
|
||||
:target: https://pypi.python.org/pypi/psutil/
|
||||
:alt: Latest version
|
||||
|
||||
.. image:: https://img.shields.io/github/stars/giampaolo/psutil.svg
|
||||
:target: https://github.com/giampaolo/psutil/
|
||||
:alt: Github stars
|
||||
|
||||
.. image:: https://img.shields.io/pypi/l/psutil.svg
|
||||
:target: https://pypi.python.org/pypi/psutil/
|
||||
:alt: License
|
||||
|
||||
===========
|
||||
Quick links
|
||||
===========
|
||||
|
||||
- `Home page <https://github.com/giampaolo/psutil>`_
|
||||
- `Install <https://github.com/giampaolo/psutil/blob/master/INSTALL.rst>`_
|
||||
- `Documentation <http://psutil.readthedocs.io>`_
|
||||
- `Download <https://pypi.python.org/pypi?:action=display&name=psutil#downloads>`_
|
||||
- `Forum <http://groups.google.com/group/psutil/topics>`_
|
||||
- `Blog <http://grodola.blogspot.com/search/label/psutil>`_
|
||||
- `Development guide <https://github.com/giampaolo/psutil/blob/master/DEVGUIDE.rst>`_
|
||||
- `What's new <https://github.com/giampaolo/psutil/blob/master/HISTORY.rst>`_
|
||||
|
||||
=======
|
||||
Summary
|
||||
=======
|
||||
|
||||
psutil (process and system utilities) is a cross-platform library for
|
||||
retrieving information on **running processes** and **system utilization**
|
||||
(CPU, memory, disks, network, sensors) in Python.
|
||||
It is useful mainly for **system monitoring**, **profiling and limiting process
|
||||
resources** and **management of running processes**.
|
||||
It implements many functionalities offered by UNIX command line tools such as:
|
||||
ps, top, lsof, netstat, ifconfig, who, df, kill, free, nice, ionice, iostat,
|
||||
iotop, uptime, pidof, tty, taskset, pmap.
|
||||
psutil currently supports the following platforms:
|
||||
|
||||
- **Linux**
|
||||
- **Windows**
|
||||
- **OSX**,
|
||||
- **FreeBSD, OpenBSD**, **NetBSD**
|
||||
- **Sun Solaris**
|
||||
- **AIX**
|
||||
|
||||
...both **32-bit** and **64-bit** architectures, with Python
|
||||
versions from **2.6 to 3.6**.
|
||||
`PyPy <http://pypy.org/>`__ is also known to work.
|
||||
|
||||
====================
|
||||
Example applications
|
||||
====================
|
||||
|
||||
+------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------+
|
||||
| .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/procinfo-small.png | .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/top-small.png |
|
||||
| :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/procinfo.png | :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/top.png |
|
||||
+------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------+
|
||||
| .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/procsmem-small.png | .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/pmap-small.png |
|
||||
| :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/procsmem.png | :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/pmap.png |
|
||||
+------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------+
|
||||
|
||||
Also see `scripts directory <https://github.com/giampaolo/psutil/tree/master/scripts>`__
|
||||
and `doc recipes <http://psutil.readthedocs.io/#recipes/>`__.
|
||||
|
||||
=====================
|
||||
Projects using psutil
|
||||
=====================
|
||||
|
||||
At the time of writing psutil has roughly
|
||||
`2.9 milion downloads <https://github.com/giampaolo/psutil/issues/1053#issuecomment-340166262>`__
|
||||
per month and there are over
|
||||
`6000 open source projects <https://libraries.io/pypi/psutil/dependent_repositories?page=1>`__
|
||||
on github which depend from psutil.
|
||||
Here's some I find particularly interesting:
|
||||
|
||||
- https://github.com/facebook/osquery/
|
||||
- https://github.com/nicolargo/glances
|
||||
- https://github.com/google/grr
|
||||
- https://github.com/Jahaja/psdash
|
||||
- https://github.com/ajenti/ajenti
|
||||
- https://github.com/home-assistant/home-assistant/
|
||||
|
||||
========
|
||||
Portings
|
||||
========
|
||||
|
||||
- Go: https://github.com/shirou/gopsutil
|
||||
- C: https://github.com/hamon-in/cpslib
|
||||
- Node: https://github.com/christkv/node-psutil
|
||||
- Rust: https://github.com/borntyping/rust-psutil
|
||||
- Ruby: https://github.com/spacewander/posixpsutil
|
||||
- Nim: https://github.com/johnscillieri/psutil-nim
|
||||
|
||||
==============
|
||||
Example usages
|
||||
==============
|
||||
|
||||
CPU
|
||||
===
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> import psutil
|
||||
>>> psutil.cpu_times()
|
||||
scputimes(user=3961.46, nice=169.729, system=2150.659, idle=16900.540, iowait=629.59, irq=0.0, softirq=19.42, steal=0.0, guest=0, nice=0.0)
|
||||
>>>
|
||||
>>> for x in range(3):
|
||||
... psutil.cpu_percent(interval=1)
|
||||
...
|
||||
4.0
|
||||
5.9
|
||||
3.8
|
||||
>>>
|
||||
>>> for x in range(3):
|
||||
... psutil.cpu_percent(interval=1, percpu=True)
|
||||
...
|
||||
[4.0, 6.9, 3.7, 9.2]
|
||||
[7.0, 8.5, 2.4, 2.1]
|
||||
[1.2, 9.0, 9.9, 7.2]
|
||||
>>>
|
||||
>>> for x in range(3):
|
||||
... psutil.cpu_times_percent(interval=1, percpu=False)
|
||||
...
|
||||
scputimes(user=1.5, nice=0.0, system=0.5, idle=96.5, iowait=1.5, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0)
|
||||
scputimes(user=1.0, nice=0.0, system=0.0, idle=99.0, iowait=0.0, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0)
|
||||
scputimes(user=2.0, nice=0.0, system=0.0, idle=98.0, iowait=0.0, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0)
|
||||
>>>
|
||||
>>> psutil.cpu_count()
|
||||
4
|
||||
>>> psutil.cpu_count(logical=False)
|
||||
2
|
||||
>>>
|
||||
>>> psutil.cpu_stats()
|
||||
scpustats(ctx_switches=20455687, interrupts=6598984, soft_interrupts=2134212, syscalls=0)
|
||||
>>>
|
||||
>>> psutil.cpu_freq()
|
||||
scpufreq(current=931.42925, min=800.0, max=3500.0)
|
||||
>>>
|
||||
|
||||
Memory
|
||||
======
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> import psutil
|
||||
>>> psutil.virtual_memory()
|
||||
svmem(total=10367352832, available=6472179712, percent=37.6, used=8186245120, free=2181107712, active=4748992512, inactive=2758115328, buffers=790724608, cached=3500347392, shared=787554304)
|
||||
>>> psutil.swap_memory()
|
||||
sswap(total=2097147904, used=296128512, free=1801019392, percent=14.1, sin=304193536, sout=677842944)
|
||||
>>>
|
||||
|
||||
Disks
|
||||
=====
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> import psutil
|
||||
>>> psutil.disk_partitions()
|
||||
[sdiskpart(device='/dev/sda1', mountpoint='/', fstype='ext4', opts='rw,nosuid'),
|
||||
sdiskpart(device='/dev/sda2', mountpoint='/home', fstype='ext, opts='rw')]
|
||||
>>>
|
||||
>>> psutil.disk_usage('/')
|
||||
sdiskusage(total=21378641920, used=4809781248, free=15482871808, percent=22.5)
|
||||
>>>
|
||||
>>> psutil.disk_io_counters(perdisk=False)
|
||||
sdiskio(read_count=719566, write_count=1082197, read_bytes=18626220032, write_bytes=24081764352, read_time=5023392, write_time=63199568, read_merged_count=619166, write_merged_count=812396, busy_time=4523412)
|
||||
>>>
|
||||
|
||||
Network
|
||||
=======
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> import psutil
|
||||
>>> psutil.net_io_counters(pernic=True)
|
||||
{'eth0': netio(bytes_sent=485291293, bytes_recv=6004858642, packets_sent=3251564, packets_recv=4787798, errin=0, errout=0, dropin=0, dropout=0),
|
||||
'lo': netio(bytes_sent=2838627, bytes_recv=2838627, packets_sent=30567, packets_recv=30567, errin=0, errout=0, dropin=0, dropout=0)}
|
||||
>>>
|
||||
>>> psutil.net_connections()
|
||||
[sconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=48776), raddr=addr(ip='93.186.135.91', port=80), status='ESTABLISHED', pid=1254),
|
||||
sconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=43761), raddr=addr(ip='72.14.234.100', port=80), status='CLOSING', pid=2987),
|
||||
sconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=60759), raddr=addr(ip='72.14.234.104', port=80), status='ESTABLISHED', pid=None),
|
||||
sconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=51314), raddr=addr(ip='72.14.234.83', port=443), status='SYN_SENT', pid=None)
|
||||
...]
|
||||
>>>
|
||||
>>> psutil.net_if_addrs()
|
||||
{'lo': [snic(family=<AddressFamily.AF_INET: 2>, address='127.0.0.1', netmask='255.0.0.0', broadcast='127.0.0.1', ptp=None),
|
||||
snic(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None, ptp=None),
|
||||
snic(family=<AddressFamily.AF_LINK: 17>, address='00:00:00:00:00:00', netmask=None, broadcast='00:00:00:00:00:00', ptp=None)],
|
||||
'wlan0': [snic(family=<AddressFamily.AF_INET: 2>, address='192.168.1.3', netmask='255.255.255.0', broadcast='192.168.1.255', ptp=None),
|
||||
snic(family=<AddressFamily.AF_INET6: 10>, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None, ptp=None),
|
||||
snic(family=<AddressFamily.AF_LINK: 17>, address='c4:85:08:45:06:41', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)]}
|
||||
>>>
|
||||
>>> psutil.net_if_stats()
|
||||
{'eth0': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=100, mtu=1500),
|
||||
'lo': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_UNKNOWN: 0>, speed=0, mtu=65536)}
|
||||
>>>
|
||||
|
||||
Sensors
|
||||
=======
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> import psutil
|
||||
>>> psutil.sensors_temperatures()
|
||||
{'acpitz': [shwtemp(label='', current=47.0, high=103.0, critical=103.0)],
|
||||
'asus': [shwtemp(label='', current=47.0, high=None, critical=None)],
|
||||
'coretemp': [shwtemp(label='Physical id 0', current=52.0, high=100.0, critical=100.0),
|
||||
shwtemp(label='Core 0', current=45.0, high=100.0, critical=100.0),
|
||||
shwtemp(label='Core 1', current=52.0, high=100.0, critical=100.0),
|
||||
shwtemp(label='Core 2', current=45.0, high=100.0, critical=100.0),
|
||||
shwtemp(label='Core 3', current=47.0, high=100.0, critical=100.0)]}
|
||||
>>>
|
||||
>>> psutil.sensors_fans()
|
||||
{'asus': [sfan(label='cpu_fan', current=3200)]}
|
||||
>>>
|
||||
>>> psutil.sensors_battery()
|
||||
sbattery(percent=93, secsleft=16628, power_plugged=False)
|
||||
>>>
|
||||
|
||||
Other system info
|
||||
=================
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> import psutil
|
||||
>>> psutil.users()
|
||||
[suser(name='giampaolo', terminal='pts/2', host='localhost', started=1340737536.0, pid=1352),
|
||||
suser(name='giampaolo', terminal='pts/3', host='localhost', started=1340737792.0, pid=1788)]
|
||||
>>>
|
||||
>>> psutil.boot_time()
|
||||
1365519115.0
|
||||
>>>
|
||||
|
||||
Process management
|
||||
==================
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> import psutil
|
||||
>>> psutil.pids()
|
||||
[1, 2, 3, 4, 5, 6, 7, 46, 48, 50, 51, 178, 182, 222, 223, 224, 268, 1215, 1216, 1220, 1221, 1243, 1244,
|
||||
1301, 1601, 2237, 2355, 2637, 2774, 3932, 4176, 4177, 4185, 4187, 4189, 4225, 4243, 4245, 4263, 4282,
|
||||
4306, 4311, 4312, 4313, 4314, 4337, 4339, 4357, 4358, 4363, 4383, 4395, 4408, 4433, 4443, 4445, 4446,
|
||||
5167, 5234, 5235, 5252, 5318, 5424, 5644, 6987, 7054, 7055, 7071]
|
||||
>>>
|
||||
>>> p = psutil.Process(7055)
|
||||
>>> p.name()
|
||||
'python'
|
||||
>>> p.exe()
|
||||
'/usr/bin/python'
|
||||
>>> p.cwd()
|
||||
'/home/giampaolo'
|
||||
>>> p.cmdline()
|
||||
['/usr/bin/python', 'main.py']
|
||||
>>>
|
||||
>>> p.pid
|
||||
7055
|
||||
>>> p.ppid()
|
||||
7054
|
||||
>>> p.parent()
|
||||
<psutil.Process(pid=7054, name='bash') at 140008329539408>
|
||||
>>> p.children()
|
||||
[<psutil.Process(pid=8031, name='python') at 14020832451977>,
|
||||
<psutil.Process(pid=8044, name='python') at 19229444921932>]
|
||||
>>>
|
||||
>>> p.status()
|
||||
'running'
|
||||
>>> p.username()
|
||||
'giampaolo'
|
||||
>>> p.create_time()
|
||||
1267551141.5019531
|
||||
>>> p.terminal()
|
||||
'/dev/pts/0'
|
||||
>>>
|
||||
>>> p.uids()
|
||||
puids(real=1000, effective=1000, saved=1000)
|
||||
>>> p.gids()
|
||||
pgids(real=1000, effective=1000, saved=1000)
|
||||
>>>
|
||||
>>> p.cpu_times()
|
||||
pcputimes(user=1.02, system=0.31, children_user=0.32, children_system=0.1)
|
||||
>>> p.cpu_percent(interval=1.0)
|
||||
12.1
|
||||
>>> p.cpu_affinity()
|
||||
[0, 1, 2, 3]
|
||||
>>> p.cpu_affinity([0, 1]) # set
|
||||
>>> p.cpu_num()
|
||||
1
|
||||
>>>
|
||||
>>> p.memory_info()
|
||||
pmem(rss=10915840, vms=67608576, shared=3313664, text=2310144, lib=0, data=7262208, dirty=0)
|
||||
>>> p.memory_full_info() # "real" USS memory usage (Linux, OSX, Win only)
|
||||
pfullmem(rss=10199040, vms=52133888, shared=3887104, text=2867200, lib=0, data=5967872, dirty=0, uss=6545408, pss=6872064, swap=0)
|
||||
>>> p.memory_percent()
|
||||
0.7823
|
||||
>>> p.memory_maps()
|
||||
[pmmap_grouped(path='/lib/x8664-linux-gnu/libutil-2.15.so', rss=32768, size=2125824, pss=32768, shared_clean=0, shared_dirty=0, private_clean=20480, private_dirty=12288, referenced=32768, anonymous=12288, swap=0),
|
||||
pmmap_grouped(path='/lib/x8664-linux-gnu/libc-2.15.so', rss=3821568, size=3842048, pss=3821568, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=3821568, referenced=3575808, anonymous=3821568, swap=0),
|
||||
pmmap_grouped(path='/lib/x8664-linux-gnu/libcrypto.so.0.1', rss=34124, rss=32768, size=2134016, pss=15360, shared_clean=24576, shared_dirty=0, private_clean=0, private_dirty=8192, referenced=24576, anonymous=8192, swap=0),
|
||||
pmmap_grouped(path='[heap]', rss=32768, size=139264, pss=32768, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=32768, referenced=32768, anonymous=32768, swap=0),
|
||||
pmmap_grouped(path='[stack]', rss=2465792, size=2494464, pss=2465792, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=2465792, referenced=2277376, anonymous=2465792, swap=0),
|
||||
...]
|
||||
>>>
|
||||
>>> p.io_counters()
|
||||
pio(read_count=478001, write_count=59371, read_bytes=700416, write_bytes=69632, read_chars=456232, write_chars=517543)
|
||||
>>>
|
||||
>>> p.open_files()
|
||||
[popenfile(path='/home/giampaolo/svn/psutil/setup.py', fd=3, position=0, mode='r', flags=32768),
|
||||
popenfile(path='/var/log/monitd', fd=4, position=235542, mode='a', flags=33793)]
|
||||
>>>
|
||||
>>> p.connections()
|
||||
[pconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=48776), raddr=addr(ip='93.186.135.91', port=80), status='ESTABLISHED'),
|
||||
pconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=43761), raddr=addr(ip='72.14.234.100', port=80), status='CLOSING'),
|
||||
pconn(fd=119, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=60759), raddr=addr(ip='72.14.234.104', port=80), status='ESTABLISHED'),
|
||||
pconn(fd=123, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=51314), raddr=addr(ip='72.14.234.83', port=443), status='SYN_SENT')]
|
||||
>>>
|
||||
>>> p.num_threads()
|
||||
4
|
||||
>>> p.num_fds()
|
||||
8
|
||||
>>> p.threads()
|
||||
[pthread(id=5234, user_time=22.5, system_time=9.2891),
|
||||
pthread(id=5235, user_time=0.0, system_time=0.0),
|
||||
pthread(id=5236, user_time=0.0, system_time=0.0),
|
||||
pthread(id=5237, user_time=0.0707, system_time=1.1)]
|
||||
>>>
|
||||
>>> p.num_ctx_switches()
|
||||
pctxsw(voluntary=78, involuntary=19)
|
||||
>>>
|
||||
>>> p.nice()
|
||||
0
|
||||
>>> p.nice(10) # set
|
||||
>>>
|
||||
>>> p.ionice(psutil.IOPRIO_CLASS_IDLE) # IO priority (Win and Linux only)
|
||||
>>> p.ionice()
|
||||
pionice(ioclass=<IOPriority.IOPRIO_CLASS_IDLE: 3>, value=0)
|
||||
>>>
|
||||
>>> p.rlimit(psutil.RLIMIT_NOFILE, (5, 5)) # set resource limits (Linux only)
|
||||
>>> p.rlimit(psutil.RLIMIT_NOFILE)
|
||||
(5, 5)
|
||||
>>>
|
||||
>>> p.environ()
|
||||
{'LC_PAPER': 'it_IT.UTF-8', 'SHELL': '/bin/bash', 'GREP_OPTIONS': '--color=auto',
|
||||
'XDG_CONFIG_DIRS': '/etc/xdg/xdg-ubuntu:/usr/share/upstart/xdg:/etc/xdg', 'COLORTERM': 'gnome-terminal',
|
||||
...}
|
||||
>>>
|
||||
>>> p.as_dict()
|
||||
{'status': 'running', 'num_ctx_switches': pctxsw(voluntary=63, involuntary=1), 'pid': 5457, ...}
|
||||
>>> p.is_running()
|
||||
True
|
||||
>>> p.suspend()
|
||||
>>> p.resume()
|
||||
>>>
|
||||
>>> p.terminate()
|
||||
>>> p.wait(timeout=3)
|
||||
0
|
||||
>>>
|
||||
>>> psutil.test()
|
||||
USER PID %CPU %MEM VSZ RSS TTY START TIME COMMAND
|
||||
root 1 0.0 0.0 24584 2240 Jun17 00:00 init
|
||||
root 2 0.0 0.0 0 0 Jun17 00:00 kthreadd
|
||||
root 3 0.0 0.0 0 0 Jun17 00:05 ksoftirqd/0
|
||||
...
|
||||
giampaolo 31475 0.0 0.0 20760 3024 /dev/pts/0 Jun19 00:00 python2.4
|
||||
giampaolo 31721 0.0 2.2 773060 181896 00:04 10:30 chrome
|
||||
root 31763 0.0 0.0 0 0 00:05 00:00 kworker/0:1
|
||||
>>>
|
||||
|
||||
Further process APIs
|
||||
====================
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> import psutil
|
||||
>>> for proc in psutil.process_iter(attrs=['pid', 'name']):
|
||||
... print(proc.info)
|
||||
...
|
||||
{'pid': 1, 'name': 'systemd'}
|
||||
{'pid': 2, 'name': 'kthreadd'}
|
||||
{'pid': 3, 'name': 'ksoftirqd/0'}
|
||||
...
|
||||
>>>
|
||||
>>> psutil.pid_exists(3)
|
||||
True
|
||||
>>>
|
||||
>>> def on_terminate(proc):
|
||||
... print("process {} terminated".format(proc))
|
||||
...
|
||||
>>> # waits for multiple processes to terminate
|
||||
>>> gone, alive = psutil.wait_procs(procs_list, timeout=3, callback=on_terminate)
|
||||
>>>
|
||||
|
||||
Popen wrapper:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> import psutil
|
||||
>>> from subprocess import PIPE
|
||||
>>> p = psutil.Popen(["/usr/bin/python", "-c", "print('hello')"], stdout=PIPE)
|
||||
>>> p.name()
|
||||
'python'
|
||||
>>> p.username()
|
||||
'giampaolo'
|
||||
>>> p.communicate()
|
||||
('hello\n', None)
|
||||
>>> p.wait(timeout=2)
|
||||
0
|
||||
>>>
|
||||
|
||||
Windows services
|
||||
================
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> list(psutil.win_service_iter())
|
||||
[<WindowsService(name='AeLookupSvc', display_name='Application Experience') at 38850096>,
|
||||
<WindowsService(name='ALG', display_name='Application Layer Gateway Service') at 38850128>,
|
||||
<WindowsService(name='APNMCP', display_name='Ask Update Service') at 38850160>,
|
||||
<WindowsService(name='AppIDSvc', display_name='Application Identity') at 38850192>,
|
||||
...]
|
||||
>>> s = psutil.win_service_get('alg')
|
||||
>>> s.as_dict()
|
||||
{'binpath': 'C:\\Windows\\System32\\alg.exe',
|
||||
'description': 'Provides support for 3rd party protocol plug-ins for Internet Connection Sharing',
|
||||
'display_name': 'Application Layer Gateway Service',
|
||||
'name': 'alg',
|
||||
'pid': None,
|
||||
'start_type': 'manual',
|
||||
'status': 'stopped',
|
||||
'username': 'NT AUTHORITY\\LocalService'}
|
||||
|
||||
Other samples
|
||||
=============
|
||||
|
||||
See `doc recipes <http://psutil.readthedocs.io/#recipes>`__.
|
||||
|
||||
======
|
||||
Author
|
||||
======
|
||||
|
||||
psutil was created and is maintained by
|
||||
`Giampaolo Rodola' <http://grodola.blogspot.com/p/about.html>`__.
|
||||
A lot of time and effort went into making psutil as it is right now.
|
||||
If you feel psutil is useful to you or your business and want to support its
|
||||
future development please consider donating me
|
||||
(`Giampaolo <http://grodola.blogspot.com/p/about.html>`__) some money.
|
||||
|
||||
.. image:: http://www.paypal.com/en_US/i/btn/x-click-but04.gif
|
||||
:target: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A9ZS7PKKRM3S8
|
||||
:alt: Donate via PayPal
|
||||
|
||||
Don't want to donate money? Then maybe you could `write me a recommendation on Linkedin <https://www.linkedin.com/in/grodola>`_.
|
||||
|
||||
|
34
third_party/python/psutil-cp27-none-win_amd64/psutil-5.4.3.dist-info/RECORD
поставляемый
Normal file
34
third_party/python/psutil-cp27-none-win_amd64/psutil-5.4.3.dist-info/RECORD
поставляемый
Normal file
|
@ -0,0 +1,34 @@
|
|||
psutil/__init__.py,sha256=220_B4k7vC9eoVP_OW8SFcaXCSBGpj_nacxvfBQ5O2o,84989
|
||||
psutil/_common.py,sha256=df5J2HqrWvGoFdumxDL1q9fgJOOYyiCmV0EFxb4ghuY,17852
|
||||
psutil/_compat.py,sha256=0VqlfcCGD5tZRBW-mFroguS0J7YNw6y3LjEcX5ChXDc,8170
|
||||
psutil/_exceptions.py,sha256=37eRgLuwTy7X4tjovePfZfYif-veW6LFeRlPqsgnNBU,3009
|
||||
psutil/_psaix.py,sha256=uAqwhQHS0upGc8OIk8Qa5PScCwXNvaMkoIdltZZ0n8A,19376
|
||||
psutil/_psbsd.py,sha256=ewmj2_DfzZpQZEcRvo1xvjVFhQqJidnENLgS8jrBb68,30244
|
||||
psutil/_pslinux.py,sha256=ME3wEgxfOWSFxgKXpTKbFw29ur1toMT4DdkKLJGkaD4,74850
|
||||
psutil/_psosx.py,sha256=X2WzhpuGjffjzFt3B3hphX7piPRCrPsjJrk6p6vu96w,17213
|
||||
psutil/_psposix.py,sha256=AmpZmKnvzCFcf7RpYypiUxOxKoRdXHRy2p9hFEIAJVc,6345
|
||||
psutil/_pssunos.py,sha256=uEsntvZPXplCuP9ER2W1QaGXjOqUZx_qFx2iLeyc5V8,25650
|
||||
psutil/_psutil_windows.pyd,sha256=wbQ_dSXTvdmCyQV02P7uCk95MwDkZ_D1g5r4G7IiYr8,59904
|
||||
psutil/_pswindows.py,sha256=_KYB-Vyhnz2A3l8I7tuXvFSrBPqKIb9slcwh5Azj0QU,33121
|
||||
psutil/tests/__init__.py,sha256=hkGHtLQNHjKrqhuV3Sk0kkHir17Mlam-amZBkLdfGwA,37656
|
||||
psutil/tests/__main__.py,sha256=dssAzXI-sAHkObtruDvc1cYUFNWOi-ZXETQgwaLKJS0,2784
|
||||
psutil/tests/test_aix.py,sha256=_ItFqb-CmYHlnlcduSKbgsPBw_xEIfE5v_pOr_YD8gw,4483
|
||||
psutil/tests/test_bsd.py,sha256=aif308A3TRnPZGY1tmNlH25YCweeSMpwbkah2K13wZs,17785
|
||||
psutil/tests/test_connections.py,sha256=eXOPOkusHO6Xc8gNrDxPBhq1Ni2fYYe0AAzeGU4gijQ,20676
|
||||
psutil/tests/test_contracts.py,sha256=ryPd7QDkQKxh8Mjcl-iPflXw5OTi8TWWLzQjIJ4EW2w,24136
|
||||
psutil/tests/test_linux.py,sha256=_gQBxUSiRSygoGfFXn-2m5XpXJQMQSiurVobrwkaAgc,78746
|
||||
psutil/tests/test_memory_leaks.py,sha256=v-RmU0BAzH05pkQ1dUV1hUXxlMva7943GFvT9Erl6J4,18259
|
||||
psutil/tests/test_misc.py,sha256=4qu61Sdmvzbaz2heOXKlg_PveYrzamBIUJ5QlLIYmSQ,37821
|
||||
psutil/tests/test_osx.py,sha256=UL3sovPp-5f0LIjNqjHu12NnpXF2uuv8Z62wbeAJj2c,9652
|
||||
psutil/tests/test_posix.py,sha256=4gm2VeCYoPYnstn_2GMG18c6xvMV7APXA26W5Dcm99s,16397
|
||||
psutil/tests/test_process.py,sha256=IE-v3DHKIje6Kwnas8kzfsbz15L4-0dpI555lXg7-NE,60495
|
||||
psutil/tests/test_sunos.py,sha256=UNywEx_qlSOyUHV48lMKqmnu8RKPBDCQrO0llulCUHY,1322
|
||||
psutil/tests/test_system.py,sha256=fv3otFKJVOn3VpRrD5IMivbI-hfajL6wmzVQF_JJqDI,34885
|
||||
psutil/tests/test_unicode.py,sha256=M0VTr_kGgmDKiNq6nSvraaw-711pRXe_6R948qHAr8I,12913
|
||||
psutil/tests/test_windows.py,sha256=AG2Feks59VOahEW_hJs_o4f5wt20vS1jxxaUCijcwAQ,32609
|
||||
psutil-5.4.3.dist-info/DESCRIPTION.rst,sha256=oATWrkVX56oC_b77TIXQsrm1CxSgD93PM71km6ud5G4,19853
|
||||
psutil-5.4.3.dist-info/METADATA,sha256=neLhT7NMfWptGzaSxueDDYqVDOR0C9cNvE8pAK14C2c,22835
|
||||
psutil-5.4.3.dist-info/RECORD,,
|
||||
psutil-5.4.3.dist-info/WHEEL,sha256=oT-jJdPOIfRdvpqTJO9X6OjCsyUImH2THoT54KREdwI,106
|
||||
psutil-5.4.3.dist-info/metadata.json,sha256=RqO1wxtF8F5B2HqYztzUkdKh5XmF8Wq_PxB9l571GM0,2492
|
||||
psutil-5.4.3.dist-info/top_level.txt,sha256=gCNhn57wzksDjSAISmgMJ0aiXzQulk0GJhb2-BAyYgw,7
|
5
third_party/python/psutil-cp27-none-win_amd64/psutil-5.4.3.dist-info/WHEEL
поставляемый
Normal file
5
third_party/python/psutil-cp27-none-win_amd64/psutil-5.4.3.dist-info/WHEEL
поставляемый
Normal file
|
@ -0,0 +1,5 @@
|
|||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.30.0)
|
||||
Root-Is-Purelib: false
|
||||
Tag: cp27-cp27m-win_amd64
|
||||
|
1
third_party/python/psutil-cp27-none-win_amd64/psutil-5.4.3.dist-info/metadata.json
поставляемый
Normal file
1
third_party/python/psutil-cp27-none-win_amd64/psutil-5.4.3.dist-info/metadata.json
поставляемый
Normal file
|
@ -0,0 +1 @@
|
|||
{"classifiers": ["Development Status :: 5 - Production/Stable", "Environment :: Console", "Environment :: Win32 (MS Windows)", "Intended Audience :: Developers", "Intended Audience :: Information Technology", "Intended Audience :: System Administrators", "License :: OSI Approved :: BSD License", "Operating System :: MacOS :: MacOS X", "Operating System :: Microsoft :: Windows :: Windows NT/2000", "Operating System :: Microsoft", "Operating System :: OS Independent", "Operating System :: POSIX :: BSD :: FreeBSD", "Operating System :: POSIX :: BSD :: NetBSD", "Operating System :: POSIX :: BSD :: OpenBSD", "Operating System :: POSIX :: BSD", "Operating System :: POSIX :: Linux", "Operating System :: POSIX :: SunOS/Solaris", "Operating System :: POSIX", "Programming Language :: C", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Programming Language :: Python", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Software Development :: Libraries", "Topic :: System :: Benchmark", "Topic :: System :: Hardware", "Topic :: System :: Monitoring", "Topic :: System :: Networking :: Monitoring", "Topic :: System :: Networking", "Topic :: System :: Operating System", "Topic :: System :: Systems Administration", "Topic :: Utilities"], "extensions": {"python.details": {"contacts": [{"email": "g.rodola@gmail.com", "name": "Giampaolo Rodola", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "https://github.com/giampaolo/psutil"}}}, "extras": ["enum"], "generator": "bdist_wheel (0.30.0)", "keywords": ["ps", "top", "kill", "free", "lsof", "netstat", "nice", "tty", "ionice", "uptime", "taskmgr", "process", "df", "iotop", "iostat", "ifconfig", "taskset", "who", "pidof", "pmap", "smem", "pstree", "monitoring", "ulimit", "prlimit", "smem"], "license": "BSD", "metadata_version": "2.0", "name": "psutil", "platform": "Platform Independent", "run_requires": [{"extra": "enum", "requires": ["enum34"]}], "summary": "Cross-platform lib for process and system monitoring in Python.", "test_requires": [{"requires": ["ipaddress", "mock"]}], "version": "5.4.3"}
|
1
third_party/python/psutil-cp27-none-win_amd64/psutil-5.4.3.dist-info/top_level.txt
поставляемый
Normal file
1
third_party/python/psutil-cp27-none-win_amd64/psutil-5.4.3.dist-info/top_level.txt
поставляемый
Normal file
|
@ -0,0 +1 @@
|
|||
psutil
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,575 @@
|
|||
# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
"""Common objects shared by __init__.py and _ps*.py modules."""
|
||||
|
||||
# Note: this module is imported by setup.py so it should not import
|
||||
# psutil or third-party modules.
|
||||
|
||||
from __future__ import division
|
||||
|
||||
import contextlib
|
||||
import errno
|
||||
import functools
|
||||
import os
|
||||
import socket
|
||||
import stat
|
||||
import sys
|
||||
import threading
|
||||
import warnings
|
||||
from collections import defaultdict
|
||||
from collections import namedtuple
|
||||
from socket import AF_INET
|
||||
from socket import SOCK_DGRAM
|
||||
from socket import SOCK_STREAM
|
||||
try:
|
||||
from socket import AF_INET6
|
||||
except ImportError:
|
||||
AF_INET6 = None
|
||||
try:
|
||||
from socket import AF_UNIX
|
||||
except ImportError:
|
||||
AF_UNIX = None
|
||||
|
||||
if sys.version_info >= (3, 4):
|
||||
import enum
|
||||
else:
|
||||
enum = None
|
||||
|
||||
# can't take it from _common.py as this script is imported by setup.py
|
||||
PY3 = sys.version_info[0] == 3
|
||||
|
||||
__all__ = [
|
||||
# constants
|
||||
'FREEBSD', 'BSD', 'LINUX', 'NETBSD', 'OPENBSD', 'OSX', 'POSIX', 'SUNOS',
|
||||
'WINDOWS',
|
||||
'ENCODING', 'ENCODING_ERRS', 'AF_INET6',
|
||||
# connection constants
|
||||
'CONN_CLOSE', 'CONN_CLOSE_WAIT', 'CONN_CLOSING', 'CONN_ESTABLISHED',
|
||||
'CONN_FIN_WAIT1', 'CONN_FIN_WAIT2', 'CONN_LAST_ACK', 'CONN_LISTEN',
|
||||
'CONN_NONE', 'CONN_SYN_RECV', 'CONN_SYN_SENT', 'CONN_TIME_WAIT',
|
||||
# net constants
|
||||
'NIC_DUPLEX_FULL', 'NIC_DUPLEX_HALF', 'NIC_DUPLEX_UNKNOWN',
|
||||
# process status constants
|
||||
'STATUS_DEAD', 'STATUS_DISK_SLEEP', 'STATUS_IDLE', 'STATUS_LOCKED',
|
||||
'STATUS_RUNNING', 'STATUS_SLEEPING', 'STATUS_STOPPED', 'STATUS_SUSPENDED',
|
||||
'STATUS_TRACING_STOP', 'STATUS_WAITING', 'STATUS_WAKE_KILL',
|
||||
'STATUS_WAKING', 'STATUS_ZOMBIE',
|
||||
# named tuples
|
||||
'pconn', 'pcputimes', 'pctxsw', 'pgids', 'pio', 'pionice', 'popenfile',
|
||||
'pthread', 'puids', 'sconn', 'scpustats', 'sdiskio', 'sdiskpart',
|
||||
'sdiskusage', 'snetio', 'snic', 'snicstats', 'sswap', 'suser',
|
||||
# utility functions
|
||||
'conn_tmap', 'deprecated_method', 'isfile_strict', 'memoize',
|
||||
'parse_environ_block', 'path_exists_strict', 'usage_percent',
|
||||
'supports_ipv6', 'sockfam_to_enum', 'socktype_to_enum', "wrap_numbers",
|
||||
]
|
||||
|
||||
|
||||
# ===================================================================
|
||||
# --- OS constants
|
||||
# ===================================================================
|
||||
|
||||
|
||||
POSIX = os.name == "posix"
|
||||
WINDOWS = os.name == "nt"
|
||||
LINUX = sys.platform.startswith("linux")
|
||||
OSX = sys.platform.startswith("darwin")
|
||||
FREEBSD = sys.platform.startswith("freebsd")
|
||||
OPENBSD = sys.platform.startswith("openbsd")
|
||||
NETBSD = sys.platform.startswith("netbsd")
|
||||
BSD = FREEBSD or OPENBSD or NETBSD
|
||||
SUNOS = sys.platform.startswith("sunos") or sys.platform.startswith("solaris")
|
||||
AIX = sys.platform.startswith("aix")
|
||||
|
||||
|
||||
# ===================================================================
|
||||
# --- API constants
|
||||
# ===================================================================
|
||||
|
||||
|
||||
# Process.status()
|
||||
STATUS_RUNNING = "running"
|
||||
STATUS_SLEEPING = "sleeping"
|
||||
STATUS_DISK_SLEEP = "disk-sleep"
|
||||
STATUS_STOPPED = "stopped"
|
||||
STATUS_TRACING_STOP = "tracing-stop"
|
||||
STATUS_ZOMBIE = "zombie"
|
||||
STATUS_DEAD = "dead"
|
||||
STATUS_WAKE_KILL = "wake-kill"
|
||||
STATUS_WAKING = "waking"
|
||||
STATUS_IDLE = "idle" # FreeBSD, OSX
|
||||
STATUS_LOCKED = "locked" # FreeBSD
|
||||
STATUS_WAITING = "waiting" # FreeBSD
|
||||
STATUS_SUSPENDED = "suspended" # NetBSD
|
||||
|
||||
# Process.connections() and psutil.net_connections()
|
||||
CONN_ESTABLISHED = "ESTABLISHED"
|
||||
CONN_SYN_SENT = "SYN_SENT"
|
||||
CONN_SYN_RECV = "SYN_RECV"
|
||||
CONN_FIN_WAIT1 = "FIN_WAIT1"
|
||||
CONN_FIN_WAIT2 = "FIN_WAIT2"
|
||||
CONN_TIME_WAIT = "TIME_WAIT"
|
||||
CONN_CLOSE = "CLOSE"
|
||||
CONN_CLOSE_WAIT = "CLOSE_WAIT"
|
||||
CONN_LAST_ACK = "LAST_ACK"
|
||||
CONN_LISTEN = "LISTEN"
|
||||
CONN_CLOSING = "CLOSING"
|
||||
CONN_NONE = "NONE"
|
||||
|
||||
# net_if_stats()
|
||||
if enum is None:
|
||||
NIC_DUPLEX_FULL = 2
|
||||
NIC_DUPLEX_HALF = 1
|
||||
NIC_DUPLEX_UNKNOWN = 0
|
||||
else:
|
||||
class NicDuplex(enum.IntEnum):
|
||||
NIC_DUPLEX_FULL = 2
|
||||
NIC_DUPLEX_HALF = 1
|
||||
NIC_DUPLEX_UNKNOWN = 0
|
||||
|
||||
globals().update(NicDuplex.__members__)
|
||||
|
||||
# sensors_battery()
|
||||
if enum is None:
|
||||
POWER_TIME_UNKNOWN = -1
|
||||
POWER_TIME_UNLIMITED = -2
|
||||
else:
|
||||
class BatteryTime(enum.IntEnum):
|
||||
POWER_TIME_UNKNOWN = -1
|
||||
POWER_TIME_UNLIMITED = -2
|
||||
|
||||
globals().update(BatteryTime.__members__)
|
||||
|
||||
# --- others
|
||||
|
||||
ENCODING = sys.getfilesystemencoding()
|
||||
if not PY3:
|
||||
ENCODING_ERRS = "replace"
|
||||
else:
|
||||
try:
|
||||
ENCODING_ERRS = sys.getfilesystemencodeerrors() # py 3.6
|
||||
except AttributeError:
|
||||
ENCODING_ERRS = "surrogateescape" if POSIX else "replace"
|
||||
|
||||
|
||||
# ===================================================================
|
||||
# --- namedtuples
|
||||
# ===================================================================
|
||||
|
||||
# --- for system functions
|
||||
|
||||
# psutil.swap_memory()
|
||||
sswap = namedtuple('sswap', ['total', 'used', 'free', 'percent', 'sin',
|
||||
'sout'])
|
||||
# psutil.disk_usage()
|
||||
sdiskusage = namedtuple('sdiskusage', ['total', 'used', 'free', 'percent'])
|
||||
# psutil.disk_io_counters()
|
||||
sdiskio = namedtuple('sdiskio', ['read_count', 'write_count',
|
||||
'read_bytes', 'write_bytes',
|
||||
'read_time', 'write_time'])
|
||||
# psutil.disk_partitions()
|
||||
sdiskpart = namedtuple('sdiskpart', ['device', 'mountpoint', 'fstype', 'opts'])
|
||||
# psutil.net_io_counters()
|
||||
snetio = namedtuple('snetio', ['bytes_sent', 'bytes_recv',
|
||||
'packets_sent', 'packets_recv',
|
||||
'errin', 'errout',
|
||||
'dropin', 'dropout'])
|
||||
# psutil.users()
|
||||
suser = namedtuple('suser', ['name', 'terminal', 'host', 'started', 'pid'])
|
||||
# psutil.net_connections()
|
||||
sconn = namedtuple('sconn', ['fd', 'family', 'type', 'laddr', 'raddr',
|
||||
'status', 'pid'])
|
||||
# psutil.net_if_addrs()
|
||||
snic = namedtuple('snic', ['family', 'address', 'netmask', 'broadcast', 'ptp'])
|
||||
# psutil.net_if_stats()
|
||||
snicstats = namedtuple('snicstats', ['isup', 'duplex', 'speed', 'mtu'])
|
||||
# psutil.cpu_stats()
|
||||
scpustats = namedtuple(
|
||||
'scpustats', ['ctx_switches', 'interrupts', 'soft_interrupts', 'syscalls'])
|
||||
# psutil.cpu_freq()
|
||||
scpufreq = namedtuple('scpufreq', ['current', 'min', 'max'])
|
||||
# psutil.sensors_temperatures()
|
||||
shwtemp = namedtuple(
|
||||
'shwtemp', ['label', 'current', 'high', 'critical'])
|
||||
# psutil.sensors_battery()
|
||||
sbattery = namedtuple('sbattery', ['percent', 'secsleft', 'power_plugged'])
|
||||
# psutil.sensors_battery()
|
||||
sfan = namedtuple('sfan', ['label', 'current'])
|
||||
|
||||
# --- for Process methods
|
||||
|
||||
# psutil.Process.cpu_times()
|
||||
pcputimes = namedtuple('pcputimes',
|
||||
['user', 'system', 'children_user', 'children_system'])
|
||||
# psutil.Process.open_files()
|
||||
popenfile = namedtuple('popenfile', ['path', 'fd'])
|
||||
# psutil.Process.threads()
|
||||
pthread = namedtuple('pthread', ['id', 'user_time', 'system_time'])
|
||||
# psutil.Process.uids()
|
||||
puids = namedtuple('puids', ['real', 'effective', 'saved'])
|
||||
# psutil.Process.gids()
|
||||
pgids = namedtuple('pgids', ['real', 'effective', 'saved'])
|
||||
# psutil.Process.io_counters()
|
||||
pio = namedtuple('pio', ['read_count', 'write_count',
|
||||
'read_bytes', 'write_bytes'])
|
||||
# psutil.Process.ionice()
|
||||
pionice = namedtuple('pionice', ['ioclass', 'value'])
|
||||
# psutil.Process.ctx_switches()
|
||||
pctxsw = namedtuple('pctxsw', ['voluntary', 'involuntary'])
|
||||
# psutil.Process.connections()
|
||||
pconn = namedtuple('pconn', ['fd', 'family', 'type', 'laddr', 'raddr',
|
||||
'status'])
|
||||
|
||||
# psutil.connections() and psutil.Process.connections()
|
||||
addr = namedtuple('addr', ['ip', 'port'])
|
||||
|
||||
|
||||
# ===================================================================
|
||||
# --- Process.connections() 'kind' parameter mapping
|
||||
# ===================================================================
|
||||
|
||||
|
||||
conn_tmap = {
|
||||
"all": ([AF_INET, AF_INET6, AF_UNIX], [SOCK_STREAM, SOCK_DGRAM]),
|
||||
"tcp": ([AF_INET, AF_INET6], [SOCK_STREAM]),
|
||||
"tcp4": ([AF_INET], [SOCK_STREAM]),
|
||||
"udp": ([AF_INET, AF_INET6], [SOCK_DGRAM]),
|
||||
"udp4": ([AF_INET], [SOCK_DGRAM]),
|
||||
"inet": ([AF_INET, AF_INET6], [SOCK_STREAM, SOCK_DGRAM]),
|
||||
"inet4": ([AF_INET], [SOCK_STREAM, SOCK_DGRAM]),
|
||||
"inet6": ([AF_INET6], [SOCK_STREAM, SOCK_DGRAM]),
|
||||
}
|
||||
|
||||
if AF_INET6 is not None:
|
||||
conn_tmap.update({
|
||||
"tcp6": ([AF_INET6], [SOCK_STREAM]),
|
||||
"udp6": ([AF_INET6], [SOCK_DGRAM]),
|
||||
})
|
||||
|
||||
if AF_UNIX is not None:
|
||||
conn_tmap.update({
|
||||
"unix": ([AF_UNIX], [SOCK_STREAM, SOCK_DGRAM]),
|
||||
})
|
||||
|
||||
del AF_INET, AF_UNIX, SOCK_STREAM, SOCK_DGRAM
|
||||
|
||||
|
||||
# ===================================================================
|
||||
# --- utils
|
||||
# ===================================================================
|
||||
|
||||
|
||||
def usage_percent(used, total, _round=None):
|
||||
"""Calculate percentage usage of 'used' against 'total'."""
|
||||
try:
|
||||
ret = (used / total) * 100
|
||||
except ZeroDivisionError:
|
||||
ret = 0.0 if isinstance(used, float) or isinstance(total, float) else 0
|
||||
if _round is not None:
|
||||
return round(ret, _round)
|
||||
else:
|
||||
return ret
|
||||
|
||||
|
||||
def memoize(fun):
|
||||
"""A simple memoize decorator for functions supporting (hashable)
|
||||
positional arguments.
|
||||
It also provides a cache_clear() function for clearing the cache:
|
||||
|
||||
>>> @memoize
|
||||
... def foo()
|
||||
... return 1
|
||||
...
|
||||
>>> foo()
|
||||
1
|
||||
>>> foo.cache_clear()
|
||||
>>>
|
||||
"""
|
||||
@functools.wraps(fun)
|
||||
def wrapper(*args, **kwargs):
|
||||
key = (args, frozenset(sorted(kwargs.items())))
|
||||
try:
|
||||
return cache[key]
|
||||
except KeyError:
|
||||
ret = cache[key] = fun(*args, **kwargs)
|
||||
return ret
|
||||
|
||||
def cache_clear():
|
||||
"""Clear cache."""
|
||||
cache.clear()
|
||||
|
||||
cache = {}
|
||||
wrapper.cache_clear = cache_clear
|
||||
return wrapper
|
||||
|
||||
|
||||
def memoize_when_activated(fun):
|
||||
"""A memoize decorator which is disabled by default. It can be
|
||||
activated and deactivated on request.
|
||||
For efficiency reasons it can be used only against class methods
|
||||
accepting no arguments.
|
||||
|
||||
>>> class Foo:
|
||||
... @memoize
|
||||
... def foo()
|
||||
... print(1)
|
||||
...
|
||||
>>> f = Foo()
|
||||
>>> # deactivated (default)
|
||||
>>> foo()
|
||||
1
|
||||
>>> foo()
|
||||
1
|
||||
>>>
|
||||
>>> # activated
|
||||
>>> foo.cache_activate()
|
||||
>>> foo()
|
||||
1
|
||||
>>> foo()
|
||||
>>> foo()
|
||||
>>>
|
||||
"""
|
||||
@functools.wraps(fun)
|
||||
def wrapper(self):
|
||||
if not wrapper.cache_activated:
|
||||
return fun(self)
|
||||
else:
|
||||
try:
|
||||
ret = cache[fun]
|
||||
except KeyError:
|
||||
ret = cache[fun] = fun(self)
|
||||
return ret
|
||||
|
||||
def cache_activate():
|
||||
"""Activate cache."""
|
||||
wrapper.cache_activated = True
|
||||
|
||||
def cache_deactivate():
|
||||
"""Deactivate and clear cache."""
|
||||
wrapper.cache_activated = False
|
||||
cache.clear()
|
||||
|
||||
cache = {}
|
||||
wrapper.cache_activated = False
|
||||
wrapper.cache_activate = cache_activate
|
||||
wrapper.cache_deactivate = cache_deactivate
|
||||
return wrapper
|
||||
|
||||
|
||||
def isfile_strict(path):
|
||||
"""Same as os.path.isfile() but does not swallow EACCES / EPERM
|
||||
exceptions, see:
|
||||
http://mail.python.org/pipermail/python-dev/2012-June/120787.html
|
||||
"""
|
||||
try:
|
||||
st = os.stat(path)
|
||||
except OSError as err:
|
||||
if err.errno in (errno.EPERM, errno.EACCES):
|
||||
raise
|
||||
return False
|
||||
else:
|
||||
return stat.S_ISREG(st.st_mode)
|
||||
|
||||
|
||||
def path_exists_strict(path):
|
||||
"""Same as os.path.exists() but does not swallow EACCES / EPERM
|
||||
exceptions, see:
|
||||
http://mail.python.org/pipermail/python-dev/2012-June/120787.html
|
||||
"""
|
||||
try:
|
||||
os.stat(path)
|
||||
except OSError as err:
|
||||
if err.errno in (errno.EPERM, errno.EACCES):
|
||||
raise
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
@memoize
|
||||
def supports_ipv6():
|
||||
"""Return True if IPv6 is supported on this platform."""
|
||||
if not socket.has_ipv6 or AF_INET6 is None:
|
||||
return False
|
||||
try:
|
||||
sock = socket.socket(AF_INET6, socket.SOCK_STREAM)
|
||||
with contextlib.closing(sock):
|
||||
sock.bind(("::1", 0))
|
||||
return True
|
||||
except socket.error:
|
||||
return False
|
||||
|
||||
|
||||
def parse_environ_block(data):
|
||||
"""Parse a C environ block of environment variables into a dictionary."""
|
||||
# The block is usually raw data from the target process. It might contain
|
||||
# trailing garbage and lines that do not look like assignments.
|
||||
ret = {}
|
||||
pos = 0
|
||||
|
||||
# localize global variable to speed up access.
|
||||
WINDOWS_ = WINDOWS
|
||||
while True:
|
||||
next_pos = data.find("\0", pos)
|
||||
# nul byte at the beginning or double nul byte means finish
|
||||
if next_pos <= pos:
|
||||
break
|
||||
# there might not be an equals sign
|
||||
equal_pos = data.find("=", pos, next_pos)
|
||||
if equal_pos > pos:
|
||||
key = data[pos:equal_pos]
|
||||
value = data[equal_pos + 1:next_pos]
|
||||
# Windows expects environment variables to be uppercase only
|
||||
if WINDOWS_:
|
||||
key = key.upper()
|
||||
ret[key] = value
|
||||
pos = next_pos + 1
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def sockfam_to_enum(num):
|
||||
"""Convert a numeric socket family value to an IntEnum member.
|
||||
If it's not a known member, return the numeric value itself.
|
||||
"""
|
||||
if enum is None:
|
||||
return num
|
||||
else: # pragma: no cover
|
||||
try:
|
||||
return socket.AddressFamily(num)
|
||||
except (ValueError, AttributeError):
|
||||
return num
|
||||
|
||||
|
||||
def socktype_to_enum(num):
|
||||
"""Convert a numeric socket type value to an IntEnum member.
|
||||
If it's not a known member, return the numeric value itself.
|
||||
"""
|
||||
if enum is None:
|
||||
return num
|
||||
else: # pragma: no cover
|
||||
try:
|
||||
return socket.AddressType(num)
|
||||
except (ValueError, AttributeError):
|
||||
return num
|
||||
|
||||
|
||||
def deprecated_method(replacement):
|
||||
"""A decorator which can be used to mark a method as deprecated
|
||||
'replcement' is the method name which will be called instead.
|
||||
"""
|
||||
def outer(fun):
|
||||
msg = "%s() is deprecated and will be removed; use %s() instead" % (
|
||||
fun.__name__, replacement)
|
||||
if fun.__doc__ is None:
|
||||
fun.__doc__ = msg
|
||||
|
||||
@functools.wraps(fun)
|
||||
def inner(self, *args, **kwargs):
|
||||
warnings.warn(msg, category=FutureWarning, stacklevel=2)
|
||||
return getattr(self, replacement)(*args, **kwargs)
|
||||
return inner
|
||||
return outer
|
||||
|
||||
|
||||
class _WrapNumbers:
|
||||
"""Watches numbers so that they don't overflow and wrap
|
||||
(reset to zero).
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.lock = threading.Lock()
|
||||
self.cache = {}
|
||||
self.reminders = {}
|
||||
self.reminder_keys = {}
|
||||
|
||||
def _add_dict(self, input_dict, name):
|
||||
assert name not in self.cache
|
||||
assert name not in self.reminders
|
||||
assert name not in self.reminder_keys
|
||||
self.cache[name] = input_dict
|
||||
self.reminders[name] = defaultdict(int)
|
||||
self.reminder_keys[name] = defaultdict(set)
|
||||
|
||||
def _remove_dead_reminders(self, input_dict, name):
|
||||
"""In case the number of keys changed between calls (e.g. a
|
||||
disk disappears) this removes the entry from self.reminders.
|
||||
"""
|
||||
old_dict = self.cache[name]
|
||||
gone_keys = set(old_dict.keys()) - set(input_dict.keys())
|
||||
for gone_key in gone_keys:
|
||||
for remkey in self.reminder_keys[name][gone_key]:
|
||||
del self.reminders[name][remkey]
|
||||
del self.reminder_keys[name][gone_key]
|
||||
|
||||
def run(self, input_dict, name):
|
||||
"""Cache dict and sum numbers which overflow and wrap.
|
||||
Return an updated copy of `input_dict`
|
||||
"""
|
||||
if name not in self.cache:
|
||||
# This was the first call.
|
||||
self._add_dict(input_dict, name)
|
||||
return input_dict
|
||||
|
||||
self._remove_dead_reminders(input_dict, name)
|
||||
|
||||
old_dict = self.cache[name]
|
||||
new_dict = {}
|
||||
for key in input_dict.keys():
|
||||
input_tuple = input_dict[key]
|
||||
try:
|
||||
old_tuple = old_dict[key]
|
||||
except KeyError:
|
||||
# The input dict has a new key (e.g. a new disk or NIC)
|
||||
# which didn't exist in the previous call.
|
||||
new_dict[key] = input_tuple
|
||||
continue
|
||||
|
||||
bits = []
|
||||
for i in range(len(input_tuple)):
|
||||
input_value = input_tuple[i]
|
||||
old_value = old_tuple[i]
|
||||
remkey = (key, i)
|
||||
if input_value < old_value:
|
||||
# it wrapped!
|
||||
self.reminders[name][remkey] += old_value
|
||||
self.reminder_keys[name][key].add(remkey)
|
||||
bits.append(input_value + self.reminders[name][remkey])
|
||||
|
||||
new_dict[key] = tuple(bits)
|
||||
|
||||
self.cache[name] = input_dict
|
||||
return new_dict
|
||||
|
||||
def cache_clear(self, name=None):
|
||||
"""Clear the internal cache, optionally only for function 'name'."""
|
||||
with self.lock:
|
||||
if name is None:
|
||||
self.cache.clear()
|
||||
self.reminders.clear()
|
||||
self.reminder_keys.clear()
|
||||
else:
|
||||
self.cache.pop(name, None)
|
||||
self.reminders.pop(name, None)
|
||||
self.reminder_keys.pop(name, None)
|
||||
|
||||
def cache_info(self):
|
||||
"""Return internal cache dicts as a tuple of 3 elements."""
|
||||
with self.lock:
|
||||
return (self.cache, self.reminders, self.reminder_keys)
|
||||
|
||||
|
||||
def wrap_numbers(input_dict, name):
|
||||
"""Given an `input_dict` and a function `name`, adjust the numbers
|
||||
which "wrap" (restart from zero) across different calls by adding
|
||||
"old value" to "new value" and return an updated dict.
|
||||
"""
|
||||
with _wn.lock:
|
||||
return _wn.run(input_dict, name)
|
||||
|
||||
|
||||
_wn = _WrapNumbers()
|
||||
wrap_numbers.cache_clear = _wn.cache_clear
|
||||
wrap_numbers.cache_info = _wn.cache_info
|
|
@ -0,0 +1,249 @@
|
|||
# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
"""Module which provides compatibility with older Python versions."""
|
||||
|
||||
import collections
|
||||
import functools
|
||||
import os
|
||||
import sys
|
||||
|
||||
__all__ = ["PY3", "long", "xrange", "unicode", "basestring", "u", "b",
|
||||
"callable", "lru_cache", "which"]
|
||||
|
||||
PY3 = sys.version_info[0] == 3
|
||||
|
||||
if PY3:
|
||||
long = int
|
||||
xrange = range
|
||||
unicode = str
|
||||
basestring = str
|
||||
|
||||
def u(s):
|
||||
return s
|
||||
|
||||
def b(s):
|
||||
return s.encode("latin-1")
|
||||
else:
|
||||
long = long
|
||||
xrange = xrange
|
||||
unicode = unicode
|
||||
basestring = basestring
|
||||
|
||||
def u(s):
|
||||
return unicode(s, "unicode_escape")
|
||||
|
||||
def b(s):
|
||||
return s
|
||||
|
||||
|
||||
# removed in 3.0, reintroduced in 3.2
|
||||
try:
|
||||
callable = callable
|
||||
except NameError:
|
||||
def callable(obj):
|
||||
return any("__call__" in klass.__dict__ for klass in type(obj).__mro__)
|
||||
|
||||
|
||||
# --- stdlib additions
|
||||
|
||||
|
||||
# py 3.2 functools.lru_cache
|
||||
# Taken from: http://code.activestate.com/recipes/578078
|
||||
# Credit: Raymond Hettinger
|
||||
try:
|
||||
from functools import lru_cache
|
||||
except ImportError:
|
||||
try:
|
||||
from threading import RLock
|
||||
except ImportError:
|
||||
from dummy_threading import RLock
|
||||
|
||||
_CacheInfo = collections.namedtuple(
|
||||
"CacheInfo", ["hits", "misses", "maxsize", "currsize"])
|
||||
|
||||
class _HashedSeq(list):
|
||||
__slots__ = 'hashvalue'
|
||||
|
||||
def __init__(self, tup, hash=hash):
|
||||
self[:] = tup
|
||||
self.hashvalue = hash(tup)
|
||||
|
||||
def __hash__(self):
|
||||
return self.hashvalue
|
||||
|
||||
def _make_key(args, kwds, typed,
|
||||
kwd_mark=(object(), ),
|
||||
fasttypes=set((int, str, frozenset, type(None))),
|
||||
sorted=sorted, tuple=tuple, type=type, len=len):
|
||||
key = args
|
||||
if kwds:
|
||||
sorted_items = sorted(kwds.items())
|
||||
key += kwd_mark
|
||||
for item in sorted_items:
|
||||
key += item
|
||||
if typed:
|
||||
key += tuple(type(v) for v in args)
|
||||
if kwds:
|
||||
key += tuple(type(v) for k, v in sorted_items)
|
||||
elif len(key) == 1 and type(key[0]) in fasttypes:
|
||||
return key[0]
|
||||
return _HashedSeq(key)
|
||||
|
||||
def lru_cache(maxsize=100, typed=False):
|
||||
"""Least-recently-used cache decorator, see:
|
||||
http://docs.python.org/3/library/functools.html#functools.lru_cache
|
||||
"""
|
||||
def decorating_function(user_function):
|
||||
cache = dict()
|
||||
stats = [0, 0]
|
||||
HITS, MISSES = 0, 1
|
||||
make_key = _make_key
|
||||
cache_get = cache.get
|
||||
_len = len
|
||||
lock = RLock()
|
||||
root = []
|
||||
root[:] = [root, root, None, None]
|
||||
nonlocal_root = [root]
|
||||
PREV, NEXT, KEY, RESULT = 0, 1, 2, 3
|
||||
if maxsize == 0:
|
||||
def wrapper(*args, **kwds):
|
||||
result = user_function(*args, **kwds)
|
||||
stats[MISSES] += 1
|
||||
return result
|
||||
elif maxsize is None:
|
||||
def wrapper(*args, **kwds):
|
||||
key = make_key(args, kwds, typed)
|
||||
result = cache_get(key, root)
|
||||
if result is not root:
|
||||
stats[HITS] += 1
|
||||
return result
|
||||
result = user_function(*args, **kwds)
|
||||
cache[key] = result
|
||||
stats[MISSES] += 1
|
||||
return result
|
||||
else:
|
||||
def wrapper(*args, **kwds):
|
||||
if kwds or typed:
|
||||
key = make_key(args, kwds, typed)
|
||||
else:
|
||||
key = args
|
||||
lock.acquire()
|
||||
try:
|
||||
link = cache_get(key)
|
||||
if link is not None:
|
||||
root, = nonlocal_root
|
||||
link_prev, link_next, key, result = link
|
||||
link_prev[NEXT] = link_next
|
||||
link_next[PREV] = link_prev
|
||||
last = root[PREV]
|
||||
last[NEXT] = root[PREV] = link
|
||||
link[PREV] = last
|
||||
link[NEXT] = root
|
||||
stats[HITS] += 1
|
||||
return result
|
||||
finally:
|
||||
lock.release()
|
||||
result = user_function(*args, **kwds)
|
||||
lock.acquire()
|
||||
try:
|
||||
root, = nonlocal_root
|
||||
if key in cache:
|
||||
pass
|
||||
elif _len(cache) >= maxsize:
|
||||
oldroot = root
|
||||
oldroot[KEY] = key
|
||||
oldroot[RESULT] = result
|
||||
root = nonlocal_root[0] = oldroot[NEXT]
|
||||
oldkey = root[KEY]
|
||||
root[KEY] = root[RESULT] = None
|
||||
del cache[oldkey]
|
||||
cache[key] = oldroot
|
||||
else:
|
||||
last = root[PREV]
|
||||
link = [last, root, key, result]
|
||||
last[NEXT] = root[PREV] = cache[key] = link
|
||||
stats[MISSES] += 1
|
||||
finally:
|
||||
lock.release()
|
||||
return result
|
||||
|
||||
def cache_info():
|
||||
"""Report cache statistics"""
|
||||
lock.acquire()
|
||||
try:
|
||||
return _CacheInfo(stats[HITS], stats[MISSES], maxsize,
|
||||
len(cache))
|
||||
finally:
|
||||
lock.release()
|
||||
|
||||
def cache_clear():
|
||||
"""Clear the cache and cache statistics"""
|
||||
lock.acquire()
|
||||
try:
|
||||
cache.clear()
|
||||
root = nonlocal_root[0]
|
||||
root[:] = [root, root, None, None]
|
||||
stats[:] = [0, 0]
|
||||
finally:
|
||||
lock.release()
|
||||
|
||||
wrapper.__wrapped__ = user_function
|
||||
wrapper.cache_info = cache_info
|
||||
wrapper.cache_clear = cache_clear
|
||||
return functools.update_wrapper(wrapper, user_function)
|
||||
|
||||
return decorating_function
|
||||
|
||||
|
||||
# python 3.3
|
||||
try:
|
||||
from shutil import which
|
||||
except ImportError:
|
||||
def which(cmd, mode=os.F_OK | os.X_OK, path=None):
|
||||
"""Given a command, mode, and a PATH string, return the path which
|
||||
conforms to the given mode on the PATH, or None if there is no such
|
||||
file.
|
||||
|
||||
`mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result
|
||||
of os.environ.get("PATH"), or can be overridden with a custom search
|
||||
path.
|
||||
"""
|
||||
def _access_check(fn, mode):
|
||||
return (os.path.exists(fn) and os.access(fn, mode) and
|
||||
not os.path.isdir(fn))
|
||||
|
||||
if os.path.dirname(cmd):
|
||||
if _access_check(cmd, mode):
|
||||
return cmd
|
||||
return None
|
||||
|
||||
if path is None:
|
||||
path = os.environ.get("PATH", os.defpath)
|
||||
if not path:
|
||||
return None
|
||||
path = path.split(os.pathsep)
|
||||
|
||||
if sys.platform == "win32":
|
||||
if os.curdir not in path:
|
||||
path.insert(0, os.curdir)
|
||||
|
||||
pathext = os.environ.get("PATHEXT", "").split(os.pathsep)
|
||||
if any(cmd.lower().endswith(ext.lower()) for ext in pathext):
|
||||
files = [cmd]
|
||||
else:
|
||||
files = [cmd + ext for ext in pathext]
|
||||
else:
|
||||
files = [cmd]
|
||||
|
||||
seen = set()
|
||||
for dir in path:
|
||||
normdir = os.path.normcase(dir)
|
||||
if normdir not in seen:
|
||||
seen.add(normdir)
|
||||
for thefile in files:
|
||||
name = os.path.join(dir, thefile)
|
||||
if _access_check(name, mode):
|
||||
return name
|
||||
return None
|
|
@ -0,0 +1,94 @@
|
|||
# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
|
||||
class Error(Exception):
|
||||
"""Base exception class. All other psutil exceptions inherit
|
||||
from this one.
|
||||
"""
|
||||
|
||||
def __init__(self, msg=""):
|
||||
Exception.__init__(self, msg)
|
||||
self.msg = msg
|
||||
|
||||
def __repr__(self):
|
||||
ret = "psutil.%s %s" % (self.__class__.__name__, self.msg)
|
||||
return ret.strip()
|
||||
|
||||
__str__ = __repr__
|
||||
|
||||
|
||||
class NoSuchProcess(Error):
|
||||
"""Exception raised when a process with a certain PID doesn't
|
||||
or no longer exists.
|
||||
"""
|
||||
|
||||
def __init__(self, pid, name=None, msg=None):
|
||||
Error.__init__(self, msg)
|
||||
self.pid = pid
|
||||
self.name = name
|
||||
self.msg = msg
|
||||
if msg is None:
|
||||
if name:
|
||||
details = "(pid=%s, name=%s)" % (self.pid, repr(self.name))
|
||||
else:
|
||||
details = "(pid=%s)" % self.pid
|
||||
self.msg = "process no longer exists " + details
|
||||
|
||||
|
||||
class ZombieProcess(NoSuchProcess):
|
||||
"""Exception raised when querying a zombie process. This is
|
||||
raised on OSX, BSD and Solaris only, and not always: depending
|
||||
on the query the OS may be able to succeed anyway.
|
||||
On Linux all zombie processes are querable (hence this is never
|
||||
raised). Windows doesn't have zombie processes.
|
||||
"""
|
||||
|
||||
def __init__(self, pid, name=None, ppid=None, msg=None):
|
||||
NoSuchProcess.__init__(self, msg)
|
||||
self.pid = pid
|
||||
self.ppid = ppid
|
||||
self.name = name
|
||||
self.msg = msg
|
||||
if msg is None:
|
||||
args = ["pid=%s" % pid]
|
||||
if name:
|
||||
args.append("name=%s" % repr(self.name))
|
||||
if ppid:
|
||||
args.append("ppid=%s" % self.ppid)
|
||||
details = "(%s)" % ", ".join(args)
|
||||
self.msg = "process still exists but it's a zombie " + details
|
||||
|
||||
|
||||
class AccessDenied(Error):
|
||||
"""Exception raised when permission to perform an action is denied."""
|
||||
|
||||
def __init__(self, pid=None, name=None, msg=None):
|
||||
Error.__init__(self, msg)
|
||||
self.pid = pid
|
||||
self.name = name
|
||||
self.msg = msg
|
||||
if msg is None:
|
||||
if (pid is not None) and (name is not None):
|
||||
self.msg = "(pid=%s, name=%s)" % (pid, repr(name))
|
||||
elif (pid is not None):
|
||||
self.msg = "(pid=%s)" % self.pid
|
||||
else:
|
||||
self.msg = ""
|
||||
|
||||
|
||||
class TimeoutExpired(Error):
|
||||
"""Raised on Process.wait(timeout) if timeout expires and process
|
||||
is still alive.
|
||||
"""
|
||||
|
||||
def __init__(self, seconds, pid=None, name=None):
|
||||
Error.__init__(self, "timeout after %s seconds" % seconds)
|
||||
self.seconds = seconds
|
||||
self.pid = pid
|
||||
self.name = name
|
||||
if (pid is not None) and (name is not None):
|
||||
self.msg += " (pid=%s, name=%s)" % (pid, repr(name))
|
||||
elif (pid is not None):
|
||||
self.msg += " (pid=%s)" % self.pid
|
|
@ -0,0 +1,573 @@
|
|||
# Copyright (c) 2009, Giampaolo Rodola'
|
||||
# Copyright (c) 2017, Arnon Yaari
|
||||
# All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
"""AIX platform implementation."""
|
||||
|
||||
import errno
|
||||
import glob
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from collections import namedtuple
|
||||
from socket import AF_INET
|
||||
|
||||
from . import _common
|
||||
from . import _psposix
|
||||
from . import _psutil_aix as cext
|
||||
from . import _psutil_posix as cext_posix
|
||||
from ._common import AF_INET6
|
||||
from ._common import memoize_when_activated
|
||||
from ._common import NIC_DUPLEX_FULL
|
||||
from ._common import NIC_DUPLEX_HALF
|
||||
from ._common import NIC_DUPLEX_UNKNOWN
|
||||
from ._common import sockfam_to_enum
|
||||
from ._common import socktype_to_enum
|
||||
from ._common import usage_percent
|
||||
from ._compat import PY3
|
||||
from ._exceptions import AccessDenied
|
||||
from ._exceptions import NoSuchProcess
|
||||
from ._exceptions import ZombieProcess
|
||||
|
||||
|
||||
__extra__all__ = ["PROCFS_PATH"]
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- globals
|
||||
# =====================================================================
|
||||
|
||||
|
||||
HAS_THREADS = hasattr(cext, "proc_threads")
|
||||
|
||||
PAGE_SIZE = os.sysconf('SC_PAGE_SIZE')
|
||||
AF_LINK = cext_posix.AF_LINK
|
||||
|
||||
PROC_STATUSES = {
|
||||
cext.SIDL: _common.STATUS_IDLE,
|
||||
cext.SZOMB: _common.STATUS_ZOMBIE,
|
||||
cext.SACTIVE: _common.STATUS_RUNNING,
|
||||
cext.SSWAP: _common.STATUS_RUNNING, # TODO what status is this?
|
||||
cext.SSTOP: _common.STATUS_STOPPED,
|
||||
}
|
||||
|
||||
TCP_STATUSES = {
|
||||
cext.TCPS_ESTABLISHED: _common.CONN_ESTABLISHED,
|
||||
cext.TCPS_SYN_SENT: _common.CONN_SYN_SENT,
|
||||
cext.TCPS_SYN_RCVD: _common.CONN_SYN_RECV,
|
||||
cext.TCPS_FIN_WAIT_1: _common.CONN_FIN_WAIT1,
|
||||
cext.TCPS_FIN_WAIT_2: _common.CONN_FIN_WAIT2,
|
||||
cext.TCPS_TIME_WAIT: _common.CONN_TIME_WAIT,
|
||||
cext.TCPS_CLOSED: _common.CONN_CLOSE,
|
||||
cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT,
|
||||
cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK,
|
||||
cext.TCPS_LISTEN: _common.CONN_LISTEN,
|
||||
cext.TCPS_CLOSING: _common.CONN_CLOSING,
|
||||
cext.PSUTIL_CONN_NONE: _common.CONN_NONE,
|
||||
}
|
||||
|
||||
proc_info_map = dict(
|
||||
ppid=0,
|
||||
rss=1,
|
||||
vms=2,
|
||||
create_time=3,
|
||||
nice=4,
|
||||
num_threads=5,
|
||||
status=6,
|
||||
ttynr=7)
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- named tuples
|
||||
# =====================================================================
|
||||
|
||||
|
||||
# psutil.Process.memory_info()
|
||||
pmem = namedtuple('pmem', ['rss', 'vms'])
|
||||
# psutil.Process.memory_full_info()
|
||||
pfullmem = pmem
|
||||
# psutil.Process.cpu_times()
|
||||
scputimes = namedtuple('scputimes', ['user', 'system', 'idle', 'iowait'])
|
||||
# psutil.virtual_memory()
|
||||
svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free'])
|
||||
# psutil.Process.memory_maps(grouped=True)
|
||||
pmmap_grouped = namedtuple('pmmap_grouped', ['path', 'rss', 'anon', 'locked'])
|
||||
# psutil.Process.memory_maps(grouped=False)
|
||||
pmmap_ext = namedtuple(
|
||||
'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields))
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- utils
|
||||
# =====================================================================
|
||||
|
||||
|
||||
def get_procfs_path():
|
||||
"""Return updated psutil.PROCFS_PATH constant."""
|
||||
return sys.modules['psutil'].PROCFS_PATH
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- memory
|
||||
# =====================================================================
|
||||
|
||||
|
||||
def virtual_memory():
|
||||
total, avail, free, pinned, inuse = cext.virtual_mem()
|
||||
percent = usage_percent((total - avail), total, _round=1)
|
||||
return svmem(total, avail, percent, inuse, free)
|
||||
|
||||
|
||||
def swap_memory():
|
||||
"""Swap system memory as a (total, used, free, sin, sout) tuple."""
|
||||
total, free, sin, sout = cext.swap_mem()
|
||||
used = total - free
|
||||
percent = usage_percent(used, total, _round=1)
|
||||
return _common.sswap(total, used, free, percent, sin, sout)
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- CPU
|
||||
# =====================================================================
|
||||
|
||||
|
||||
def cpu_times():
|
||||
"""Return system-wide CPU times as a named tuple"""
|
||||
ret = cext.per_cpu_times()
|
||||
return scputimes(*[sum(x) for x in zip(*ret)])
|
||||
|
||||
|
||||
def per_cpu_times():
|
||||
"""Return system per-CPU times as a list of named tuples"""
|
||||
ret = cext.per_cpu_times()
|
||||
return [scputimes(*x) for x in ret]
|
||||
|
||||
|
||||
def cpu_count_logical():
|
||||
"""Return the number of logical CPUs in the system."""
|
||||
try:
|
||||
return os.sysconf("SC_NPROCESSORS_ONLN")
|
||||
except ValueError:
|
||||
# mimic os.cpu_count() behavior
|
||||
return None
|
||||
|
||||
|
||||
def cpu_count_physical():
|
||||
cmd = "lsdev -Cc processor"
|
||||
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
stdout, stderr = p.communicate()
|
||||
if PY3:
|
||||
stdout, stderr = [x.decode(sys.stdout.encoding)
|
||||
for x in (stdout, stderr)]
|
||||
if p.returncode != 0:
|
||||
raise RuntimeError("%r command error\n%s" % (cmd, stderr))
|
||||
processors = stdout.strip().splitlines()
|
||||
return len(processors) or None
|
||||
|
||||
|
||||
def cpu_stats():
|
||||
"""Return various CPU stats as a named tuple."""
|
||||
ctx_switches, interrupts, soft_interrupts, syscalls = cext.cpu_stats()
|
||||
return _common.scpustats(
|
||||
ctx_switches, interrupts, soft_interrupts, syscalls)
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- disks
|
||||
# =====================================================================
|
||||
|
||||
|
||||
disk_io_counters = cext.disk_io_counters
|
||||
disk_usage = _psposix.disk_usage
|
||||
|
||||
|
||||
def disk_partitions(all=False):
|
||||
"""Return system disk partitions."""
|
||||
# TODO - the filtering logic should be better checked so that
|
||||
# it tries to reflect 'df' as much as possible
|
||||
retlist = []
|
||||
partitions = cext.disk_partitions()
|
||||
for partition in partitions:
|
||||
device, mountpoint, fstype, opts = partition
|
||||
if device == 'none':
|
||||
device = ''
|
||||
if not all:
|
||||
# Differently from, say, Linux, we don't have a list of
|
||||
# common fs types so the best we can do, AFAIK, is to
|
||||
# filter by filesystem having a total size > 0.
|
||||
if not disk_usage(mountpoint).total:
|
||||
continue
|
||||
ntuple = _common.sdiskpart(device, mountpoint, fstype, opts)
|
||||
retlist.append(ntuple)
|
||||
return retlist
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- network
|
||||
# =====================================================================
|
||||
|
||||
|
||||
net_if_addrs = cext_posix.net_if_addrs
|
||||
net_io_counters = cext.net_io_counters
|
||||
|
||||
|
||||
def net_connections(kind, _pid=-1):
|
||||
"""Return socket connections. If pid == -1 return system-wide
|
||||
connections (as opposed to connections opened by one process only).
|
||||
"""
|
||||
cmap = _common.conn_tmap
|
||||
if kind not in cmap:
|
||||
raise ValueError("invalid %r kind argument; choose between %s"
|
||||
% (kind, ', '.join([repr(x) for x in cmap])))
|
||||
families, types = _common.conn_tmap[kind]
|
||||
rawlist = cext.net_connections(_pid)
|
||||
ret = set()
|
||||
for item in rawlist:
|
||||
fd, fam, type_, laddr, raddr, status, pid = item
|
||||
if fam not in families:
|
||||
continue
|
||||
if type_ not in types:
|
||||
continue
|
||||
status = TCP_STATUSES[status]
|
||||
if fam in (AF_INET, AF_INET6):
|
||||
if laddr:
|
||||
laddr = _common.addr(*laddr)
|
||||
if raddr:
|
||||
raddr = _common.addr(*raddr)
|
||||
fam = sockfam_to_enum(fam)
|
||||
type_ = socktype_to_enum(type_)
|
||||
if _pid == -1:
|
||||
nt = _common.sconn(fd, fam, type_, laddr, raddr, status, pid)
|
||||
else:
|
||||
nt = _common.pconn(fd, fam, type_, laddr, raddr, status)
|
||||
ret.add(nt)
|
||||
return list(ret)
|
||||
|
||||
|
||||
def net_if_stats():
|
||||
"""Get NIC stats (isup, duplex, speed, mtu)."""
|
||||
duplex_map = {"Full": NIC_DUPLEX_FULL,
|
||||
"Half": NIC_DUPLEX_HALF}
|
||||
names = set([x[0] for x in net_if_addrs()])
|
||||
ret = {}
|
||||
for name in names:
|
||||
isup, mtu = cext.net_if_stats(name)
|
||||
|
||||
# try to get speed and duplex
|
||||
# TODO: rewrite this in C (entstat forks, so use truss -f to follow.
|
||||
# looks like it is using an undocumented ioctl?)
|
||||
duplex = ""
|
||||
speed = 0
|
||||
p = subprocess.Popen(["/usr/bin/entstat", "-d", name],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
stdout, stderr = p.communicate()
|
||||
if PY3:
|
||||
stdout, stderr = [x.decode(sys.stdout.encoding)
|
||||
for x in (stdout, stderr)]
|
||||
if p.returncode == 0:
|
||||
re_result = re.search("Running: (\d+) Mbps.*?(\w+) Duplex", stdout)
|
||||
if re_result is not None:
|
||||
speed = int(re_result.group(1))
|
||||
duplex = re_result.group(2)
|
||||
|
||||
duplex = duplex_map.get(duplex, NIC_DUPLEX_UNKNOWN)
|
||||
ret[name] = _common.snicstats(isup, duplex, speed, mtu)
|
||||
return ret
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- other system functions
|
||||
# =====================================================================
|
||||
|
||||
|
||||
def boot_time():
|
||||
"""The system boot time expressed in seconds since the epoch."""
|
||||
return cext.boot_time()
|
||||
|
||||
|
||||
def users():
|
||||
"""Return currently connected users as a list of namedtuples."""
|
||||
retlist = []
|
||||
rawlist = cext.users()
|
||||
localhost = (':0.0', ':0')
|
||||
for item in rawlist:
|
||||
user, tty, hostname, tstamp, user_process, pid = item
|
||||
# note: the underlying C function includes entries about
|
||||
# system boot, run level and others. We might want
|
||||
# to use them in the future.
|
||||
if not user_process:
|
||||
continue
|
||||
if hostname in localhost:
|
||||
hostname = 'localhost'
|
||||
nt = _common.suser(user, tty, hostname, tstamp, pid)
|
||||
retlist.append(nt)
|
||||
return retlist
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- processes
|
||||
# =====================================================================
|
||||
|
||||
|
||||
def pids():
|
||||
"""Returns a list of PIDs currently running on the system."""
|
||||
return [int(x) for x in os.listdir(get_procfs_path()) if x.isdigit()]
|
||||
|
||||
|
||||
def pid_exists(pid):
|
||||
"""Check for the existence of a unix pid."""
|
||||
return os.path.exists(os.path.join(get_procfs_path(), str(pid), "psinfo"))
|
||||
|
||||
|
||||
def wrap_exceptions(fun):
|
||||
"""Call callable into a try/except clause and translate ENOENT,
|
||||
EACCES and EPERM in NoSuchProcess or AccessDenied exceptions.
|
||||
"""
|
||||
|
||||
def wrapper(self, *args, **kwargs):
|
||||
try:
|
||||
return fun(self, *args, **kwargs)
|
||||
except EnvironmentError as err:
|
||||
# support for private module import
|
||||
if (NoSuchProcess is None or AccessDenied is None or
|
||||
ZombieProcess is None):
|
||||
raise
|
||||
# ENOENT (no such file or directory) gets raised on open().
|
||||
# ESRCH (no such process) can get raised on read() if
|
||||
# process is gone in meantime.
|
||||
if err.errno in (errno.ENOENT, errno.ESRCH):
|
||||
if not pid_exists(self.pid):
|
||||
raise NoSuchProcess(self.pid, self._name)
|
||||
else:
|
||||
raise ZombieProcess(self.pid, self._name, self._ppid)
|
||||
if err.errno in (errno.EPERM, errno.EACCES):
|
||||
raise AccessDenied(self.pid, self._name)
|
||||
raise
|
||||
return wrapper
|
||||
|
||||
|
||||
class Process(object):
|
||||
"""Wrapper class around underlying C implementation."""
|
||||
|
||||
__slots__ = ["pid", "_name", "_ppid", "_procfs_path"]
|
||||
|
||||
def __init__(self, pid):
|
||||
self.pid = pid
|
||||
self._name = None
|
||||
self._ppid = None
|
||||
self._procfs_path = get_procfs_path()
|
||||
|
||||
def oneshot_enter(self):
|
||||
self._proc_name_and_args.cache_activate()
|
||||
self._proc_basic_info.cache_activate()
|
||||
self._proc_cred.cache_activate()
|
||||
|
||||
def oneshot_exit(self):
|
||||
self._proc_name_and_args.cache_deactivate()
|
||||
self._proc_basic_info.cache_deactivate()
|
||||
self._proc_cred.cache_deactivate()
|
||||
|
||||
@memoize_when_activated
|
||||
def _proc_name_and_args(self):
|
||||
return cext.proc_name_and_args(self.pid, self._procfs_path)
|
||||
|
||||
@memoize_when_activated
|
||||
def _proc_basic_info(self):
|
||||
return cext.proc_basic_info(self.pid, self._procfs_path)
|
||||
|
||||
@memoize_when_activated
|
||||
def _proc_cred(self):
|
||||
return cext.proc_cred(self.pid, self._procfs_path)
|
||||
|
||||
@wrap_exceptions
|
||||
def name(self):
|
||||
if self.pid == 0:
|
||||
return "swapper"
|
||||
# note: this is limited to 15 characters
|
||||
return self._proc_name_and_args()[0].rstrip("\x00")
|
||||
|
||||
@wrap_exceptions
|
||||
def exe(self):
|
||||
# there is no way to get executable path in AIX other than to guess,
|
||||
# and guessing is more complex than what's in the wrapping class
|
||||
exe = self.cmdline()[0]
|
||||
if os.path.sep in exe:
|
||||
# relative or absolute path
|
||||
if not os.path.isabs(exe):
|
||||
# if cwd has changed, we're out of luck - this may be wrong!
|
||||
exe = os.path.abspath(os.path.join(self.cwd(), exe))
|
||||
if (os.path.isabs(exe) and
|
||||
os.path.isfile(exe) and
|
||||
os.access(exe, os.X_OK)):
|
||||
return exe
|
||||
# not found, move to search in PATH using basename only
|
||||
exe = os.path.basename(exe)
|
||||
# search for exe name PATH
|
||||
for path in os.environ["PATH"].split(":"):
|
||||
possible_exe = os.path.abspath(os.path.join(path, exe))
|
||||
if (os.path.isfile(possible_exe) and
|
||||
os.access(possible_exe, os.X_OK)):
|
||||
return possible_exe
|
||||
return ''
|
||||
|
||||
@wrap_exceptions
|
||||
def cmdline(self):
|
||||
return self._proc_name_and_args()[1].split(' ')
|
||||
|
||||
@wrap_exceptions
|
||||
def create_time(self):
|
||||
return self._proc_basic_info()[proc_info_map['create_time']]
|
||||
|
||||
@wrap_exceptions
|
||||
def num_threads(self):
|
||||
return self._proc_basic_info()[proc_info_map['num_threads']]
|
||||
|
||||
if HAS_THREADS:
|
||||
@wrap_exceptions
|
||||
def threads(self):
|
||||
rawlist = cext.proc_threads(self.pid)
|
||||
retlist = []
|
||||
for thread_id, utime, stime in rawlist:
|
||||
ntuple = _common.pthread(thread_id, utime, stime)
|
||||
retlist.append(ntuple)
|
||||
# The underlying C implementation retrieves all OS threads
|
||||
# and filters them by PID. At this point we can't tell whether
|
||||
# an empty list means there were no connections for process or
|
||||
# process is no longer active so we force NSP in case the PID
|
||||
# is no longer there.
|
||||
if not retlist:
|
||||
# will raise NSP if process is gone
|
||||
os.stat('%s/%s' % (self._procfs_path, self.pid))
|
||||
return retlist
|
||||
|
||||
@wrap_exceptions
|
||||
def connections(self, kind='inet'):
|
||||
ret = net_connections(kind, _pid=self.pid)
|
||||
# The underlying C implementation retrieves all OS connections
|
||||
# and filters them by PID. At this point we can't tell whether
|
||||
# an empty list means there were no connections for process or
|
||||
# process is no longer active so we force NSP in case the PID
|
||||
# is no longer there.
|
||||
if not ret:
|
||||
# will raise NSP if process is gone
|
||||
os.stat('%s/%s' % (self._procfs_path, self.pid))
|
||||
return ret
|
||||
|
||||
@wrap_exceptions
|
||||
def nice_get(self):
|
||||
return cext_posix.getpriority(self.pid)
|
||||
|
||||
@wrap_exceptions
|
||||
def nice_set(self, value):
|
||||
return cext_posix.setpriority(self.pid, value)
|
||||
|
||||
@wrap_exceptions
|
||||
def ppid(self):
|
||||
self._ppid = self._proc_basic_info()[proc_info_map['ppid']]
|
||||
return self._ppid
|
||||
|
||||
@wrap_exceptions
|
||||
def uids(self):
|
||||
real, effective, saved, _, _, _ = self._proc_cred()
|
||||
return _common.puids(real, effective, saved)
|
||||
|
||||
@wrap_exceptions
|
||||
def gids(self):
|
||||
_, _, _, real, effective, saved = self._proc_cred()
|
||||
return _common.puids(real, effective, saved)
|
||||
|
||||
@wrap_exceptions
|
||||
def cpu_times(self):
|
||||
cpu_times = cext.proc_cpu_times(self.pid, self._procfs_path)
|
||||
return _common.pcputimes(*cpu_times)
|
||||
|
||||
@wrap_exceptions
|
||||
def terminal(self):
|
||||
ttydev = self._proc_basic_info()[proc_info_map['ttynr']]
|
||||
# convert from 64-bit dev_t to 32-bit dev_t and then map the device
|
||||
ttydev = (((ttydev & 0x0000FFFF00000000) >> 16) | (ttydev & 0xFFFF))
|
||||
# try to match rdev of /dev/pts/* files ttydev
|
||||
for dev in glob.glob("/dev/**/*"):
|
||||
if os.stat(dev).st_rdev == ttydev:
|
||||
return dev
|
||||
return None
|
||||
|
||||
@wrap_exceptions
|
||||
def cwd(self):
|
||||
procfs_path = self._procfs_path
|
||||
try:
|
||||
result = os.readlink("%s/%s/cwd" % (procfs_path, self.pid))
|
||||
return result.rstrip('/')
|
||||
except OSError as err:
|
||||
if err.errno == errno.ENOENT:
|
||||
os.stat("%s/%s" % (procfs_path, self.pid)) # raise NSP or AD
|
||||
return None
|
||||
raise
|
||||
|
||||
@wrap_exceptions
|
||||
def memory_info(self):
|
||||
ret = self._proc_basic_info()
|
||||
rss = ret[proc_info_map['rss']] * 1024
|
||||
vms = ret[proc_info_map['vms']] * 1024
|
||||
return pmem(rss, vms)
|
||||
|
||||
memory_full_info = memory_info
|
||||
|
||||
@wrap_exceptions
|
||||
def status(self):
|
||||
code = self._proc_basic_info()[proc_info_map['status']]
|
||||
# XXX is '?' legit? (we're not supposed to return it anyway)
|
||||
return PROC_STATUSES.get(code, '?')
|
||||
|
||||
def open_files(self):
|
||||
# TODO rewrite without using procfiles (stat /proc/pid/fd/* and then
|
||||
# find matching name of the inode)
|
||||
p = subprocess.Popen(["/usr/bin/procfiles", "-n", str(self.pid)],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
stdout, stderr = p.communicate()
|
||||
if PY3:
|
||||
stdout, stderr = [x.decode(sys.stdout.encoding)
|
||||
for x in (stdout, stderr)]
|
||||
if "no such process" in stderr.lower():
|
||||
raise NoSuchProcess(self.pid, self._name)
|
||||
procfiles = re.findall("(\d+): S_IFREG.*\s*.*name:(.*)\n", stdout)
|
||||
retlist = []
|
||||
for fd, path in procfiles:
|
||||
path = path.strip()
|
||||
if path.startswith("//"):
|
||||
path = path[1:]
|
||||
if path.lower() == "cannot be retrieved":
|
||||
continue
|
||||
retlist.append(_common.popenfile(path, int(fd)))
|
||||
return retlist
|
||||
|
||||
@wrap_exceptions
|
||||
def num_fds(self):
|
||||
if self.pid == 0: # no /proc/0/fd
|
||||
return 0
|
||||
return len(os.listdir("%s/%s/fd" % (self._procfs_path, self.pid)))
|
||||
|
||||
@wrap_exceptions
|
||||
def num_ctx_switches(self):
|
||||
return _common.pctxsw(
|
||||
*cext.proc_num_ctx_switches(self.pid))
|
||||
|
||||
@wrap_exceptions
|
||||
def wait(self, timeout=None):
|
||||
return _psposix.wait_pid(self.pid, timeout, self._name)
|
||||
|
||||
@wrap_exceptions
|
||||
def io_counters(self):
|
||||
try:
|
||||
rc, wc, rb, wb = cext.proc_io_counters(self.pid)
|
||||
except OSError:
|
||||
# if process is terminated, proc_io_counters returns OSError
|
||||
# instead of NSP
|
||||
if not pid_exists(self.pid):
|
||||
raise NoSuchProcess(self.pid, self._name)
|
||||
raise
|
||||
return _common.pio(rc, wc, rb, wb)
|
|
@ -0,0 +1,873 @@
|
|||
# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
"""FreeBSD, OpenBSD and NetBSD platforms implementation."""
|
||||
|
||||
import contextlib
|
||||
import errno
|
||||
import functools
|
||||
import os
|
||||
import xml.etree.ElementTree as ET
|
||||
from collections import namedtuple
|
||||
from socket import AF_INET
|
||||
|
||||
from . import _common
|
||||
from . import _psposix
|
||||
from . import _psutil_bsd as cext
|
||||
from . import _psutil_posix as cext_posix
|
||||
from ._common import AF_INET6
|
||||
from ._common import conn_tmap
|
||||
from ._common import FREEBSD
|
||||
from ._common import memoize
|
||||
from ._common import memoize_when_activated
|
||||
from ._common import NETBSD
|
||||
from ._common import OPENBSD
|
||||
from ._common import sockfam_to_enum
|
||||
from ._common import socktype_to_enum
|
||||
from ._common import usage_percent
|
||||
from ._compat import which
|
||||
from ._exceptions import AccessDenied
|
||||
from ._exceptions import NoSuchProcess
|
||||
from ._exceptions import ZombieProcess
|
||||
|
||||
__extra__all__ = []
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- globals
|
||||
# =====================================================================
|
||||
|
||||
|
||||
if FREEBSD:
|
||||
PROC_STATUSES = {
|
||||
cext.SIDL: _common.STATUS_IDLE,
|
||||
cext.SRUN: _common.STATUS_RUNNING,
|
||||
cext.SSLEEP: _common.STATUS_SLEEPING,
|
||||
cext.SSTOP: _common.STATUS_STOPPED,
|
||||
cext.SZOMB: _common.STATUS_ZOMBIE,
|
||||
cext.SWAIT: _common.STATUS_WAITING,
|
||||
cext.SLOCK: _common.STATUS_LOCKED,
|
||||
}
|
||||
elif OPENBSD or NETBSD:
|
||||
PROC_STATUSES = {
|
||||
cext.SIDL: _common.STATUS_IDLE,
|
||||
cext.SSLEEP: _common.STATUS_SLEEPING,
|
||||
cext.SSTOP: _common.STATUS_STOPPED,
|
||||
# According to /usr/include/sys/proc.h SZOMB is unused.
|
||||
# test_zombie_process() shows that SDEAD is the right
|
||||
# equivalent. Also it appears there's no equivalent of
|
||||
# psutil.STATUS_DEAD. SDEAD really means STATUS_ZOMBIE.
|
||||
# cext.SZOMB: _common.STATUS_ZOMBIE,
|
||||
cext.SDEAD: _common.STATUS_ZOMBIE,
|
||||
cext.SZOMB: _common.STATUS_ZOMBIE,
|
||||
# From http://www.eecs.harvard.edu/~margo/cs161/videos/proc.h.txt
|
||||
# OpenBSD has SRUN and SONPROC: SRUN indicates that a process
|
||||
# is runnable but *not* yet running, i.e. is on a run queue.
|
||||
# SONPROC indicates that the process is actually executing on
|
||||
# a CPU, i.e. it is no longer on a run queue.
|
||||
# As such we'll map SRUN to STATUS_WAKING and SONPROC to
|
||||
# STATUS_RUNNING
|
||||
cext.SRUN: _common.STATUS_WAKING,
|
||||
cext.SONPROC: _common.STATUS_RUNNING,
|
||||
}
|
||||
elif NETBSD:
|
||||
PROC_STATUSES = {
|
||||
cext.SIDL: _common.STATUS_IDLE,
|
||||
cext.SACTIVE: _common.STATUS_RUNNING,
|
||||
cext.SDYING: _common.STATUS_ZOMBIE,
|
||||
cext.SSTOP: _common.STATUS_STOPPED,
|
||||
cext.SZOMB: _common.STATUS_ZOMBIE,
|
||||
cext.SDEAD: _common.STATUS_DEAD,
|
||||
cext.SSUSPENDED: _common.STATUS_SUSPENDED, # unique to NetBSD
|
||||
}
|
||||
|
||||
TCP_STATUSES = {
|
||||
cext.TCPS_ESTABLISHED: _common.CONN_ESTABLISHED,
|
||||
cext.TCPS_SYN_SENT: _common.CONN_SYN_SENT,
|
||||
cext.TCPS_SYN_RECEIVED: _common.CONN_SYN_RECV,
|
||||
cext.TCPS_FIN_WAIT_1: _common.CONN_FIN_WAIT1,
|
||||
cext.TCPS_FIN_WAIT_2: _common.CONN_FIN_WAIT2,
|
||||
cext.TCPS_TIME_WAIT: _common.CONN_TIME_WAIT,
|
||||
cext.TCPS_CLOSED: _common.CONN_CLOSE,
|
||||
cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT,
|
||||
cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK,
|
||||
cext.TCPS_LISTEN: _common.CONN_LISTEN,
|
||||
cext.TCPS_CLOSING: _common.CONN_CLOSING,
|
||||
cext.PSUTIL_CONN_NONE: _common.CONN_NONE,
|
||||
}
|
||||
|
||||
if NETBSD:
|
||||
PAGESIZE = os.sysconf("SC_PAGESIZE")
|
||||
else:
|
||||
PAGESIZE = os.sysconf("SC_PAGE_SIZE")
|
||||
AF_LINK = cext_posix.AF_LINK
|
||||
|
||||
kinfo_proc_map = dict(
|
||||
ppid=0,
|
||||
status=1,
|
||||
real_uid=2,
|
||||
effective_uid=3,
|
||||
saved_uid=4,
|
||||
real_gid=5,
|
||||
effective_gid=6,
|
||||
saved_gid=7,
|
||||
ttynr=8,
|
||||
create_time=9,
|
||||
ctx_switches_vol=10,
|
||||
ctx_switches_unvol=11,
|
||||
read_io_count=12,
|
||||
write_io_count=13,
|
||||
user_time=14,
|
||||
sys_time=15,
|
||||
ch_user_time=16,
|
||||
ch_sys_time=17,
|
||||
rss=18,
|
||||
vms=19,
|
||||
memtext=20,
|
||||
memdata=21,
|
||||
memstack=22,
|
||||
cpunum=23,
|
||||
name=24,
|
||||
)
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- named tuples
|
||||
# =====================================================================
|
||||
|
||||
|
||||
# psutil.virtual_memory()
|
||||
svmem = namedtuple(
|
||||
'svmem', ['total', 'available', 'percent', 'used', 'free',
|
||||
'active', 'inactive', 'buffers', 'cached', 'shared', 'wired'])
|
||||
# psutil.cpu_times()
|
||||
scputimes = namedtuple(
|
||||
'scputimes', ['user', 'nice', 'system', 'idle', 'irq'])
|
||||
# psutil.Process.memory_info()
|
||||
pmem = namedtuple('pmem', ['rss', 'vms', 'text', 'data', 'stack'])
|
||||
# psutil.Process.memory_full_info()
|
||||
pfullmem = pmem
|
||||
# psutil.Process.cpu_times()
|
||||
pcputimes = namedtuple('pcputimes',
|
||||
['user', 'system', 'children_user', 'children_system'])
|
||||
# psutil.Process.memory_maps(grouped=True)
|
||||
pmmap_grouped = namedtuple(
|
||||
'pmmap_grouped', 'path rss, private, ref_count, shadow_count')
|
||||
# psutil.Process.memory_maps(grouped=False)
|
||||
pmmap_ext = namedtuple(
|
||||
'pmmap_ext', 'addr, perms path rss, private, ref_count, shadow_count')
|
||||
# psutil.disk_io_counters()
|
||||
if FREEBSD:
|
||||
sdiskio = namedtuple('sdiskio', ['read_count', 'write_count',
|
||||
'read_bytes', 'write_bytes',
|
||||
'read_time', 'write_time',
|
||||
'busy_time'])
|
||||
else:
|
||||
sdiskio = namedtuple('sdiskio', ['read_count', 'write_count',
|
||||
'read_bytes', 'write_bytes'])
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- memory
|
||||
# =====================================================================
|
||||
|
||||
|
||||
def virtual_memory():
|
||||
"""System virtual memory as a namedtuple."""
|
||||
mem = cext.virtual_mem()
|
||||
total, free, active, inactive, wired, cached, buffers, shared = mem
|
||||
if NETBSD:
|
||||
# On NetBSD buffers and shared mem is determined via /proc.
|
||||
# The C ext set them to 0.
|
||||
with open('/proc/meminfo', 'rb') as f:
|
||||
for line in f:
|
||||
if line.startswith(b'Buffers:'):
|
||||
buffers = int(line.split()[1]) * 1024
|
||||
elif line.startswith(b'MemShared:'):
|
||||
shared = int(line.split()[1]) * 1024
|
||||
avail = inactive + cached + free
|
||||
used = active + wired + cached
|
||||
percent = usage_percent((total - avail), total, _round=1)
|
||||
return svmem(total, avail, percent, used, free,
|
||||
active, inactive, buffers, cached, shared, wired)
|
||||
|
||||
|
||||
def swap_memory():
|
||||
"""System swap memory as (total, used, free, sin, sout) namedtuple."""
|
||||
total, used, free, sin, sout = cext.swap_mem()
|
||||
percent = usage_percent(used, total, _round=1)
|
||||
return _common.sswap(total, used, free, percent, sin, sout)
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- CPU
|
||||
# =====================================================================
|
||||
|
||||
|
||||
def cpu_times():
|
||||
"""Return system per-CPU times as a namedtuple"""
|
||||
user, nice, system, idle, irq = cext.cpu_times()
|
||||
return scputimes(user, nice, system, idle, irq)
|
||||
|
||||
|
||||
if hasattr(cext, "per_cpu_times"):
|
||||
def per_cpu_times():
|
||||
"""Return system CPU times as a namedtuple"""
|
||||
ret = []
|
||||
for cpu_t in cext.per_cpu_times():
|
||||
user, nice, system, idle, irq = cpu_t
|
||||
item = scputimes(user, nice, system, idle, irq)
|
||||
ret.append(item)
|
||||
return ret
|
||||
else:
|
||||
# XXX
|
||||
# Ok, this is very dirty.
|
||||
# On FreeBSD < 8 we cannot gather per-cpu information, see:
|
||||
# https://github.com/giampaolo/psutil/issues/226
|
||||
# If num cpus > 1, on first call we return single cpu times to avoid a
|
||||
# crash at psutil import time.
|
||||
# Next calls will fail with NotImplementedError
|
||||
def per_cpu_times():
|
||||
"""Return system CPU times as a namedtuple"""
|
||||
if cpu_count_logical() == 1:
|
||||
return [cpu_times()]
|
||||
if per_cpu_times.__called__:
|
||||
raise NotImplementedError("supported only starting from FreeBSD 8")
|
||||
per_cpu_times.__called__ = True
|
||||
return [cpu_times()]
|
||||
|
||||
per_cpu_times.__called__ = False
|
||||
|
||||
|
||||
def cpu_count_logical():
|
||||
"""Return the number of logical CPUs in the system."""
|
||||
return cext.cpu_count_logical()
|
||||
|
||||
|
||||
if OPENBSD or NETBSD:
|
||||
def cpu_count_physical():
|
||||
# OpenBSD and NetBSD do not implement this.
|
||||
return 1 if cpu_count_logical() == 1 else None
|
||||
else:
|
||||
def cpu_count_physical():
|
||||
"""Return the number of physical CPUs in the system."""
|
||||
# From the C module we'll get an XML string similar to this:
|
||||
# http://manpages.ubuntu.com/manpages/precise/man4/smp.4freebsd.html
|
||||
# We may get None in case "sysctl kern.sched.topology_spec"
|
||||
# is not supported on this BSD version, in which case we'll mimic
|
||||
# os.cpu_count() and return None.
|
||||
ret = None
|
||||
s = cext.cpu_count_phys()
|
||||
if s is not None:
|
||||
# get rid of padding chars appended at the end of the string
|
||||
index = s.rfind("</groups>")
|
||||
if index != -1:
|
||||
s = s[:index + 9]
|
||||
root = ET.fromstring(s)
|
||||
try:
|
||||
ret = len(root.findall('group/children/group/cpu')) or None
|
||||
finally:
|
||||
# needed otherwise it will memleak
|
||||
root.clear()
|
||||
if not ret:
|
||||
# If logical CPUs are 1 it's obvious we'll have only 1
|
||||
# physical CPU.
|
||||
if cpu_count_logical() == 1:
|
||||
return 1
|
||||
return ret
|
||||
|
||||
|
||||
def cpu_stats():
|
||||
"""Return various CPU stats as a named tuple."""
|
||||
if FREEBSD:
|
||||
# Note: the C ext is returning some metrics we are not exposing:
|
||||
# traps.
|
||||
ctxsw, intrs, soft_intrs, syscalls, traps = cext.cpu_stats()
|
||||
elif NETBSD:
|
||||
# XXX
|
||||
# Note about intrs: the C extension returns 0. intrs
|
||||
# can be determined via /proc/stat; it has the same value as
|
||||
# soft_intrs thought so the kernel is faking it (?).
|
||||
#
|
||||
# Note about syscalls: the C extension always sets it to 0 (?).
|
||||
#
|
||||
# Note: the C ext is returning some metrics we are not exposing:
|
||||
# traps, faults and forks.
|
||||
ctxsw, intrs, soft_intrs, syscalls, traps, faults, forks = \
|
||||
cext.cpu_stats()
|
||||
with open('/proc/stat', 'rb') as f:
|
||||
for line in f:
|
||||
if line.startswith(b'intr'):
|
||||
intrs = int(line.split()[1])
|
||||
elif OPENBSD:
|
||||
# Note: the C ext is returning some metrics we are not exposing:
|
||||
# traps, faults and forks.
|
||||
ctxsw, intrs, soft_intrs, syscalls, traps, faults, forks = \
|
||||
cext.cpu_stats()
|
||||
return _common.scpustats(ctxsw, intrs, soft_intrs, syscalls)
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- disks
|
||||
# =====================================================================
|
||||
|
||||
|
||||
def disk_partitions(all=False):
|
||||
"""Return mounted disk partitions as a list of namedtuples.
|
||||
'all' argument is ignored, see:
|
||||
https://github.com/giampaolo/psutil/issues/906
|
||||
"""
|
||||
retlist = []
|
||||
partitions = cext.disk_partitions()
|
||||
for partition in partitions:
|
||||
device, mountpoint, fstype, opts = partition
|
||||
ntuple = _common.sdiskpart(device, mountpoint, fstype, opts)
|
||||
retlist.append(ntuple)
|
||||
return retlist
|
||||
|
||||
|
||||
disk_usage = _psposix.disk_usage
|
||||
disk_io_counters = cext.disk_io_counters
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- network
|
||||
# =====================================================================
|
||||
|
||||
|
||||
net_io_counters = cext.net_io_counters
|
||||
net_if_addrs = cext_posix.net_if_addrs
|
||||
|
||||
|
||||
def net_if_stats():
|
||||
"""Get NIC stats (isup, duplex, speed, mtu)."""
|
||||
names = net_io_counters().keys()
|
||||
ret = {}
|
||||
for name in names:
|
||||
mtu = cext_posix.net_if_mtu(name)
|
||||
isup = cext_posix.net_if_flags(name)
|
||||
duplex, speed = cext_posix.net_if_duplex_speed(name)
|
||||
if hasattr(_common, 'NicDuplex'):
|
||||
duplex = _common.NicDuplex(duplex)
|
||||
ret[name] = _common.snicstats(isup, duplex, speed, mtu)
|
||||
return ret
|
||||
|
||||
|
||||
def net_connections(kind):
|
||||
"""System-wide network connections."""
|
||||
if OPENBSD:
|
||||
ret = []
|
||||
for pid in pids():
|
||||
try:
|
||||
cons = Process(pid).connections(kind)
|
||||
except (NoSuchProcess, ZombieProcess):
|
||||
continue
|
||||
else:
|
||||
for conn in cons:
|
||||
conn = list(conn)
|
||||
conn.append(pid)
|
||||
ret.append(_common.sconn(*conn))
|
||||
return ret
|
||||
|
||||
if kind not in _common.conn_tmap:
|
||||
raise ValueError("invalid %r kind argument; choose between %s"
|
||||
% (kind, ', '.join([repr(x) for x in conn_tmap])))
|
||||
families, types = conn_tmap[kind]
|
||||
ret = set()
|
||||
if NETBSD:
|
||||
rawlist = cext.net_connections(-1)
|
||||
else:
|
||||
rawlist = cext.net_connections()
|
||||
for item in rawlist:
|
||||
fd, fam, type, laddr, raddr, status, pid = item
|
||||
# TODO: apply filter at C level
|
||||
if fam in families and type in types:
|
||||
try:
|
||||
status = TCP_STATUSES[status]
|
||||
except KeyError:
|
||||
# XXX: Not sure why this happens. I saw this occurring
|
||||
# with IPv6 sockets opened by 'vim'. Those sockets
|
||||
# have a very short lifetime so maybe the kernel
|
||||
# can't initialize their status?
|
||||
status = TCP_STATUSES[cext.PSUTIL_CONN_NONE]
|
||||
if fam in (AF_INET, AF_INET6):
|
||||
if laddr:
|
||||
laddr = _common.addr(*laddr)
|
||||
if raddr:
|
||||
raddr = _common.addr(*raddr)
|
||||
fam = sockfam_to_enum(fam)
|
||||
type = socktype_to_enum(type)
|
||||
nt = _common.sconn(fd, fam, type, laddr, raddr, status, pid)
|
||||
ret.add(nt)
|
||||
return list(ret)
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- sensors
|
||||
# =====================================================================
|
||||
|
||||
|
||||
if FREEBSD:
|
||||
|
||||
def sensors_battery():
|
||||
"""Return battery info."""
|
||||
try:
|
||||
percent, minsleft, power_plugged = cext.sensors_battery()
|
||||
except NotImplementedError:
|
||||
# See: https://github.com/giampaolo/psutil/issues/1074
|
||||
return None
|
||||
power_plugged = power_plugged == 1
|
||||
if power_plugged:
|
||||
secsleft = _common.POWER_TIME_UNLIMITED
|
||||
elif minsleft == -1:
|
||||
secsleft = _common.POWER_TIME_UNKNOWN
|
||||
else:
|
||||
secsleft = minsleft * 60
|
||||
return _common.sbattery(percent, secsleft, power_plugged)
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- other system functions
|
||||
# =====================================================================
|
||||
|
||||
|
||||
def boot_time():
|
||||
"""The system boot time expressed in seconds since the epoch."""
|
||||
return cext.boot_time()
|
||||
|
||||
|
||||
def users():
|
||||
"""Return currently connected users as a list of namedtuples."""
|
||||
retlist = []
|
||||
rawlist = cext.users()
|
||||
for item in rawlist:
|
||||
user, tty, hostname, tstamp, pid = item
|
||||
if pid == -1:
|
||||
assert OPENBSD
|
||||
pid = None
|
||||
if tty == '~':
|
||||
continue # reboot or shutdown
|
||||
nt = _common.suser(user, tty or None, hostname, tstamp, pid)
|
||||
retlist.append(nt)
|
||||
return retlist
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- processes
|
||||
# =====================================================================
|
||||
|
||||
|
||||
@memoize
|
||||
def _pid_0_exists():
|
||||
try:
|
||||
Process(0).name()
|
||||
except NoSuchProcess:
|
||||
return False
|
||||
except AccessDenied:
|
||||
return True
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
def pids():
|
||||
"""Returns a list of PIDs currently running on the system."""
|
||||
ret = cext.pids()
|
||||
if OPENBSD and (0 not in ret) and _pid_0_exists():
|
||||
# On OpenBSD the kernel does not return PID 0 (neither does
|
||||
# ps) but it's actually querable (Process(0) will succeed).
|
||||
ret.insert(0, 0)
|
||||
return ret
|
||||
|
||||
|
||||
if OPENBSD or NETBSD:
|
||||
def pid_exists(pid):
|
||||
"""Return True if pid exists."""
|
||||
exists = _psposix.pid_exists(pid)
|
||||
if not exists:
|
||||
# We do this because _psposix.pid_exists() lies in case of
|
||||
# zombie processes.
|
||||
return pid in pids()
|
||||
else:
|
||||
return True
|
||||
else:
|
||||
pid_exists = _psposix.pid_exists
|
||||
|
||||
|
||||
def wrap_exceptions(fun):
|
||||
"""Decorator which translates bare OSError exceptions into
|
||||
NoSuchProcess and AccessDenied.
|
||||
"""
|
||||
@functools.wraps(fun)
|
||||
def wrapper(self, *args, **kwargs):
|
||||
try:
|
||||
return fun(self, *args, **kwargs)
|
||||
except OSError as err:
|
||||
if self.pid == 0:
|
||||
if 0 in pids():
|
||||
raise AccessDenied(self.pid, self._name)
|
||||
else:
|
||||
raise
|
||||
if err.errno == errno.ESRCH:
|
||||
if not pid_exists(self.pid):
|
||||
raise NoSuchProcess(self.pid, self._name)
|
||||
else:
|
||||
raise ZombieProcess(self.pid, self._name, self._ppid)
|
||||
if err.errno in (errno.EPERM, errno.EACCES):
|
||||
raise AccessDenied(self.pid, self._name)
|
||||
raise
|
||||
return wrapper
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def wrap_exceptions_procfs(inst):
|
||||
"""Same as above, for routines relying on reading /proc fs."""
|
||||
try:
|
||||
yield
|
||||
except EnvironmentError as err:
|
||||
# ENOENT (no such file or directory) gets raised on open().
|
||||
# ESRCH (no such process) can get raised on read() if
|
||||
# process is gone in meantime.
|
||||
if err.errno in (errno.ENOENT, errno.ESRCH):
|
||||
if not pid_exists(inst.pid):
|
||||
raise NoSuchProcess(inst.pid, inst._name)
|
||||
else:
|
||||
raise ZombieProcess(inst.pid, inst._name, inst._ppid)
|
||||
if err.errno in (errno.EPERM, errno.EACCES):
|
||||
raise AccessDenied(inst.pid, inst._name)
|
||||
raise
|
||||
|
||||
|
||||
class Process(object):
|
||||
"""Wrapper class around underlying C implementation."""
|
||||
|
||||
__slots__ = ["pid", "_name", "_ppid"]
|
||||
|
||||
def __init__(self, pid):
|
||||
self.pid = pid
|
||||
self._name = None
|
||||
self._ppid = None
|
||||
|
||||
@memoize_when_activated
|
||||
def oneshot(self):
|
||||
"""Retrieves multiple process info in one shot as a raw tuple."""
|
||||
ret = cext.proc_oneshot_info(self.pid)
|
||||
assert len(ret) == len(kinfo_proc_map)
|
||||
return ret
|
||||
|
||||
def oneshot_enter(self):
|
||||
self.oneshot.cache_activate()
|
||||
|
||||
def oneshot_exit(self):
|
||||
self.oneshot.cache_deactivate()
|
||||
|
||||
@wrap_exceptions
|
||||
def name(self):
|
||||
name = self.oneshot()[kinfo_proc_map['name']]
|
||||
return name if name is not None else cext.proc_name(self.pid)
|
||||
|
||||
@wrap_exceptions
|
||||
def exe(self):
|
||||
if FREEBSD:
|
||||
return cext.proc_exe(self.pid)
|
||||
elif NETBSD:
|
||||
if self.pid == 0:
|
||||
# /proc/0 dir exists but /proc/0/exe doesn't
|
||||
return ""
|
||||
with wrap_exceptions_procfs(self):
|
||||
return os.readlink("/proc/%s/exe" % self.pid)
|
||||
else:
|
||||
# OpenBSD: exe cannot be determined; references:
|
||||
# https://chromium.googlesource.com/chromium/src/base/+/
|
||||
# master/base_paths_posix.cc
|
||||
# We try our best guess by using which against the first
|
||||
# cmdline arg (may return None).
|
||||
cmdline = self.cmdline()
|
||||
if cmdline:
|
||||
return which(cmdline[0])
|
||||
else:
|
||||
return ""
|
||||
|
||||
@wrap_exceptions
|
||||
def cmdline(self):
|
||||
if OPENBSD and self.pid == 0:
|
||||
return [] # ...else it crashes
|
||||
elif NETBSD:
|
||||
# XXX - most of the times the underlying sysctl() call on Net
|
||||
# and Open BSD returns a truncated string.
|
||||
# Also /proc/pid/cmdline behaves the same so it looks
|
||||
# like this is a kernel bug.
|
||||
try:
|
||||
return cext.proc_cmdline(self.pid)
|
||||
except OSError as err:
|
||||
if err.errno == errno.EINVAL:
|
||||
if not pid_exists(self.pid):
|
||||
raise NoSuchProcess(self.pid, self._name)
|
||||
else:
|
||||
raise ZombieProcess(self.pid, self._name, self._ppid)
|
||||
else:
|
||||
raise
|
||||
else:
|
||||
return cext.proc_cmdline(self.pid)
|
||||
|
||||
@wrap_exceptions
|
||||
def terminal(self):
|
||||
tty_nr = self.oneshot()[kinfo_proc_map['ttynr']]
|
||||
tmap = _psposix.get_terminal_map()
|
||||
try:
|
||||
return tmap[tty_nr]
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
@wrap_exceptions
|
||||
def ppid(self):
|
||||
self._ppid = self.oneshot()[kinfo_proc_map['ppid']]
|
||||
return self._ppid
|
||||
|
||||
@wrap_exceptions
|
||||
def uids(self):
|
||||
rawtuple = self.oneshot()
|
||||
return _common.puids(
|
||||
rawtuple[kinfo_proc_map['real_uid']],
|
||||
rawtuple[kinfo_proc_map['effective_uid']],
|
||||
rawtuple[kinfo_proc_map['saved_uid']])
|
||||
|
||||
@wrap_exceptions
|
||||
def gids(self):
|
||||
rawtuple = self.oneshot()
|
||||
return _common.pgids(
|
||||
rawtuple[kinfo_proc_map['real_gid']],
|
||||
rawtuple[kinfo_proc_map['effective_gid']],
|
||||
rawtuple[kinfo_proc_map['saved_gid']])
|
||||
|
||||
@wrap_exceptions
|
||||
def cpu_times(self):
|
||||
rawtuple = self.oneshot()
|
||||
return _common.pcputimes(
|
||||
rawtuple[kinfo_proc_map['user_time']],
|
||||
rawtuple[kinfo_proc_map['sys_time']],
|
||||
rawtuple[kinfo_proc_map['ch_user_time']],
|
||||
rawtuple[kinfo_proc_map['ch_sys_time']])
|
||||
|
||||
if FREEBSD:
|
||||
@wrap_exceptions
|
||||
def cpu_num(self):
|
||||
return self.oneshot()[kinfo_proc_map['cpunum']]
|
||||
|
||||
@wrap_exceptions
|
||||
def memory_info(self):
|
||||
rawtuple = self.oneshot()
|
||||
return pmem(
|
||||
rawtuple[kinfo_proc_map['rss']],
|
||||
rawtuple[kinfo_proc_map['vms']],
|
||||
rawtuple[kinfo_proc_map['memtext']],
|
||||
rawtuple[kinfo_proc_map['memdata']],
|
||||
rawtuple[kinfo_proc_map['memstack']])
|
||||
|
||||
memory_full_info = memory_info
|
||||
|
||||
@wrap_exceptions
|
||||
def create_time(self):
|
||||
return self.oneshot()[kinfo_proc_map['create_time']]
|
||||
|
||||
@wrap_exceptions
|
||||
def num_threads(self):
|
||||
if hasattr(cext, "proc_num_threads"):
|
||||
# FreeBSD
|
||||
return cext.proc_num_threads(self.pid)
|
||||
else:
|
||||
return len(self.threads())
|
||||
|
||||
@wrap_exceptions
|
||||
def num_ctx_switches(self):
|
||||
rawtuple = self.oneshot()
|
||||
return _common.pctxsw(
|
||||
rawtuple[kinfo_proc_map['ctx_switches_vol']],
|
||||
rawtuple[kinfo_proc_map['ctx_switches_unvol']])
|
||||
|
||||
@wrap_exceptions
|
||||
def threads(self):
|
||||
# Note: on OpenSBD this (/dev/mem) requires root access.
|
||||
rawlist = cext.proc_threads(self.pid)
|
||||
retlist = []
|
||||
for thread_id, utime, stime in rawlist:
|
||||
ntuple = _common.pthread(thread_id, utime, stime)
|
||||
retlist.append(ntuple)
|
||||
if OPENBSD:
|
||||
# On OpenBSD the underlying C function does not raise NSP
|
||||
# in case the process is gone (and the returned list may
|
||||
# incomplete).
|
||||
self.name() # raise NSP if the process disappeared on us
|
||||
return retlist
|
||||
|
||||
@wrap_exceptions
|
||||
def connections(self, kind='inet'):
|
||||
if kind not in conn_tmap:
|
||||
raise ValueError("invalid %r kind argument; choose between %s"
|
||||
% (kind, ', '.join([repr(x) for x in conn_tmap])))
|
||||
|
||||
if NETBSD:
|
||||
families, types = conn_tmap[kind]
|
||||
ret = set()
|
||||
rawlist = cext.net_connections(self.pid)
|
||||
for item in rawlist:
|
||||
fd, fam, type, laddr, raddr, status, pid = item
|
||||
assert pid == self.pid
|
||||
if fam in families and type in types:
|
||||
try:
|
||||
status = TCP_STATUSES[status]
|
||||
except KeyError:
|
||||
status = TCP_STATUSES[cext.PSUTIL_CONN_NONE]
|
||||
if fam in (AF_INET, AF_INET6):
|
||||
if laddr:
|
||||
laddr = _common.addr(*laddr)
|
||||
if raddr:
|
||||
raddr = _common.addr(*raddr)
|
||||
fam = sockfam_to_enum(fam)
|
||||
type = socktype_to_enum(type)
|
||||
nt = _common.pconn(fd, fam, type, laddr, raddr, status)
|
||||
ret.add(nt)
|
||||
# On NetBSD the underlying C function does not raise NSP
|
||||
# in case the process is gone (and the returned list may
|
||||
# incomplete).
|
||||
self.name() # raise NSP if the process disappeared on us
|
||||
return list(ret)
|
||||
|
||||
families, types = conn_tmap[kind]
|
||||
rawlist = cext.proc_connections(self.pid, families, types)
|
||||
ret = []
|
||||
for item in rawlist:
|
||||
fd, fam, type, laddr, raddr, status = item
|
||||
if fam in (AF_INET, AF_INET6):
|
||||
if laddr:
|
||||
laddr = _common.addr(*laddr)
|
||||
if raddr:
|
||||
raddr = _common.addr(*raddr)
|
||||
fam = sockfam_to_enum(fam)
|
||||
type = socktype_to_enum(type)
|
||||
status = TCP_STATUSES[status]
|
||||
nt = _common.pconn(fd, fam, type, laddr, raddr, status)
|
||||
ret.append(nt)
|
||||
if OPENBSD:
|
||||
# On OpenBSD the underlying C function does not raise NSP
|
||||
# in case the process is gone (and the returned list may
|
||||
# incomplete).
|
||||
self.name() # raise NSP if the process disappeared on us
|
||||
return ret
|
||||
|
||||
@wrap_exceptions
|
||||
def wait(self, timeout=None):
|
||||
return _psposix.wait_pid(self.pid, timeout, self._name)
|
||||
|
||||
@wrap_exceptions
|
||||
def nice_get(self):
|
||||
return cext_posix.getpriority(self.pid)
|
||||
|
||||
@wrap_exceptions
|
||||
def nice_set(self, value):
|
||||
return cext_posix.setpriority(self.pid, value)
|
||||
|
||||
@wrap_exceptions
|
||||
def status(self):
|
||||
code = self.oneshot()[kinfo_proc_map['status']]
|
||||
# XXX is '?' legit? (we're not supposed to return it anyway)
|
||||
return PROC_STATUSES.get(code, '?')
|
||||
|
||||
@wrap_exceptions
|
||||
def io_counters(self):
|
||||
rawtuple = self.oneshot()
|
||||
return _common.pio(
|
||||
rawtuple[kinfo_proc_map['read_io_count']],
|
||||
rawtuple[kinfo_proc_map['write_io_count']],
|
||||
-1,
|
||||
-1)
|
||||
|
||||
@wrap_exceptions
|
||||
def cwd(self):
|
||||
"""Return process current working directory."""
|
||||
# sometimes we get an empty string, in which case we turn
|
||||
# it into None
|
||||
if OPENBSD and self.pid == 0:
|
||||
return None # ...else it would raise EINVAL
|
||||
elif NETBSD:
|
||||
with wrap_exceptions_procfs(self):
|
||||
return os.readlink("/proc/%s/cwd" % self.pid)
|
||||
elif hasattr(cext, 'proc_open_files'):
|
||||
# FreeBSD < 8 does not support functions based on
|
||||
# kinfo_getfile() and kinfo_getvmmap()
|
||||
return cext.proc_cwd(self.pid) or None
|
||||
else:
|
||||
raise NotImplementedError(
|
||||
"supported only starting from FreeBSD 8" if
|
||||
FREEBSD else "")
|
||||
|
||||
nt_mmap_grouped = namedtuple(
|
||||
'mmap', 'path rss, private, ref_count, shadow_count')
|
||||
nt_mmap_ext = namedtuple(
|
||||
'mmap', 'addr, perms path rss, private, ref_count, shadow_count')
|
||||
|
||||
def _not_implemented(self):
|
||||
raise NotImplementedError
|
||||
|
||||
# FreeBSD < 8 does not support functions based on kinfo_getfile()
|
||||
# and kinfo_getvmmap()
|
||||
if hasattr(cext, 'proc_open_files'):
|
||||
@wrap_exceptions
|
||||
def open_files(self):
|
||||
"""Return files opened by process as a list of namedtuples."""
|
||||
rawlist = cext.proc_open_files(self.pid)
|
||||
return [_common.popenfile(path, fd) for path, fd in rawlist]
|
||||
else:
|
||||
open_files = _not_implemented
|
||||
|
||||
# FreeBSD < 8 does not support functions based on kinfo_getfile()
|
||||
# and kinfo_getvmmap()
|
||||
if hasattr(cext, 'proc_num_fds'):
|
||||
@wrap_exceptions
|
||||
def num_fds(self):
|
||||
"""Return the number of file descriptors opened by this process."""
|
||||
ret = cext.proc_num_fds(self.pid)
|
||||
if NETBSD:
|
||||
# On NetBSD the underlying C function does not raise NSP
|
||||
# in case the process is gone.
|
||||
self.name() # raise NSP if the process disappeared on us
|
||||
return ret
|
||||
else:
|
||||
num_fds = _not_implemented
|
||||
|
||||
# --- FreeBSD only APIs
|
||||
|
||||
if FREEBSD:
|
||||
|
||||
@wrap_exceptions
|
||||
def cpu_affinity_get(self):
|
||||
return cext.proc_cpu_affinity_get(self.pid)
|
||||
|
||||
@wrap_exceptions
|
||||
def cpu_affinity_set(self, cpus):
|
||||
# Pre-emptively check if CPUs are valid because the C
|
||||
# function has a weird behavior in case of invalid CPUs,
|
||||
# see: https://github.com/giampaolo/psutil/issues/586
|
||||
allcpus = tuple(range(len(per_cpu_times())))
|
||||
for cpu in cpus:
|
||||
if cpu not in allcpus:
|
||||
raise ValueError("invalid CPU #%i (choose between %s)"
|
||||
% (cpu, allcpus))
|
||||
try:
|
||||
cext.proc_cpu_affinity_set(self.pid, cpus)
|
||||
except OSError as err:
|
||||
# 'man cpuset_setaffinity' about EDEADLK:
|
||||
# <<the call would leave a thread without a valid CPU to run
|
||||
# on because the set does not overlap with the thread's
|
||||
# anonymous mask>>
|
||||
if err.errno in (errno.EINVAL, errno.EDEADLK):
|
||||
for cpu in cpus:
|
||||
if cpu not in allcpus:
|
||||
raise ValueError(
|
||||
"invalid CPU #%i (choose between %s)" % (
|
||||
cpu, allcpus))
|
||||
raise
|
||||
|
||||
@wrap_exceptions
|
||||
def memory_maps(self):
|
||||
return cext.proc_memory_maps(self.pid)
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,571 @@
|
|||
# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
"""OSX platform implementation."""
|
||||
|
||||
import contextlib
|
||||
import errno
|
||||
import functools
|
||||
import os
|
||||
from socket import AF_INET
|
||||
from collections import namedtuple
|
||||
|
||||
from . import _common
|
||||
from . import _psposix
|
||||
from . import _psutil_osx as cext
|
||||
from . import _psutil_posix as cext_posix
|
||||
from ._common import AF_INET6
|
||||
from ._common import conn_tmap
|
||||
from ._common import isfile_strict
|
||||
from ._common import memoize_when_activated
|
||||
from ._common import parse_environ_block
|
||||
from ._common import sockfam_to_enum
|
||||
from ._common import socktype_to_enum
|
||||
from ._common import usage_percent
|
||||
from ._exceptions import AccessDenied
|
||||
from ._exceptions import NoSuchProcess
|
||||
from ._exceptions import ZombieProcess
|
||||
|
||||
|
||||
__extra__all__ = []
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- globals
|
||||
# =====================================================================
|
||||
|
||||
|
||||
PAGESIZE = os.sysconf("SC_PAGE_SIZE")
|
||||
AF_LINK = cext_posix.AF_LINK
|
||||
|
||||
TCP_STATUSES = {
|
||||
cext.TCPS_ESTABLISHED: _common.CONN_ESTABLISHED,
|
||||
cext.TCPS_SYN_SENT: _common.CONN_SYN_SENT,
|
||||
cext.TCPS_SYN_RECEIVED: _common.CONN_SYN_RECV,
|
||||
cext.TCPS_FIN_WAIT_1: _common.CONN_FIN_WAIT1,
|
||||
cext.TCPS_FIN_WAIT_2: _common.CONN_FIN_WAIT2,
|
||||
cext.TCPS_TIME_WAIT: _common.CONN_TIME_WAIT,
|
||||
cext.TCPS_CLOSED: _common.CONN_CLOSE,
|
||||
cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT,
|
||||
cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK,
|
||||
cext.TCPS_LISTEN: _common.CONN_LISTEN,
|
||||
cext.TCPS_CLOSING: _common.CONN_CLOSING,
|
||||
cext.PSUTIL_CONN_NONE: _common.CONN_NONE,
|
||||
}
|
||||
|
||||
PROC_STATUSES = {
|
||||
cext.SIDL: _common.STATUS_IDLE,
|
||||
cext.SRUN: _common.STATUS_RUNNING,
|
||||
cext.SSLEEP: _common.STATUS_SLEEPING,
|
||||
cext.SSTOP: _common.STATUS_STOPPED,
|
||||
cext.SZOMB: _common.STATUS_ZOMBIE,
|
||||
}
|
||||
|
||||
kinfo_proc_map = dict(
|
||||
ppid=0,
|
||||
ruid=1,
|
||||
euid=2,
|
||||
suid=3,
|
||||
rgid=4,
|
||||
egid=5,
|
||||
sgid=6,
|
||||
ttynr=7,
|
||||
ctime=8,
|
||||
status=9,
|
||||
name=10,
|
||||
)
|
||||
|
||||
pidtaskinfo_map = dict(
|
||||
cpuutime=0,
|
||||
cpustime=1,
|
||||
rss=2,
|
||||
vms=3,
|
||||
pfaults=4,
|
||||
pageins=5,
|
||||
numthreads=6,
|
||||
volctxsw=7,
|
||||
)
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- named tuples
|
||||
# =====================================================================
|
||||
|
||||
|
||||
# psutil.cpu_times()
|
||||
scputimes = namedtuple('scputimes', ['user', 'nice', 'system', 'idle'])
|
||||
# psutil.virtual_memory()
|
||||
svmem = namedtuple(
|
||||
'svmem', ['total', 'available', 'percent', 'used', 'free',
|
||||
'active', 'inactive', 'wired'])
|
||||
# psutil.Process.memory_info()
|
||||
pmem = namedtuple('pmem', ['rss', 'vms', 'pfaults', 'pageins'])
|
||||
# psutil.Process.memory_full_info()
|
||||
pfullmem = namedtuple('pfullmem', pmem._fields + ('uss', ))
|
||||
# psutil.Process.memory_maps(grouped=True)
|
||||
pmmap_grouped = namedtuple(
|
||||
'pmmap_grouped',
|
||||
'path rss private swapped dirtied ref_count shadow_depth')
|
||||
# psutil.Process.memory_maps(grouped=False)
|
||||
pmmap_ext = namedtuple(
|
||||
'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields))
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- memory
|
||||
# =====================================================================
|
||||
|
||||
|
||||
def virtual_memory():
|
||||
"""System virtual memory as a namedtuple."""
|
||||
total, active, inactive, wired, free = cext.virtual_mem()
|
||||
avail = inactive + free
|
||||
used = active + inactive + wired
|
||||
percent = usage_percent((total - avail), total, _round=1)
|
||||
return svmem(total, avail, percent, used, free,
|
||||
active, inactive, wired)
|
||||
|
||||
|
||||
def swap_memory():
|
||||
"""Swap system memory as a (total, used, free, sin, sout) tuple."""
|
||||
total, used, free, sin, sout = cext.swap_mem()
|
||||
percent = usage_percent(used, total, _round=1)
|
||||
return _common.sswap(total, used, free, percent, sin, sout)
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- CPU
|
||||
# =====================================================================
|
||||
|
||||
|
||||
def cpu_times():
|
||||
"""Return system CPU times as a namedtuple."""
|
||||
user, nice, system, idle = cext.cpu_times()
|
||||
return scputimes(user, nice, system, idle)
|
||||
|
||||
|
||||
def per_cpu_times():
|
||||
"""Return system CPU times as a named tuple"""
|
||||
ret = []
|
||||
for cpu_t in cext.per_cpu_times():
|
||||
user, nice, system, idle = cpu_t
|
||||
item = scputimes(user, nice, system, idle)
|
||||
ret.append(item)
|
||||
return ret
|
||||
|
||||
|
||||
def cpu_count_logical():
|
||||
"""Return the number of logical CPUs in the system."""
|
||||
return cext.cpu_count_logical()
|
||||
|
||||
|
||||
def cpu_count_physical():
|
||||
"""Return the number of physical CPUs in the system."""
|
||||
return cext.cpu_count_phys()
|
||||
|
||||
|
||||
def cpu_stats():
|
||||
ctx_switches, interrupts, soft_interrupts, syscalls, traps = \
|
||||
cext.cpu_stats()
|
||||
return _common.scpustats(
|
||||
ctx_switches, interrupts, soft_interrupts, syscalls)
|
||||
|
||||
|
||||
def cpu_freq():
|
||||
"""Return CPU frequency.
|
||||
On OSX per-cpu frequency is not supported.
|
||||
Also, the returned frequency never changes, see:
|
||||
https://arstechnica.com/civis/viewtopic.php?f=19&t=465002
|
||||
"""
|
||||
curr, min_, max_ = cext.cpu_freq()
|
||||
return [_common.scpufreq(curr, min_, max_)]
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- disks
|
||||
# =====================================================================
|
||||
|
||||
|
||||
disk_usage = _psposix.disk_usage
|
||||
disk_io_counters = cext.disk_io_counters
|
||||
|
||||
|
||||
def disk_partitions(all=False):
|
||||
"""Return mounted disk partitions as a list of namedtuples."""
|
||||
retlist = []
|
||||
partitions = cext.disk_partitions()
|
||||
for partition in partitions:
|
||||
device, mountpoint, fstype, opts = partition
|
||||
if device == 'none':
|
||||
device = ''
|
||||
if not all:
|
||||
if not os.path.isabs(device) or not os.path.exists(device):
|
||||
continue
|
||||
ntuple = _common.sdiskpart(device, mountpoint, fstype, opts)
|
||||
retlist.append(ntuple)
|
||||
return retlist
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- sensors
|
||||
# =====================================================================
|
||||
|
||||
|
||||
def sensors_battery():
|
||||
"""Return battery information.
|
||||
"""
|
||||
try:
|
||||
percent, minsleft, power_plugged = cext.sensors_battery()
|
||||
except NotImplementedError:
|
||||
# no power source - return None according to interface
|
||||
return None
|
||||
power_plugged = power_plugged == 1
|
||||
if power_plugged:
|
||||
secsleft = _common.POWER_TIME_UNLIMITED
|
||||
elif minsleft == -1:
|
||||
secsleft = _common.POWER_TIME_UNKNOWN
|
||||
else:
|
||||
secsleft = minsleft * 60
|
||||
return _common.sbattery(percent, secsleft, power_plugged)
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- network
|
||||
# =====================================================================
|
||||
|
||||
|
||||
net_io_counters = cext.net_io_counters
|
||||
net_if_addrs = cext_posix.net_if_addrs
|
||||
|
||||
|
||||
def net_connections(kind='inet'):
|
||||
"""System-wide network connections."""
|
||||
# Note: on OSX this will fail with AccessDenied unless
|
||||
# the process is owned by root.
|
||||
ret = []
|
||||
for pid in pids():
|
||||
try:
|
||||
cons = Process(pid).connections(kind)
|
||||
except NoSuchProcess:
|
||||
continue
|
||||
else:
|
||||
if cons:
|
||||
for c in cons:
|
||||
c = list(c) + [pid]
|
||||
ret.append(_common.sconn(*c))
|
||||
return ret
|
||||
|
||||
|
||||
def net_if_stats():
|
||||
"""Get NIC stats (isup, duplex, speed, mtu)."""
|
||||
names = net_io_counters().keys()
|
||||
ret = {}
|
||||
for name in names:
|
||||
mtu = cext_posix.net_if_mtu(name)
|
||||
isup = cext_posix.net_if_flags(name)
|
||||
duplex, speed = cext_posix.net_if_duplex_speed(name)
|
||||
if hasattr(_common, 'NicDuplex'):
|
||||
duplex = _common.NicDuplex(duplex)
|
||||
ret[name] = _common.snicstats(isup, duplex, speed, mtu)
|
||||
return ret
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- other system functions
|
||||
# =====================================================================
|
||||
|
||||
|
||||
def boot_time():
|
||||
"""The system boot time expressed in seconds since the epoch."""
|
||||
return cext.boot_time()
|
||||
|
||||
|
||||
def users():
|
||||
"""Return currently connected users as a list of namedtuples."""
|
||||
retlist = []
|
||||
rawlist = cext.users()
|
||||
for item in rawlist:
|
||||
user, tty, hostname, tstamp, pid = item
|
||||
if tty == '~':
|
||||
continue # reboot or shutdown
|
||||
if not tstamp:
|
||||
continue
|
||||
nt = _common.suser(user, tty or None, hostname or None, tstamp, pid)
|
||||
retlist.append(nt)
|
||||
return retlist
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- processes
|
||||
# =====================================================================
|
||||
|
||||
|
||||
def pids():
|
||||
ls = cext.pids()
|
||||
if 0 not in ls:
|
||||
# On certain OSX versions pids() C doesn't return PID 0 but
|
||||
# "ps" does and the process is querable via sysctl():
|
||||
# https://travis-ci.org/giampaolo/psutil/jobs/309619941
|
||||
try:
|
||||
Process(0).create_time()
|
||||
ls.append(0)
|
||||
except NoSuchProcess:
|
||||
pass
|
||||
except AccessDenied:
|
||||
ls.append(0)
|
||||
return ls
|
||||
|
||||
|
||||
pid_exists = _psposix.pid_exists
|
||||
|
||||
|
||||
def wrap_exceptions(fun):
|
||||
"""Decorator which translates bare OSError exceptions into
|
||||
NoSuchProcess and AccessDenied.
|
||||
"""
|
||||
@functools.wraps(fun)
|
||||
def wrapper(self, *args, **kwargs):
|
||||
try:
|
||||
return fun(self, *args, **kwargs)
|
||||
except OSError as err:
|
||||
if err.errno == errno.ESRCH:
|
||||
raise NoSuchProcess(self.pid, self._name)
|
||||
if err.errno in (errno.EPERM, errno.EACCES):
|
||||
raise AccessDenied(self.pid, self._name)
|
||||
raise
|
||||
return wrapper
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def catch_zombie(proc):
|
||||
"""There are some poor C APIs which incorrectly raise ESRCH when
|
||||
the process is still alive or it's a zombie, or even RuntimeError
|
||||
(those who don't set errno). This is here in order to solve:
|
||||
https://github.com/giampaolo/psutil/issues/1044
|
||||
"""
|
||||
try:
|
||||
yield
|
||||
except (OSError, RuntimeError) as err:
|
||||
if isinstance(err, RuntimeError) or err.errno == errno.ESRCH:
|
||||
try:
|
||||
# status() is not supposed to lie and correctly detect
|
||||
# zombies so if it raises ESRCH it's true.
|
||||
status = proc.status()
|
||||
except NoSuchProcess:
|
||||
raise err
|
||||
else:
|
||||
if status == _common.STATUS_ZOMBIE:
|
||||
raise ZombieProcess(proc.pid, proc._name, proc._ppid)
|
||||
else:
|
||||
raise AccessDenied(proc.pid, proc._name)
|
||||
else:
|
||||
raise
|
||||
|
||||
|
||||
class Process(object):
|
||||
"""Wrapper class around underlying C implementation."""
|
||||
|
||||
__slots__ = ["pid", "_name", "_ppid"]
|
||||
|
||||
def __init__(self, pid):
|
||||
self.pid = pid
|
||||
self._name = None
|
||||
self._ppid = None
|
||||
|
||||
@memoize_when_activated
|
||||
def _get_kinfo_proc(self):
|
||||
# Note: should work with all PIDs without permission issues.
|
||||
ret = cext.proc_kinfo_oneshot(self.pid)
|
||||
assert len(ret) == len(kinfo_proc_map)
|
||||
return ret
|
||||
|
||||
@memoize_when_activated
|
||||
def _get_pidtaskinfo(self):
|
||||
# Note: should work for PIDs owned by user only.
|
||||
with catch_zombie(self):
|
||||
ret = cext.proc_pidtaskinfo_oneshot(self.pid)
|
||||
assert len(ret) == len(pidtaskinfo_map)
|
||||
return ret
|
||||
|
||||
def oneshot_enter(self):
|
||||
self._get_kinfo_proc.cache_activate()
|
||||
self._get_pidtaskinfo.cache_activate()
|
||||
|
||||
def oneshot_exit(self):
|
||||
self._get_kinfo_proc.cache_deactivate()
|
||||
self._get_pidtaskinfo.cache_deactivate()
|
||||
|
||||
@wrap_exceptions
|
||||
def name(self):
|
||||
name = self._get_kinfo_proc()[kinfo_proc_map['name']]
|
||||
return name if name is not None else cext.proc_name(self.pid)
|
||||
|
||||
@wrap_exceptions
|
||||
def exe(self):
|
||||
with catch_zombie(self):
|
||||
return cext.proc_exe(self.pid)
|
||||
|
||||
@wrap_exceptions
|
||||
def cmdline(self):
|
||||
with catch_zombie(self):
|
||||
return cext.proc_cmdline(self.pid)
|
||||
|
||||
@wrap_exceptions
|
||||
def environ(self):
|
||||
with catch_zombie(self):
|
||||
return parse_environ_block(cext.proc_environ(self.pid))
|
||||
|
||||
@wrap_exceptions
|
||||
def ppid(self):
|
||||
self._ppid = self._get_kinfo_proc()[kinfo_proc_map['ppid']]
|
||||
return self._ppid
|
||||
|
||||
@wrap_exceptions
|
||||
def cwd(self):
|
||||
with catch_zombie(self):
|
||||
return cext.proc_cwd(self.pid)
|
||||
|
||||
@wrap_exceptions
|
||||
def uids(self):
|
||||
rawtuple = self._get_kinfo_proc()
|
||||
return _common.puids(
|
||||
rawtuple[kinfo_proc_map['ruid']],
|
||||
rawtuple[kinfo_proc_map['euid']],
|
||||
rawtuple[kinfo_proc_map['suid']])
|
||||
|
||||
@wrap_exceptions
|
||||
def gids(self):
|
||||
rawtuple = self._get_kinfo_proc()
|
||||
return _common.puids(
|
||||
rawtuple[kinfo_proc_map['rgid']],
|
||||
rawtuple[kinfo_proc_map['egid']],
|
||||
rawtuple[kinfo_proc_map['sgid']])
|
||||
|
||||
@wrap_exceptions
|
||||
def terminal(self):
|
||||
tty_nr = self._get_kinfo_proc()[kinfo_proc_map['ttynr']]
|
||||
tmap = _psposix.get_terminal_map()
|
||||
try:
|
||||
return tmap[tty_nr]
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
@wrap_exceptions
|
||||
def memory_info(self):
|
||||
rawtuple = self._get_pidtaskinfo()
|
||||
return pmem(
|
||||
rawtuple[pidtaskinfo_map['rss']],
|
||||
rawtuple[pidtaskinfo_map['vms']],
|
||||
rawtuple[pidtaskinfo_map['pfaults']],
|
||||
rawtuple[pidtaskinfo_map['pageins']],
|
||||
)
|
||||
|
||||
@wrap_exceptions
|
||||
def memory_full_info(self):
|
||||
basic_mem = self.memory_info()
|
||||
uss = cext.proc_memory_uss(self.pid)
|
||||
return pfullmem(*basic_mem + (uss, ))
|
||||
|
||||
@wrap_exceptions
|
||||
def cpu_times(self):
|
||||
rawtuple = self._get_pidtaskinfo()
|
||||
return _common.pcputimes(
|
||||
rawtuple[pidtaskinfo_map['cpuutime']],
|
||||
rawtuple[pidtaskinfo_map['cpustime']],
|
||||
# children user / system times are not retrievable (set to 0)
|
||||
0.0, 0.0)
|
||||
|
||||
@wrap_exceptions
|
||||
def create_time(self):
|
||||
return self._get_kinfo_proc()[kinfo_proc_map['ctime']]
|
||||
|
||||
@wrap_exceptions
|
||||
def num_ctx_switches(self):
|
||||
# Unvoluntary value seems not to be available;
|
||||
# getrusage() numbers seems to confirm this theory.
|
||||
# We set it to 0.
|
||||
vol = self._get_pidtaskinfo()[pidtaskinfo_map['volctxsw']]
|
||||
return _common.pctxsw(vol, 0)
|
||||
|
||||
@wrap_exceptions
|
||||
def num_threads(self):
|
||||
return self._get_pidtaskinfo()[pidtaskinfo_map['numthreads']]
|
||||
|
||||
@wrap_exceptions
|
||||
def open_files(self):
|
||||
if self.pid == 0:
|
||||
return []
|
||||
files = []
|
||||
with catch_zombie(self):
|
||||
rawlist = cext.proc_open_files(self.pid)
|
||||
for path, fd in rawlist:
|
||||
if isfile_strict(path):
|
||||
ntuple = _common.popenfile(path, fd)
|
||||
files.append(ntuple)
|
||||
return files
|
||||
|
||||
@wrap_exceptions
|
||||
def connections(self, kind='inet'):
|
||||
if kind not in conn_tmap:
|
||||
raise ValueError("invalid %r kind argument; choose between %s"
|
||||
% (kind, ', '.join([repr(x) for x in conn_tmap])))
|
||||
families, types = conn_tmap[kind]
|
||||
with catch_zombie(self):
|
||||
rawlist = cext.proc_connections(self.pid, families, types)
|
||||
ret = []
|
||||
for item in rawlist:
|
||||
fd, fam, type, laddr, raddr, status = item
|
||||
status = TCP_STATUSES[status]
|
||||
fam = sockfam_to_enum(fam)
|
||||
type = socktype_to_enum(type)
|
||||
if fam in (AF_INET, AF_INET6):
|
||||
if laddr:
|
||||
laddr = _common.addr(*laddr)
|
||||
if raddr:
|
||||
raddr = _common.addr(*raddr)
|
||||
nt = _common.pconn(fd, fam, type, laddr, raddr, status)
|
||||
ret.append(nt)
|
||||
return ret
|
||||
|
||||
@wrap_exceptions
|
||||
def num_fds(self):
|
||||
if self.pid == 0:
|
||||
return 0
|
||||
with catch_zombie(self):
|
||||
return cext.proc_num_fds(self.pid)
|
||||
|
||||
@wrap_exceptions
|
||||
def wait(self, timeout=None):
|
||||
return _psposix.wait_pid(self.pid, timeout, self._name)
|
||||
|
||||
@wrap_exceptions
|
||||
def nice_get(self):
|
||||
with catch_zombie(self):
|
||||
return cext_posix.getpriority(self.pid)
|
||||
|
||||
@wrap_exceptions
|
||||
def nice_set(self, value):
|
||||
with catch_zombie(self):
|
||||
return cext_posix.setpriority(self.pid, value)
|
||||
|
||||
@wrap_exceptions
|
||||
def status(self):
|
||||
code = self._get_kinfo_proc()[kinfo_proc_map['status']]
|
||||
# XXX is '?' legit? (we're not supposed to return it anyway)
|
||||
return PROC_STATUSES.get(code, '?')
|
||||
|
||||
@wrap_exceptions
|
||||
def threads(self):
|
||||
with catch_zombie(self):
|
||||
rawlist = cext.proc_threads(self.pid)
|
||||
retlist = []
|
||||
for thread_id, utime, stime in rawlist:
|
||||
ntuple = _common.pthread(thread_id, utime, stime)
|
||||
retlist.append(ntuple)
|
||||
return retlist
|
||||
|
||||
@wrap_exceptions
|
||||
def memory_maps(self):
|
||||
with catch_zombie(self):
|
||||
return cext.proc_memory_maps(self.pid)
|
|
@ -0,0 +1,182 @@
|
|||
# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
"""Routines common to all posix systems."""
|
||||
|
||||
import errno
|
||||
import glob
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
from ._common import memoize
|
||||
from ._common import sdiskusage
|
||||
from ._common import usage_percent
|
||||
from ._compat import PY3
|
||||
from ._compat import unicode
|
||||
from ._exceptions import TimeoutExpired
|
||||
|
||||
|
||||
__all__ = ['pid_exists', 'wait_pid', 'disk_usage', 'get_terminal_map']
|
||||
|
||||
|
||||
def pid_exists(pid):
|
||||
"""Check whether pid exists in the current process table."""
|
||||
if pid == 0:
|
||||
# According to "man 2 kill" PID 0 has a special meaning:
|
||||
# it refers to <<every process in the process group of the
|
||||
# calling process>> so we don't want to go any further.
|
||||
# If we get here it means this UNIX platform *does* have
|
||||
# a process with id 0.
|
||||
return True
|
||||
try:
|
||||
os.kill(pid, 0)
|
||||
except OSError as err:
|
||||
if err.errno == errno.ESRCH:
|
||||
# ESRCH == No such process
|
||||
return False
|
||||
elif err.errno == errno.EPERM:
|
||||
# EPERM clearly means there's a process to deny access to
|
||||
return True
|
||||
else:
|
||||
# According to "man 2 kill" possible error values are
|
||||
# (EINVAL, EPERM, ESRCH) therefore we should never get
|
||||
# here. If we do let's be explicit in considering this
|
||||
# an error.
|
||||
raise err
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
def wait_pid(pid, timeout=None, proc_name=None):
|
||||
"""Wait for process with pid 'pid' to terminate and return its
|
||||
exit status code as an integer.
|
||||
|
||||
If pid is not a children of os.getpid() (current process) just
|
||||
waits until the process disappears and return None.
|
||||
|
||||
If pid does not exist at all return None immediately.
|
||||
|
||||
Raise TimeoutExpired on timeout expired.
|
||||
"""
|
||||
def check_timeout(delay):
|
||||
if timeout is not None:
|
||||
if timer() >= stop_at:
|
||||
raise TimeoutExpired(timeout, pid=pid, name=proc_name)
|
||||
time.sleep(delay)
|
||||
return min(delay * 2, 0.04)
|
||||
|
||||
timer = getattr(time, 'monotonic', time.time)
|
||||
if timeout is not None:
|
||||
def waitcall():
|
||||
return os.waitpid(pid, os.WNOHANG)
|
||||
stop_at = timer() + timeout
|
||||
else:
|
||||
def waitcall():
|
||||
return os.waitpid(pid, 0)
|
||||
|
||||
delay = 0.0001
|
||||
while True:
|
||||
try:
|
||||
retpid, status = waitcall()
|
||||
except OSError as err:
|
||||
if err.errno == errno.EINTR:
|
||||
delay = check_timeout(delay)
|
||||
continue
|
||||
elif err.errno == errno.ECHILD:
|
||||
# This has two meanings:
|
||||
# - pid is not a child of os.getpid() in which case
|
||||
# we keep polling until it's gone
|
||||
# - pid never existed in the first place
|
||||
# In both cases we'll eventually return None as we
|
||||
# can't determine its exit status code.
|
||||
while True:
|
||||
if pid_exists(pid):
|
||||
delay = check_timeout(delay)
|
||||
else:
|
||||
return
|
||||
else:
|
||||
raise
|
||||
else:
|
||||
if retpid == 0:
|
||||
# WNOHANG was used, pid is still running
|
||||
delay = check_timeout(delay)
|
||||
continue
|
||||
# process exited due to a signal; return the integer of
|
||||
# that signal
|
||||
if os.WIFSIGNALED(status):
|
||||
return -os.WTERMSIG(status)
|
||||
# process exited using exit(2) system call; return the
|
||||
# integer exit(2) system call has been called with
|
||||
elif os.WIFEXITED(status):
|
||||
return os.WEXITSTATUS(status)
|
||||
else:
|
||||
# should never happen
|
||||
raise ValueError("unknown process exit status %r" % status)
|
||||
|
||||
|
||||
def disk_usage(path):
|
||||
"""Return disk usage associated with path.
|
||||
Note: UNIX usually reserves 5% disk space which is not accessible
|
||||
by user. In this function "total" and "used" values reflect the
|
||||
total and used disk space whereas "free" and "percent" represent
|
||||
the "free" and "used percent" user disk space.
|
||||
"""
|
||||
if PY3:
|
||||
st = os.statvfs(path)
|
||||
else:
|
||||
# os.statvfs() does not support unicode on Python 2:
|
||||
# - https://github.com/giampaolo/psutil/issues/416
|
||||
# - http://bugs.python.org/issue18695
|
||||
try:
|
||||
st = os.statvfs(path)
|
||||
except UnicodeEncodeError:
|
||||
if isinstance(path, unicode):
|
||||
try:
|
||||
path = path.encode(sys.getfilesystemencoding())
|
||||
except UnicodeEncodeError:
|
||||
pass
|
||||
st = os.statvfs(path)
|
||||
else:
|
||||
raise
|
||||
|
||||
# Total space which is only available to root (unless changed
|
||||
# at system level).
|
||||
total = (st.f_blocks * st.f_frsize)
|
||||
# Remaining free space usable by root.
|
||||
avail_to_root = (st.f_bfree * st.f_frsize)
|
||||
# Remaining free space usable by user.
|
||||
avail_to_user = (st.f_bavail * st.f_frsize)
|
||||
# Total space being used in general.
|
||||
used = (total - avail_to_root)
|
||||
# Total space which is available to user (same as 'total' but
|
||||
# for the user).
|
||||
total_user = used + avail_to_user
|
||||
# User usage percent compared to the total amount of space
|
||||
# the user can use. This number would be higher if compared
|
||||
# to root's because the user has less space (usually -5%).
|
||||
usage_percent_user = usage_percent(used, total_user, _round=1)
|
||||
|
||||
# NB: the percentage is -5% than what shown by df due to
|
||||
# reserved blocks that we are currently not considering:
|
||||
# https://github.com/giampaolo/psutil/issues/829#issuecomment-223750462
|
||||
return sdiskusage(
|
||||
total=total, used=used, free=avail_to_user, percent=usage_percent_user)
|
||||
|
||||
|
||||
@memoize
|
||||
def get_terminal_map():
|
||||
"""Get a map of device-id -> path as a dict.
|
||||
Used by Process.terminal()
|
||||
"""
|
||||
ret = {}
|
||||
ls = glob.glob('/dev/tty*') + glob.glob('/dev/pts/*')
|
||||
for name in ls:
|
||||
assert name not in ret, name
|
||||
try:
|
||||
ret[os.stat(name).st_rdev] = name
|
||||
except OSError as err:
|
||||
if err.errno != errno.ENOENT:
|
||||
raise
|
||||
return ret
|
|
@ -0,0 +1,725 @@
|
|||
# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
"""Sun OS Solaris platform implementation."""
|
||||
|
||||
import errno
|
||||
import os
|
||||
import socket
|
||||
import subprocess
|
||||
import sys
|
||||
from collections import namedtuple
|
||||
from socket import AF_INET
|
||||
|
||||
from . import _common
|
||||
from . import _psposix
|
||||
from . import _psutil_posix as cext_posix
|
||||
from . import _psutil_sunos as cext
|
||||
from ._common import AF_INET6
|
||||
from ._common import isfile_strict
|
||||
from ._common import memoize_when_activated
|
||||
from ._common import sockfam_to_enum
|
||||
from ._common import socktype_to_enum
|
||||
from ._common import usage_percent
|
||||
from ._compat import b
|
||||
from ._compat import PY3
|
||||
from ._exceptions import AccessDenied
|
||||
from ._exceptions import NoSuchProcess
|
||||
from ._exceptions import ZombieProcess
|
||||
|
||||
|
||||
__extra__all__ = ["CONN_IDLE", "CONN_BOUND", "PROCFS_PATH"]
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- globals
|
||||
# =====================================================================
|
||||
|
||||
|
||||
PAGE_SIZE = os.sysconf('SC_PAGE_SIZE')
|
||||
AF_LINK = cext_posix.AF_LINK
|
||||
IS_64_BIT = sys.maxsize > 2**32
|
||||
|
||||
CONN_IDLE = "IDLE"
|
||||
CONN_BOUND = "BOUND"
|
||||
|
||||
PROC_STATUSES = {
|
||||
cext.SSLEEP: _common.STATUS_SLEEPING,
|
||||
cext.SRUN: _common.STATUS_RUNNING,
|
||||
cext.SZOMB: _common.STATUS_ZOMBIE,
|
||||
cext.SSTOP: _common.STATUS_STOPPED,
|
||||
cext.SIDL: _common.STATUS_IDLE,
|
||||
cext.SONPROC: _common.STATUS_RUNNING, # same as run
|
||||
cext.SWAIT: _common.STATUS_WAITING,
|
||||
}
|
||||
|
||||
TCP_STATUSES = {
|
||||
cext.TCPS_ESTABLISHED: _common.CONN_ESTABLISHED,
|
||||
cext.TCPS_SYN_SENT: _common.CONN_SYN_SENT,
|
||||
cext.TCPS_SYN_RCVD: _common.CONN_SYN_RECV,
|
||||
cext.TCPS_FIN_WAIT_1: _common.CONN_FIN_WAIT1,
|
||||
cext.TCPS_FIN_WAIT_2: _common.CONN_FIN_WAIT2,
|
||||
cext.TCPS_TIME_WAIT: _common.CONN_TIME_WAIT,
|
||||
cext.TCPS_CLOSED: _common.CONN_CLOSE,
|
||||
cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT,
|
||||
cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK,
|
||||
cext.TCPS_LISTEN: _common.CONN_LISTEN,
|
||||
cext.TCPS_CLOSING: _common.CONN_CLOSING,
|
||||
cext.PSUTIL_CONN_NONE: _common.CONN_NONE,
|
||||
cext.TCPS_IDLE: CONN_IDLE, # sunos specific
|
||||
cext.TCPS_BOUND: CONN_BOUND, # sunos specific
|
||||
}
|
||||
|
||||
proc_info_map = dict(
|
||||
ppid=0,
|
||||
rss=1,
|
||||
vms=2,
|
||||
create_time=3,
|
||||
nice=4,
|
||||
num_threads=5,
|
||||
status=6,
|
||||
ttynr=7)
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- named tuples
|
||||
# =====================================================================
|
||||
|
||||
|
||||
# psutil.cpu_times()
|
||||
scputimes = namedtuple('scputimes', ['user', 'system', 'idle', 'iowait'])
|
||||
# psutil.cpu_times(percpu=True)
|
||||
pcputimes = namedtuple('pcputimes',
|
||||
['user', 'system', 'children_user', 'children_system'])
|
||||
# psutil.virtual_memory()
|
||||
svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free'])
|
||||
# psutil.Process.memory_info()
|
||||
pmem = namedtuple('pmem', ['rss', 'vms'])
|
||||
pfullmem = pmem
|
||||
# psutil.Process.memory_maps(grouped=True)
|
||||
pmmap_grouped = namedtuple('pmmap_grouped',
|
||||
['path', 'rss', 'anonymous', 'locked'])
|
||||
# psutil.Process.memory_maps(grouped=False)
|
||||
pmmap_ext = namedtuple(
|
||||
'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields))
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- utils
|
||||
# =====================================================================
|
||||
|
||||
|
||||
def get_procfs_path():
|
||||
"""Return updated psutil.PROCFS_PATH constant."""
|
||||
return sys.modules['psutil'].PROCFS_PATH
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- memory
|
||||
# =====================================================================
|
||||
|
||||
|
||||
def virtual_memory():
|
||||
"""Report virtual memory metrics."""
|
||||
# we could have done this with kstat, but IMHO this is good enough
|
||||
total = os.sysconf('SC_PHYS_PAGES') * PAGE_SIZE
|
||||
# note: there's no difference on Solaris
|
||||
free = avail = os.sysconf('SC_AVPHYS_PAGES') * PAGE_SIZE
|
||||
used = total - free
|
||||
percent = usage_percent(used, total, _round=1)
|
||||
return svmem(total, avail, percent, used, free)
|
||||
|
||||
|
||||
def swap_memory():
|
||||
"""Report swap memory metrics."""
|
||||
sin, sout = cext.swap_mem()
|
||||
# XXX
|
||||
# we are supposed to get total/free by doing so:
|
||||
# http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/
|
||||
# usr/src/cmd/swap/swap.c
|
||||
# ...nevertheless I can't manage to obtain the same numbers as 'swap'
|
||||
# cmdline utility, so let's parse its output (sigh!)
|
||||
p = subprocess.Popen(['/usr/bin/env', 'PATH=/usr/sbin:/sbin:%s' %
|
||||
os.environ['PATH'], 'swap', '-l'],
|
||||
stdout=subprocess.PIPE)
|
||||
stdout, stderr = p.communicate()
|
||||
if PY3:
|
||||
stdout = stdout.decode(sys.stdout.encoding)
|
||||
if p.returncode != 0:
|
||||
raise RuntimeError("'swap -l' failed (retcode=%s)" % p.returncode)
|
||||
|
||||
lines = stdout.strip().split('\n')[1:]
|
||||
if not lines:
|
||||
raise RuntimeError('no swap device(s) configured')
|
||||
total = free = 0
|
||||
for line in lines:
|
||||
line = line.split()
|
||||
t, f = line[-2:]
|
||||
total += int(int(t) * 512)
|
||||
free += int(int(f) * 512)
|
||||
used = total - free
|
||||
percent = usage_percent(used, total, _round=1)
|
||||
return _common.sswap(total, used, free, percent,
|
||||
sin * PAGE_SIZE, sout * PAGE_SIZE)
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- CPU
|
||||
# =====================================================================
|
||||
|
||||
|
||||
def cpu_times():
|
||||
"""Return system-wide CPU times as a named tuple"""
|
||||
ret = cext.per_cpu_times()
|
||||
return scputimes(*[sum(x) for x in zip(*ret)])
|
||||
|
||||
|
||||
def per_cpu_times():
|
||||
"""Return system per-CPU times as a list of named tuples"""
|
||||
ret = cext.per_cpu_times()
|
||||
return [scputimes(*x) for x in ret]
|
||||
|
||||
|
||||
def cpu_count_logical():
|
||||
"""Return the number of logical CPUs in the system."""
|
||||
try:
|
||||
return os.sysconf("SC_NPROCESSORS_ONLN")
|
||||
except ValueError:
|
||||
# mimic os.cpu_count() behavior
|
||||
return None
|
||||
|
||||
|
||||
def cpu_count_physical():
|
||||
"""Return the number of physical CPUs in the system."""
|
||||
return cext.cpu_count_phys()
|
||||
|
||||
|
||||
def cpu_stats():
|
||||
"""Return various CPU stats as a named tuple."""
|
||||
ctx_switches, interrupts, syscalls, traps = cext.cpu_stats()
|
||||
soft_interrupts = 0
|
||||
return _common.scpustats(ctx_switches, interrupts, soft_interrupts,
|
||||
syscalls)
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- disks
|
||||
# =====================================================================
|
||||
|
||||
|
||||
disk_io_counters = cext.disk_io_counters
|
||||
disk_usage = _psposix.disk_usage
|
||||
|
||||
|
||||
def disk_partitions(all=False):
|
||||
"""Return system disk partitions."""
|
||||
# TODO - the filtering logic should be better checked so that
|
||||
# it tries to reflect 'df' as much as possible
|
||||
retlist = []
|
||||
partitions = cext.disk_partitions()
|
||||
for partition in partitions:
|
||||
device, mountpoint, fstype, opts = partition
|
||||
if device == 'none':
|
||||
device = ''
|
||||
if not all:
|
||||
# Differently from, say, Linux, we don't have a list of
|
||||
# common fs types so the best we can do, AFAIK, is to
|
||||
# filter by filesystem having a total size > 0.
|
||||
if not disk_usage(mountpoint).total:
|
||||
continue
|
||||
ntuple = _common.sdiskpart(device, mountpoint, fstype, opts)
|
||||
retlist.append(ntuple)
|
||||
return retlist
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- network
|
||||
# =====================================================================
|
||||
|
||||
|
||||
net_io_counters = cext.net_io_counters
|
||||
net_if_addrs = cext_posix.net_if_addrs
|
||||
|
||||
|
||||
def net_connections(kind, _pid=-1):
|
||||
"""Return socket connections. If pid == -1 return system-wide
|
||||
connections (as opposed to connections opened by one process only).
|
||||
Only INET sockets are returned (UNIX are not).
|
||||
"""
|
||||
cmap = _common.conn_tmap.copy()
|
||||
if _pid == -1:
|
||||
cmap.pop('unix', 0)
|
||||
if kind not in cmap:
|
||||
raise ValueError("invalid %r kind argument; choose between %s"
|
||||
% (kind, ', '.join([repr(x) for x in cmap])))
|
||||
families, types = _common.conn_tmap[kind]
|
||||
rawlist = cext.net_connections(_pid)
|
||||
ret = set()
|
||||
for item in rawlist:
|
||||
fd, fam, type_, laddr, raddr, status, pid = item
|
||||
if fam not in families:
|
||||
continue
|
||||
if type_ not in types:
|
||||
continue
|
||||
if fam in (AF_INET, AF_INET6):
|
||||
if laddr:
|
||||
laddr = _common.addr(*laddr)
|
||||
if raddr:
|
||||
raddr = _common.addr(*raddr)
|
||||
status = TCP_STATUSES[status]
|
||||
fam = sockfam_to_enum(fam)
|
||||
type_ = socktype_to_enum(type_)
|
||||
if _pid == -1:
|
||||
nt = _common.sconn(fd, fam, type_, laddr, raddr, status, pid)
|
||||
else:
|
||||
nt = _common.pconn(fd, fam, type_, laddr, raddr, status)
|
||||
ret.add(nt)
|
||||
return list(ret)
|
||||
|
||||
|
||||
def net_if_stats():
|
||||
"""Get NIC stats (isup, duplex, speed, mtu)."""
|
||||
ret = cext.net_if_stats()
|
||||
for name, items in ret.items():
|
||||
isup, duplex, speed, mtu = items
|
||||
if hasattr(_common, 'NicDuplex'):
|
||||
duplex = _common.NicDuplex(duplex)
|
||||
ret[name] = _common.snicstats(isup, duplex, speed, mtu)
|
||||
return ret
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- other system functions
|
||||
# =====================================================================
|
||||
|
||||
|
||||
def boot_time():
|
||||
"""The system boot time expressed in seconds since the epoch."""
|
||||
return cext.boot_time()
|
||||
|
||||
|
||||
def users():
|
||||
"""Return currently connected users as a list of namedtuples."""
|
||||
retlist = []
|
||||
rawlist = cext.users()
|
||||
localhost = (':0.0', ':0')
|
||||
for item in rawlist:
|
||||
user, tty, hostname, tstamp, user_process, pid = item
|
||||
# note: the underlying C function includes entries about
|
||||
# system boot, run level and others. We might want
|
||||
# to use them in the future.
|
||||
if not user_process:
|
||||
continue
|
||||
if hostname in localhost:
|
||||
hostname = 'localhost'
|
||||
nt = _common.suser(user, tty, hostname, tstamp, pid)
|
||||
retlist.append(nt)
|
||||
return retlist
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# --- processes
|
||||
# =====================================================================
|
||||
|
||||
|
||||
def pids():
|
||||
"""Returns a list of PIDs currently running on the system."""
|
||||
return [int(x) for x in os.listdir(b(get_procfs_path())) if x.isdigit()]
|
||||
|
||||
|
||||
def pid_exists(pid):
|
||||
"""Check for the existence of a unix pid."""
|
||||
return _psposix.pid_exists(pid)
|
||||
|
||||
|
||||
def wrap_exceptions(fun):
|
||||
"""Call callable into a try/except clause and translate ENOENT,
|
||||
EACCES and EPERM in NoSuchProcess or AccessDenied exceptions.
|
||||
"""
|
||||
|
||||
def wrapper(self, *args, **kwargs):
|
||||
try:
|
||||
return fun(self, *args, **kwargs)
|
||||
except EnvironmentError as err:
|
||||
if self.pid == 0:
|
||||
if 0 in pids():
|
||||
raise AccessDenied(self.pid, self._name)
|
||||
else:
|
||||
raise
|
||||
# ENOENT (no such file or directory) gets raised on open().
|
||||
# ESRCH (no such process) can get raised on read() if
|
||||
# process is gone in meantime.
|
||||
if err.errno in (errno.ENOENT, errno.ESRCH):
|
||||
if not pid_exists(self.pid):
|
||||
raise NoSuchProcess(self.pid, self._name)
|
||||
else:
|
||||
raise ZombieProcess(self.pid, self._name, self._ppid)
|
||||
if err.errno in (errno.EPERM, errno.EACCES):
|
||||
raise AccessDenied(self.pid, self._name)
|
||||
raise
|
||||
return wrapper
|
||||
|
||||
|
||||
class Process(object):
|
||||
"""Wrapper class around underlying C implementation."""
|
||||
|
||||
__slots__ = ["pid", "_name", "_ppid", "_procfs_path"]
|
||||
|
||||
def __init__(self, pid):
|
||||
self.pid = pid
|
||||
self._name = None
|
||||
self._ppid = None
|
||||
self._procfs_path = get_procfs_path()
|
||||
|
||||
def oneshot_enter(self):
|
||||
self._proc_name_and_args.cache_activate()
|
||||
self._proc_basic_info.cache_activate()
|
||||
self._proc_cred.cache_activate()
|
||||
|
||||
def oneshot_exit(self):
|
||||
self._proc_name_and_args.cache_deactivate()
|
||||
self._proc_basic_info.cache_deactivate()
|
||||
self._proc_cred.cache_deactivate()
|
||||
|
||||
@memoize_when_activated
|
||||
def _proc_name_and_args(self):
|
||||
return cext.proc_name_and_args(self.pid, self._procfs_path)
|
||||
|
||||
@memoize_when_activated
|
||||
def _proc_basic_info(self):
|
||||
ret = cext.proc_basic_info(self.pid, self._procfs_path)
|
||||
assert len(ret) == len(proc_info_map)
|
||||
return ret
|
||||
|
||||
@memoize_when_activated
|
||||
def _proc_cred(self):
|
||||
return cext.proc_cred(self.pid, self._procfs_path)
|
||||
|
||||
@wrap_exceptions
|
||||
def name(self):
|
||||
# note: max len == 15
|
||||
return self._proc_name_and_args()[0]
|
||||
|
||||
@wrap_exceptions
|
||||
def exe(self):
|
||||
try:
|
||||
return os.readlink(
|
||||
"%s/%s/path/a.out" % (self._procfs_path, self.pid))
|
||||
except OSError:
|
||||
pass # continue and guess the exe name from the cmdline
|
||||
# Will be guessed later from cmdline but we want to explicitly
|
||||
# invoke cmdline here in order to get an AccessDenied
|
||||
# exception if the user has not enough privileges.
|
||||
self.cmdline()
|
||||
return ""
|
||||
|
||||
@wrap_exceptions
|
||||
def cmdline(self):
|
||||
return self._proc_name_and_args()[1].split(' ')
|
||||
|
||||
@wrap_exceptions
|
||||
def environ(self):
|
||||
return cext.proc_environ(self.pid, self._procfs_path)
|
||||
|
||||
@wrap_exceptions
|
||||
def create_time(self):
|
||||
return self._proc_basic_info()[proc_info_map['create_time']]
|
||||
|
||||
@wrap_exceptions
|
||||
def num_threads(self):
|
||||
return self._proc_basic_info()[proc_info_map['num_threads']]
|
||||
|
||||
@wrap_exceptions
|
||||
def nice_get(self):
|
||||
# Note #1: for some reason getpriority(3) return ESRCH (no such
|
||||
# process) for certain low-pid processes, no matter what (even
|
||||
# as root).
|
||||
# The process actually exists though, as it has a name,
|
||||
# creation time, etc.
|
||||
# The best thing we can do here appears to be raising AD.
|
||||
# Note: tested on Solaris 11; on Open Solaris 5 everything is
|
||||
# fine.
|
||||
#
|
||||
# Note #2: we also can get niceness from /proc/pid/psinfo
|
||||
# but it's wrong, see:
|
||||
# https://github.com/giampaolo/psutil/issues/1082
|
||||
try:
|
||||
return cext_posix.getpriority(self.pid)
|
||||
except EnvironmentError as err:
|
||||
# 48 is 'operation not supported' but errno does not expose
|
||||
# it. It occurs for low system pids.
|
||||
if err.errno in (errno.ENOENT, errno.ESRCH, 48):
|
||||
if pid_exists(self.pid):
|
||||
raise AccessDenied(self.pid, self._name)
|
||||
raise
|
||||
|
||||
@wrap_exceptions
|
||||
def nice_set(self, value):
|
||||
if self.pid in (2, 3):
|
||||
# Special case PIDs: internally setpriority(3) return ESRCH
|
||||
# (no such process), no matter what.
|
||||
# The process actually exists though, as it has a name,
|
||||
# creation time, etc.
|
||||
raise AccessDenied(self.pid, self._name)
|
||||
return cext_posix.setpriority(self.pid, value)
|
||||
|
||||
@wrap_exceptions
|
||||
def ppid(self):
|
||||
self._ppid = self._proc_basic_info()[proc_info_map['ppid']]
|
||||
return self._ppid
|
||||
|
||||
@wrap_exceptions
|
||||
def uids(self):
|
||||
real, effective, saved, _, _, _ = self._proc_cred()
|
||||
return _common.puids(real, effective, saved)
|
||||
|
||||
@wrap_exceptions
|
||||
def gids(self):
|
||||
_, _, _, real, effective, saved = self._proc_cred()
|
||||
return _common.puids(real, effective, saved)
|
||||
|
||||
@wrap_exceptions
|
||||
def cpu_times(self):
|
||||
try:
|
||||
times = cext.proc_cpu_times(self.pid, self._procfs_path)
|
||||
except OSError as err:
|
||||
if err.errno == errno.EOVERFLOW and not IS_64_BIT:
|
||||
# We may get here if we attempt to query a 64bit process
|
||||
# with a 32bit python.
|
||||
# Error originates from read() and also tools like "cat"
|
||||
# fail in the same way (!).
|
||||
# Since there simply is no way to determine CPU times we
|
||||
# return 0.0 as a fallback. See:
|
||||
# https://github.com/giampaolo/psutil/issues/857
|
||||
times = (0.0, 0.0, 0.0, 0.0)
|
||||
else:
|
||||
raise
|
||||
return _common.pcputimes(*times)
|
||||
|
||||
@wrap_exceptions
|
||||
def cpu_num(self):
|
||||
return cext.proc_cpu_num(self.pid, self._procfs_path)
|
||||
|
||||
@wrap_exceptions
|
||||
def terminal(self):
|
||||
procfs_path = self._procfs_path
|
||||
hit_enoent = False
|
||||
tty = wrap_exceptions(
|
||||
self._proc_basic_info()[proc_info_map['ttynr']])
|
||||
if tty != cext.PRNODEV:
|
||||
for x in (0, 1, 2, 255):
|
||||
try:
|
||||
return os.readlink(
|
||||
'%s/%d/path/%d' % (procfs_path, self.pid, x))
|
||||
except OSError as err:
|
||||
if err.errno == errno.ENOENT:
|
||||
hit_enoent = True
|
||||
continue
|
||||
raise
|
||||
if hit_enoent:
|
||||
# raise NSP if the process disappeared on us
|
||||
os.stat('%s/%s' % (procfs_path, self.pid))
|
||||
|
||||
@wrap_exceptions
|
||||
def cwd(self):
|
||||
# /proc/PID/path/cwd may not be resolved by readlink() even if
|
||||
# it exists (ls shows it). If that's the case and the process
|
||||
# is still alive return None (we can return None also on BSD).
|
||||
# Reference: http://goo.gl/55XgO
|
||||
procfs_path = self._procfs_path
|
||||
try:
|
||||
return os.readlink("%s/%s/path/cwd" % (procfs_path, self.pid))
|
||||
except OSError as err:
|
||||
if err.errno == errno.ENOENT:
|
||||
os.stat("%s/%s" % (procfs_path, self.pid)) # raise NSP or AD
|
||||
return None
|
||||
raise
|
||||
|
||||
@wrap_exceptions
|
||||
def memory_info(self):
|
||||
ret = self._proc_basic_info()
|
||||
rss = ret[proc_info_map['rss']] * 1024
|
||||
vms = ret[proc_info_map['vms']] * 1024
|
||||
return pmem(rss, vms)
|
||||
|
||||
memory_full_info = memory_info
|
||||
|
||||
@wrap_exceptions
|
||||
def status(self):
|
||||
code = self._proc_basic_info()[proc_info_map['status']]
|
||||
# XXX is '?' legit? (we're not supposed to return it anyway)
|
||||
return PROC_STATUSES.get(code, '?')
|
||||
|
||||
@wrap_exceptions
|
||||
def threads(self):
|
||||
procfs_path = self._procfs_path
|
||||
ret = []
|
||||
tids = os.listdir('%s/%d/lwp' % (procfs_path, self.pid))
|
||||
hit_enoent = False
|
||||
for tid in tids:
|
||||
tid = int(tid)
|
||||
try:
|
||||
utime, stime = cext.query_process_thread(
|
||||
self.pid, tid, procfs_path)
|
||||
except EnvironmentError as err:
|
||||
if err.errno == errno.EOVERFLOW and not IS_64_BIT:
|
||||
# We may get here if we attempt to query a 64bit process
|
||||
# with a 32bit python.
|
||||
# Error originates from read() and also tools like "cat"
|
||||
# fail in the same way (!).
|
||||
# Since there simply is no way to determine CPU times we
|
||||
# return 0.0 as a fallback. See:
|
||||
# https://github.com/giampaolo/psutil/issues/857
|
||||
continue
|
||||
# ENOENT == thread gone in meantime
|
||||
if err.errno == errno.ENOENT:
|
||||
hit_enoent = True
|
||||
continue
|
||||
raise
|
||||
else:
|
||||
nt = _common.pthread(tid, utime, stime)
|
||||
ret.append(nt)
|
||||
if hit_enoent:
|
||||
# raise NSP if the process disappeared on us
|
||||
os.stat('%s/%s' % (procfs_path, self.pid))
|
||||
return ret
|
||||
|
||||
@wrap_exceptions
|
||||
def open_files(self):
|
||||
retlist = []
|
||||
hit_enoent = False
|
||||
procfs_path = self._procfs_path
|
||||
pathdir = '%s/%d/path' % (procfs_path, self.pid)
|
||||
for fd in os.listdir('%s/%d/fd' % (procfs_path, self.pid)):
|
||||
path = os.path.join(pathdir, fd)
|
||||
if os.path.islink(path):
|
||||
try:
|
||||
file = os.readlink(path)
|
||||
except OSError as err:
|
||||
# ENOENT == file which is gone in the meantime
|
||||
if err.errno == errno.ENOENT:
|
||||
hit_enoent = True
|
||||
continue
|
||||
raise
|
||||
else:
|
||||
if isfile_strict(file):
|
||||
retlist.append(_common.popenfile(file, int(fd)))
|
||||
if hit_enoent:
|
||||
# raise NSP if the process disappeared on us
|
||||
os.stat('%s/%s' % (procfs_path, self.pid))
|
||||
return retlist
|
||||
|
||||
def _get_unix_sockets(self, pid):
|
||||
"""Get UNIX sockets used by process by parsing 'pfiles' output."""
|
||||
# TODO: rewrite this in C (...but the damn netstat source code
|
||||
# does not include this part! Argh!!)
|
||||
cmd = "pfiles %s" % pid
|
||||
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
stdout, stderr = p.communicate()
|
||||
if PY3:
|
||||
stdout, stderr = [x.decode(sys.stdout.encoding)
|
||||
for x in (stdout, stderr)]
|
||||
if p.returncode != 0:
|
||||
if 'permission denied' in stderr.lower():
|
||||
raise AccessDenied(self.pid, self._name)
|
||||
if 'no such process' in stderr.lower():
|
||||
raise NoSuchProcess(self.pid, self._name)
|
||||
raise RuntimeError("%r command error\n%s" % (cmd, stderr))
|
||||
|
||||
lines = stdout.split('\n')[2:]
|
||||
for i, line in enumerate(lines):
|
||||
line = line.lstrip()
|
||||
if line.startswith('sockname: AF_UNIX'):
|
||||
path = line.split(' ', 2)[2]
|
||||
type = lines[i - 2].strip()
|
||||
if type == 'SOCK_STREAM':
|
||||
type = socket.SOCK_STREAM
|
||||
elif type == 'SOCK_DGRAM':
|
||||
type = socket.SOCK_DGRAM
|
||||
else:
|
||||
type = -1
|
||||
yield (-1, socket.AF_UNIX, type, path, "", _common.CONN_NONE)
|
||||
|
||||
@wrap_exceptions
|
||||
def connections(self, kind='inet'):
|
||||
ret = net_connections(kind, _pid=self.pid)
|
||||
# The underlying C implementation retrieves all OS connections
|
||||
# and filters them by PID. At this point we can't tell whether
|
||||
# an empty list means there were no connections for process or
|
||||
# process is no longer active so we force NSP in case the PID
|
||||
# is no longer there.
|
||||
if not ret:
|
||||
# will raise NSP if process is gone
|
||||
os.stat('%s/%s' % (self._procfs_path, self.pid))
|
||||
|
||||
# UNIX sockets
|
||||
if kind in ('all', 'unix'):
|
||||
ret.extend([_common.pconn(*conn) for conn in
|
||||
self._get_unix_sockets(self.pid)])
|
||||
return ret
|
||||
|
||||
nt_mmap_grouped = namedtuple('mmap', 'path rss anon locked')
|
||||
nt_mmap_ext = namedtuple('mmap', 'addr perms path rss anon locked')
|
||||
|
||||
@wrap_exceptions
|
||||
def memory_maps(self):
|
||||
def toaddr(start, end):
|
||||
return '%s-%s' % (hex(start)[2:].strip('L'),
|
||||
hex(end)[2:].strip('L'))
|
||||
|
||||
procfs_path = self._procfs_path
|
||||
retlist = []
|
||||
try:
|
||||
rawlist = cext.proc_memory_maps(self.pid, procfs_path)
|
||||
except OSError as err:
|
||||
if err.errno == errno.EOVERFLOW and not IS_64_BIT:
|
||||
# We may get here if we attempt to query a 64bit process
|
||||
# with a 32bit python.
|
||||
# Error originates from read() and also tools like "cat"
|
||||
# fail in the same way (!).
|
||||
# Since there simply is no way to determine CPU times we
|
||||
# return 0.0 as a fallback. See:
|
||||
# https://github.com/giampaolo/psutil/issues/857
|
||||
return []
|
||||
else:
|
||||
raise
|
||||
hit_enoent = False
|
||||
for item in rawlist:
|
||||
addr, addrsize, perm, name, rss, anon, locked = item
|
||||
addr = toaddr(addr, addrsize)
|
||||
if not name.startswith('['):
|
||||
try:
|
||||
name = os.readlink(
|
||||
'%s/%s/path/%s' % (procfs_path, self.pid, name))
|
||||
except OSError as err:
|
||||
if err.errno == errno.ENOENT:
|
||||
# sometimes the link may not be resolved by
|
||||
# readlink() even if it exists (ls shows it).
|
||||
# If that's the case we just return the
|
||||
# unresolved link path.
|
||||
# This seems an incosistency with /proc similar
|
||||
# to: http://goo.gl/55XgO
|
||||
name = '%s/%s/path/%s' % (procfs_path, self.pid, name)
|
||||
hit_enoent = True
|
||||
else:
|
||||
raise
|
||||
retlist.append((addr, perm, name, rss, anon, locked))
|
||||
if hit_enoent:
|
||||
# raise NSP if the process disappeared on us
|
||||
os.stat('%s/%s' % (procfs_path, self.pid))
|
||||
return retlist
|
||||
|
||||
@wrap_exceptions
|
||||
def num_fds(self):
|
||||
return len(os.listdir("%s/%s/fd" % (self._procfs_path, self.pid)))
|
||||
|
||||
@wrap_exceptions
|
||||
def num_ctx_switches(self):
|
||||
return _common.pctxsw(
|
||||
*cext.proc_num_ctx_switches(self.pid, self._procfs_path))
|
||||
|
||||
@wrap_exceptions
|
||||
def wait(self, timeout=None):
|
||||
return _psposix.wait_pid(self.pid, timeout, self._name)
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче