diff --git a/ddtrace/_monkey.py b/ddtrace/_monkey.py index dea6c6eb069..8790d653296 100644 --- a/ddtrace/_monkey.py +++ b/ddtrace/_monkey.py @@ -3,7 +3,7 @@ import threading from typing import TYPE_CHECKING -from ddtrace.vendor.wrapt.importer import when_imported +from wrapt.importer import when_imported from .internal.compat import PY2 from .internal.logger import get_logger diff --git a/ddtrace/appsec/_handlers.py b/ddtrace/appsec/_handlers.py index e1267bff344..5bef07851f4 100644 --- a/ddtrace/appsec/_handlers.py +++ b/ddtrace/appsec/_handlers.py @@ -2,6 +2,8 @@ import json from six import BytesIO +from wrapt import wrap_function_wrapper as _w +from wrapt.importer import when_imported import xmltodict from ddtrace import config @@ -12,8 +14,6 @@ from ddtrace.internal import core from ddtrace.internal.constants import HTTP_REQUEST_BLOCKED from ddtrace.internal.logger import get_logger -from ddtrace.vendor.wrapt import wrap_function_wrapper as _w -from ddtrace.vendor.wrapt.importer import when_imported try: diff --git a/ddtrace/appsec/_iast/_patch.py b/ddtrace/appsec/_iast/_patch.py index 13fbcbd96bb..ce80d4f3efd 100644 --- a/ddtrace/appsec/_iast/_patch.py +++ b/ddtrace/appsec/_iast/_patch.py @@ -3,9 +3,10 @@ import sys from typing import TYPE_CHECKING +from wrapt import FunctionWrapper +from wrapt import resolve_path + from ddtrace.internal.logger import get_logger -from ddtrace.vendor.wrapt import FunctionWrapper -from ddtrace.vendor.wrapt import resolve_path from ._utils import _is_iast_enabled diff --git a/ddtrace/appsec/_iast/_patch_modules.py b/ddtrace/appsec/_iast/_patch_modules.py index 90308d70c39..e1e28365159 100644 --- a/ddtrace/appsec/_iast/_patch_modules.py +++ b/ddtrace/appsec/_iast/_patch_modules.py @@ -1,4 +1,4 @@ -from ddtrace.vendor.wrapt.importer import when_imported +from wrapt.importer import when_imported IAST_PATCH = { diff --git a/ddtrace/contrib/aiobotocore/patch.py b/ddtrace/contrib/aiobotocore/patch.py index 9e52417947a..64b214b78f0 100644 --- a/ddtrace/contrib/aiobotocore/patch.py +++ b/ddtrace/contrib/aiobotocore/patch.py @@ -1,11 +1,11 @@ import os import aiobotocore.client +import wrapt from ddtrace import config from ddtrace.internal.constants import COMPONENT from ddtrace.internal.utils.version import parse_version -from ddtrace.vendor import wrapt from ...constants import ANALYTICS_SAMPLE_RATE_KEY from ...constants import SPAN_KIND diff --git a/ddtrace/contrib/aiohttp/patch.py b/ddtrace/contrib/aiohttp/patch.py index 5cf0bdd24c7..b84dd9af267 100644 --- a/ddtrace/contrib/aiohttp/patch.py +++ b/ddtrace/contrib/aiohttp/patch.py @@ -1,6 +1,7 @@ import os import aiohttp +import wrapt from yarl import URL from ddtrace import config @@ -10,7 +11,6 @@ from ddtrace.internal.schema.span_attribute_schema import SpanDirection from ddtrace.internal.utils import get_argument_value from ddtrace.internal.utils.formats import asbool -from ddtrace.vendor import wrapt from ...ext import SpanKind from ...ext import SpanTypes diff --git a/ddtrace/contrib/aiomysql/patch.py b/ddtrace/contrib/aiomysql/patch.py index 56a9636b4f3..588f6b0f98b 100644 --- a/ddtrace/contrib/aiomysql/patch.py +++ b/ddtrace/contrib/aiomysql/patch.py @@ -1,4 +1,5 @@ import aiomysql +import wrapt from ddtrace import Pin from ddtrace import config @@ -9,7 +10,6 @@ from ddtrace.internal.constants import COMPONENT from ddtrace.internal.schema import schematize_database_operation from ddtrace.internal.utils.wrappers import unwrap -from ddtrace.vendor import wrapt from ...ext import SpanKind from ...ext import SpanTypes diff --git a/ddtrace/contrib/aiopg/connection.py b/ddtrace/contrib/aiopg/connection.py index 3373405d26d..a9eeb9c5c3f 100644 --- a/ddtrace/contrib/aiopg/connection.py +++ b/ddtrace/contrib/aiopg/connection.py @@ -2,6 +2,7 @@ from aiopg import __version__ from aiopg.utils import _ContextManager +import wrapt from ddtrace import config from ddtrace.constants import ANALYTICS_SAMPLE_RATE_KEY @@ -16,7 +17,6 @@ from ddtrace.internal.schema import schematize_service_name from ddtrace.internal.utils.version import parse_version from ddtrace.pin import Pin -from ddtrace.vendor import wrapt AIOPG_VERSION = parse_version(__version__) diff --git a/ddtrace/contrib/aiopg/patch.py b/ddtrace/contrib/aiopg/patch.py index 1e15d54f6d7..d0b03bc7891 100644 --- a/ddtrace/contrib/aiopg/patch.py +++ b/ddtrace/contrib/aiopg/patch.py @@ -3,13 +3,13 @@ import aiopg.connection import psycopg2.extensions +import wrapt from ddtrace.contrib.aiopg.connection import AIOTracedConnection from ddtrace.contrib.psycopg.connection import patch_conn as psycopg_patch_conn from ddtrace.contrib.psycopg.extensions import _patch_extensions from ddtrace.contrib.psycopg.extensions import _unpatch_extensions from ddtrace.internal.utils.wrappers import unwrap as _u -from ddtrace.vendor import wrapt def get_version(): diff --git a/ddtrace/contrib/aioredis/patch.py b/ddtrace/contrib/aioredis/patch.py index 9fe2d7dd216..57e5f4675ef 100644 --- a/ddtrace/contrib/aioredis/patch.py +++ b/ddtrace/contrib/aioredis/patch.py @@ -3,12 +3,12 @@ import sys import aioredis +from wrapt import wrap_function_wrapper as _w from ddtrace import config from ddtrace.internal.constants import COMPONENT from ddtrace.internal.utils.wrappers import unwrap as _u from ddtrace.pin import Pin -from ddtrace.vendor.wrapt import wrap_function_wrapper as _w from .. import trace_utils from ...constants import ANALYTICS_SAMPLE_RATE_KEY diff --git a/ddtrace/contrib/algoliasearch/patch.py b/ddtrace/contrib/algoliasearch/patch.py index d160392a54b..1624fe52ca4 100644 --- a/ddtrace/contrib/algoliasearch/patch.py +++ b/ddtrace/contrib/algoliasearch/patch.py @@ -1,3 +1,5 @@ +from wrapt import wrap_function_wrapper as _w + from ddtrace import config from ddtrace.ext import SpanKind from ddtrace.ext import SpanTypes @@ -6,7 +8,6 @@ from ddtrace.internal.schema import schematize_service_name from ddtrace.internal.utils.wrappers import unwrap as _u from ddtrace.pin import Pin -from ddtrace.vendor.wrapt import wrap_function_wrapper as _w from .. import trace_utils from ...constants import SPAN_KIND diff --git a/ddtrace/contrib/aredis/patch.py b/ddtrace/contrib/aredis/patch.py index 040a82b8dea..c4cd452c480 100644 --- a/ddtrace/contrib/aredis/patch.py +++ b/ddtrace/contrib/aredis/patch.py @@ -1,9 +1,9 @@ import os import aredis +import wrapt from ddtrace import config -from ddtrace.vendor import wrapt from ...internal.schema import schematize_service_name from ...internal.utils.formats import CMD_MAX_LEN diff --git a/ddtrace/contrib/asyncio/patch.py b/ddtrace/contrib/asyncio/patch.py index 5dfcc8b7684..3475daed889 100644 --- a/ddtrace/contrib/asyncio/patch.py +++ b/ddtrace/contrib/asyncio/patch.py @@ -1,8 +1,8 @@ import asyncio import sys -from ddtrace.vendor.wrapt import ObjectProxy -from ddtrace.vendor.wrapt import wrap_function_wrapper as _w +from wrapt import ObjectProxy +from wrapt import wrap_function_wrapper as _w from ..trace_utils import unwrap as _u from .wrappers import wrapped_create_task diff --git a/ddtrace/contrib/asyncpg/patch.py b/ddtrace/contrib/asyncpg/patch.py index 757113df43c..dd6e52d29ae 100644 --- a/ddtrace/contrib/asyncpg/patch.py +++ b/ddtrace/contrib/asyncpg/patch.py @@ -1,11 +1,11 @@ from typing import TYPE_CHECKING import asyncpg +import wrapt from ddtrace import Pin from ddtrace import config from ddtrace.internal.constants import COMPONENT -from ddtrace.vendor import wrapt from ...constants import SPAN_KIND from ...constants import SPAN_MEASURED_KEY diff --git a/ddtrace/contrib/boto/patch.py b/ddtrace/contrib/boto/patch.py index 4db66fbb6b2..207ad14b4c9 100644 --- a/ddtrace/contrib/boto/patch.py +++ b/ddtrace/contrib/boto/patch.py @@ -3,6 +3,7 @@ from boto import __version__ import boto.connection +import wrapt from ddtrace import config from ddtrace.constants import ANALYTICS_SAMPLE_RATE_KEY @@ -15,7 +16,6 @@ from ddtrace.internal.constants import COMPONENT from ddtrace.internal.utils.wrappers import unwrap from ddtrace.pin import Pin -from ddtrace.vendor import wrapt from ...internal.schema import schematize_cloud_api_operation from ...internal.schema import schematize_service_name @@ -140,7 +140,7 @@ def patched_auth_request(original_func, instance, args, kwargs): # Go up the stack until we get the first non-ddtrace module # DEV: For `lambda.list_functions()` this should be: # - ddtrace.contrib.boto.patch - # - ddtrace.vendor.wrapt.wrappers + # - wrapt.wrappers # - boto.awslambda.layer1 (make_request) # - boto.awslambda.layer1 (list_functions) # But can vary depending on Python versions; that's why we use an heuristic diff --git a/ddtrace/contrib/botocore/patch.py b/ddtrace/contrib/botocore/patch.py index b068e37d268..d6a57a417ee 100644 --- a/ddtrace/contrib/botocore/patch.py +++ b/ddtrace/contrib/botocore/patch.py @@ -18,11 +18,11 @@ from botocore import __version__ import botocore.client import botocore.exceptions +import wrapt from ddtrace import config from ddtrace.internal.schema.span_attribute_schema import SpanDirection from ddtrace.settings.config import Config -from ddtrace.vendor import wrapt from ...constants import ANALYTICS_SAMPLE_RATE_KEY from ...constants import SPAN_KIND diff --git a/ddtrace/contrib/bottle/patch.py b/ddtrace/contrib/bottle/patch.py index d22f076e38e..bf5f8908c1f 100644 --- a/ddtrace/contrib/bottle/patch.py +++ b/ddtrace/contrib/bottle/patch.py @@ -1,9 +1,9 @@ import os import bottle +import wrapt from ddtrace import config -from ddtrace.vendor import wrapt from ...internal.utils.formats import asbool from .trace import TracePlugin diff --git a/ddtrace/contrib/cassandra/session.py b/ddtrace/contrib/cassandra/session.py index dd53e5bd8e6..136d5f7b632 100644 --- a/ddtrace/contrib/cassandra/session.py +++ b/ddtrace/contrib/cassandra/session.py @@ -11,6 +11,8 @@ except AttributeError: from cassandra import cluster as cassandra_cluster +import wrapt + from ddtrace import config from ddtrace.internal.constants import COMPONENT @@ -32,7 +34,6 @@ from ...internal.utils import get_argument_value from ...internal.utils.formats import deep_getattr from ...pin import Pin -from ...vendor import wrapt log = get_logger(__name__) diff --git a/ddtrace/contrib/consul/patch.py b/ddtrace/contrib/consul/patch.py index 41873407c67..4cf00dbac44 100644 --- a/ddtrace/contrib/consul/patch.py +++ b/ddtrace/contrib/consul/patch.py @@ -1,9 +1,9 @@ import consul +from wrapt import wrap_function_wrapper as _w from ddtrace import config from ddtrace.internal.constants import COMPONENT from ddtrace.internal.schema.span_attribute_schema import SpanDirection -from ddtrace.vendor.wrapt import wrap_function_wrapper as _w from ...constants import ANALYTICS_SAMPLE_RATE_KEY from ...constants import SPAN_KIND diff --git a/ddtrace/contrib/dbapi/__init__.py b/ddtrace/contrib/dbapi/__init__.py index 04eb10365e0..cb301d6870b 100644 --- a/ddtrace/contrib/dbapi/__init__.py +++ b/ddtrace/contrib/dbapi/__init__.py @@ -2,6 +2,7 @@ Generic dbapi tracing code. """ import six +import wrapt from ddtrace import config from ddtrace.appsec._iast._utils import _is_iast_enabled @@ -19,7 +20,6 @@ from ...internal.utils import ArgumentError from ...internal.utils import get_argument_value from ...pin import Pin -from ...vendor import wrapt from ..trace_utils import ext_service from ..trace_utils import iswrapped diff --git a/ddtrace/contrib/django/patch.py b/ddtrace/contrib/django/patch.py index b8bded7708b..f4f0e119602 100644 --- a/ddtrace/contrib/django/patch.py +++ b/ddtrace/contrib/django/patch.py @@ -12,6 +12,9 @@ from inspect import isfunction import os +import wrapt +from wrapt.importer import when_imported + from ddtrace import Pin from ddtrace import config from ddtrace.appsec import _asm_request_context @@ -38,8 +41,6 @@ from ddtrace.internal.schema.span_attribute_schema import SpanDirection from ddtrace.internal.utils.formats import asbool from ddtrace.settings.integration import IntegrationConfig -from ddtrace.vendor import wrapt -from ddtrace.vendor.wrapt.importer import when_imported from .. import trace_utils from ...appsec._constants import WAF_CONTEXT_NAMES diff --git a/ddtrace/contrib/django/restframework.py b/ddtrace/contrib/django/restframework.py index ed0c789efa9..c4af8b44409 100644 --- a/ddtrace/contrib/django/restframework.py +++ b/ddtrace/contrib/django/restframework.py @@ -1,6 +1,5 @@ import rest_framework.views - -from ddtrace.vendor.wrapt import wrap_function_wrapper as wrap +from wrapt import wrap_function_wrapper as wrap from ..trace_utils import iswrapped from ..trace_utils import with_traced_module diff --git a/ddtrace/contrib/django/utils.py b/ddtrace/contrib/django/utils.py index fc52d806c52..a9987e90406 100644 --- a/ddtrace/contrib/django/utils.py +++ b/ddtrace/contrib/django/utils.py @@ -9,6 +9,7 @@ import django from django.utils.functional import SimpleLazyObject import six +from wrapt import FunctionWrapper import xmltodict from ddtrace import config @@ -23,7 +24,6 @@ from ...internal import core from ...internal.logger import get_logger from ...internal.utils.formats import stringify_cache_args -from ...vendor.wrapt import FunctionWrapper from .compat import get_resolver from .compat import user_is_authenticated diff --git a/ddtrace/contrib/dogpile_cache/patch.py b/ddtrace/contrib/dogpile_cache/patch.py index 81dba87b25f..83cfe6a97a9 100644 --- a/ddtrace/contrib/dogpile_cache/patch.py +++ b/ddtrace/contrib/dogpile_cache/patch.py @@ -5,11 +5,12 @@ from dogpile import cache as dogpile_cache from dogpile import lock as dogpile_lock +from wrapt import wrap_function_wrapper as _w + from ddtrace.internal.schema import schematize_service_name from ddtrace.pin import Pin from ddtrace.pin import _DD_PIN_NAME from ddtrace.pin import _DD_PIN_PROXY_NAME -from ddtrace.vendor.wrapt import wrap_function_wrapper as _w from .lock import _wrap_lock_ctor from .region import _wrap_get_create diff --git a/ddtrace/contrib/elasticsearch/patch.py b/ddtrace/contrib/elasticsearch/patch.py index a49eb7b1d65..48f2618adc8 100644 --- a/ddtrace/contrib/elasticsearch/patch.py +++ b/ddtrace/contrib/elasticsearch/patch.py @@ -1,6 +1,8 @@ from importlib import import_module from typing import List +from wrapt import wrap_function_wrapper as _w + from ddtrace import config from ddtrace._tracing import _limits from ddtrace.contrib.trace_utils import ext_service @@ -8,7 +10,6 @@ from ddtrace.ext import net from ddtrace.internal.constants import COMPONENT from ddtrace.internal.logger import get_logger -from ddtrace.vendor.wrapt import wrap_function_wrapper as _w from ...constants import ANALYTICS_SAMPLE_RATE_KEY from ...constants import SPAN_KIND diff --git a/ddtrace/contrib/falcon/patch.py b/ddtrace/contrib/falcon/patch.py index d8deeb6cdb3..3a153c147cf 100644 --- a/ddtrace/contrib/falcon/patch.py +++ b/ddtrace/contrib/falcon/patch.py @@ -1,10 +1,10 @@ import os import falcon +import wrapt from ddtrace import config from ddtrace import tracer -from ddtrace.vendor import wrapt from ...internal.utils.formats import asbool from ...internal.utils.version import parse_version diff --git a/ddtrace/contrib/fastapi/patch.py b/ddtrace/contrib/fastapi/patch.py index 89fb7813586..7aa0285611d 100644 --- a/ddtrace/contrib/fastapi/patch.py +++ b/ddtrace/contrib/fastapi/patch.py @@ -1,5 +1,7 @@ import fastapi import fastapi.routing +from wrapt import ObjectProxy +from wrapt import wrap_function_wrapper as _w from ddtrace import Pin from ddtrace import config @@ -8,8 +10,6 @@ from ddtrace.internal.logger import get_logger from ddtrace.internal.schema import schematize_service_name from ddtrace.internal.utils.wrappers import unwrap as _u -from ddtrace.vendor.wrapt import ObjectProxy -from ddtrace.vendor.wrapt import wrap_function_wrapper as _w log = get_logger(__name__) diff --git a/ddtrace/contrib/flask/patch.py b/ddtrace/contrib/flask/patch.py index eac546fbfd3..c8f3e065ac2 100644 --- a/ddtrace/contrib/flask/patch.py +++ b/ddtrace/contrib/flask/patch.py @@ -22,9 +22,10 @@ except ImportError: _HAS_JSON_MIXIN = False +from wrapt import wrap_function_wrapper as _w + from ddtrace import Pin from ddtrace import config -from ddtrace.vendor.wrapt import wrap_function_wrapper as _w from ...contrib.wsgi.wsgi import _DDWSGIMiddlewareBase from ...internal.logger import get_logger diff --git a/ddtrace/contrib/flask/wrappers.py b/ddtrace/contrib/flask/wrappers.py index 8c2628f6eb6..feeb20ab4b3 100644 --- a/ddtrace/contrib/flask/wrappers.py +++ b/ddtrace/contrib/flask/wrappers.py @@ -1,8 +1,8 @@ import flask +from wrapt import function_wrapper from ddtrace import config from ddtrace.internal import core -from ddtrace.vendor.wrapt import function_wrapper from ...internal.logger import get_logger from ...internal.utils.importlib import func_name diff --git a/ddtrace/contrib/grpc/aio_server_interceptor.py b/ddtrace/contrib/grpc/aio_server_interceptor.py index 1a917080c2d..b2a505be6e9 100644 --- a/ddtrace/contrib/grpc/aio_server_interceptor.py +++ b/ddtrace/contrib/grpc/aio_server_interceptor.py @@ -11,6 +11,7 @@ from grpc.aio._typing import RequestType from grpc.aio._typing import ResponseIterableType from grpc.aio._typing import ResponseType +import wrapt from ddtrace import Pin from ddtrace import Span @@ -18,7 +19,6 @@ from ddtrace.internal.constants import COMPONENT from ddtrace.internal.schema import schematize_url_operation from ddtrace.internal.schema.span_attribute_schema import SpanDirection -from ddtrace.vendor import wrapt from .. import trace_utils from ...constants import ANALYTICS_SAMPLE_RATE_KEY diff --git a/ddtrace/contrib/grpc/client_interceptor.py b/ddtrace/contrib/grpc/client_interceptor.py index cb58131447d..ae7893ae3ad 100644 --- a/ddtrace/contrib/grpc/client_interceptor.py +++ b/ddtrace/contrib/grpc/client_interceptor.py @@ -1,6 +1,7 @@ import collections import grpc +import wrapt from ddtrace import config from ddtrace.ext import SpanKind @@ -9,7 +10,6 @@ from ddtrace.internal.compat import to_unicode from ddtrace.internal.constants import COMPONENT from ddtrace.internal.schema.span_attribute_schema import SpanDirection -from ddtrace.vendor import wrapt from . import constants from . import utils diff --git a/ddtrace/contrib/grpc/patch.py b/ddtrace/contrib/grpc/patch.py index 0d823a14e58..2f02df299cc 100644 --- a/ddtrace/contrib/grpc/patch.py +++ b/ddtrace/contrib/grpc/patch.py @@ -1,9 +1,9 @@ import grpc +from wrapt import wrap_function_wrapper as _w from ddtrace import Pin from ddtrace import config from ddtrace.internal.schema import schematize_service_name -from ddtrace.vendor.wrapt import wrap_function_wrapper as _w from . import constants from . import utils diff --git a/ddtrace/contrib/grpc/server_interceptor.py b/ddtrace/contrib/grpc/server_interceptor.py index c565d0b94f2..1adea38f023 100644 --- a/ddtrace/contrib/grpc/server_interceptor.py +++ b/ddtrace/contrib/grpc/server_interceptor.py @@ -1,11 +1,11 @@ import grpc +import wrapt from ddtrace import config from ddtrace.internal.compat import to_unicode from ddtrace.internal.constants import COMPONENT from ddtrace.internal.schema import schematize_url_operation from ddtrace.internal.schema.span_attribute_schema import SpanDirection -from ddtrace.vendor import wrapt from . import constants from .. import trace_utils diff --git a/ddtrace/contrib/httplib/patch.py b/ddtrace/contrib/httplib/patch.py index 90795167a82..22e3dbc75a7 100644 --- a/ddtrace/contrib/httplib/patch.py +++ b/ddtrace/contrib/httplib/patch.py @@ -2,11 +2,11 @@ import sys import six +import wrapt from ddtrace import config from ddtrace.internal.constants import COMPONENT from ddtrace.internal.schema.span_attribute_schema import SpanDirection -from ddtrace.vendor import wrapt from .. import trace_utils from ...constants import ANALYTICS_SAMPLE_RATE_KEY diff --git a/ddtrace/contrib/httpx/patch.py b/ddtrace/contrib/httpx/patch.py index 3dbad1ca4c3..a459d3510ca 100644 --- a/ddtrace/contrib/httpx/patch.py +++ b/ddtrace/contrib/httpx/patch.py @@ -4,6 +4,7 @@ import httpx from six import ensure_binary from six import ensure_text +from wrapt import wrap_function_wrapper as _w from ddtrace import config from ddtrace.constants import ANALYTICS_SAMPLE_RATE_KEY @@ -23,12 +24,12 @@ from ddtrace.internal.utils.wrappers import unwrap as _u from ddtrace.pin import Pin from ddtrace.propagation.http import HTTPPropagator -from ddtrace.vendor.wrapt import wrap_function_wrapper as _w if typing.TYPE_CHECKING: # pragma: no cover + from wrapt import BoundFunctionWrapper + from ddtrace import Span - from ddtrace.vendor.wrapt import BoundFunctionWrapper HTTPX_VERSION = parse_version(httpx.__version__) diff --git a/ddtrace/contrib/jinja2/patch.py b/ddtrace/contrib/jinja2/patch.py index 2ffd2f6a55f..7e705b5830d 100644 --- a/ddtrace/contrib/jinja2/patch.py +++ b/ddtrace/contrib/jinja2/patch.py @@ -1,10 +1,10 @@ import os import jinja2 +from wrapt import wrap_function_wrapper as _w from ddtrace import config from ddtrace.internal.constants import COMPONENT -from ddtrace.vendor.wrapt import wrap_function_wrapper as _w from ...constants import SPAN_MEASURED_KEY from ...ext import SpanTypes diff --git a/ddtrace/contrib/kombu/patch.py b/ddtrace/contrib/kombu/patch.py index 99a390229c6..6f073ce324f 100644 --- a/ddtrace/contrib/kombu/patch.py +++ b/ddtrace/contrib/kombu/patch.py @@ -2,13 +2,13 @@ # 3p import kombu +import wrapt from ddtrace import config from ddtrace.internal.constants import COMPONENT from ddtrace.internal.schema import schematize_messaging_operation from ddtrace.internal.schema import schematize_service_name from ddtrace.internal.schema.span_attribute_schema import SpanDirection -from ddtrace.vendor import wrapt # project from .. import trace_utils diff --git a/ddtrace/contrib/langchain/patch.py b/ddtrace/contrib/langchain/patch.py index a7e2a483e3b..a7dc115822e 100644 --- a/ddtrace/contrib/langchain/patch.py +++ b/ddtrace/contrib/langchain/patch.py @@ -7,6 +7,7 @@ import langchain from langchain.callbacks.openai_info import get_openai_token_cost_for_model +import wrapt from ddtrace import config from ddtrace.constants import ERROR_TYPE @@ -30,7 +31,6 @@ from ddtrace.internal.utils.formats import asbool from ddtrace.internal.utils.formats import deep_getattr from ddtrace.pin import Pin -from ddtrace.vendor import wrapt if TYPE_CHECKING: diff --git a/ddtrace/contrib/logging/patch.py b/ddtrace/contrib/logging/patch.py index 7f5c0e8b0c5..3d4af7428a1 100644 --- a/ddtrace/contrib/logging/patch.py +++ b/ddtrace/contrib/logging/patch.py @@ -1,12 +1,12 @@ import logging import attr +from wrapt import wrap_function_wrapper as _w import ddtrace from ddtrace import config from ...internal.utils import get_argument_value -from ...vendor.wrapt import wrap_function_wrapper as _w from ..trace_utils import unwrap as _u diff --git a/ddtrace/contrib/mariadb/patch.py b/ddtrace/contrib/mariadb/patch.py index 771bb0555be..85db3678de2 100644 --- a/ddtrace/contrib/mariadb/patch.py +++ b/ddtrace/contrib/mariadb/patch.py @@ -1,6 +1,7 @@ import os import mariadb +import wrapt from ddtrace import Pin from ddtrace import config @@ -10,7 +11,6 @@ from ddtrace.internal.schema import schematize_service_name from ddtrace.internal.utils.formats import asbool from ddtrace.internal.utils.wrappers import unwrap -from ddtrace.vendor import wrapt config._add( diff --git a/ddtrace/contrib/molten/patch.py b/ddtrace/contrib/molten/patch.py index 411e89bf2a0..f8e2a62ac76 100644 --- a/ddtrace/contrib/molten/patch.py +++ b/ddtrace/contrib/molten/patch.py @@ -1,11 +1,11 @@ import os import molten +import wrapt +from wrapt import wrap_function_wrapper as _w from ddtrace.internal.constants import COMPONENT from ddtrace.internal.schema.span_attribute_schema import SpanDirection -from ddtrace.vendor import wrapt -from ddtrace.vendor.wrapt import wrap_function_wrapper as _w from .. import trace_utils from ... import Pin diff --git a/ddtrace/contrib/molten/wrappers.py b/ddtrace/contrib/molten/wrappers.py index fca5d752224..ea0e132ee6d 100644 --- a/ddtrace/contrib/molten/wrappers.py +++ b/ddtrace/contrib/molten/wrappers.py @@ -1,9 +1,9 @@ import molten +import wrapt from ddtrace import config from ddtrace.constants import SPAN_KIND from ddtrace.internal.constants import COMPONENT -from ddtrace.vendor import wrapt from .. import trace_utils from ... import Pin diff --git a/ddtrace/contrib/mongoengine/trace.py b/ddtrace/contrib/mongoengine/trace.py index 17add796b9c..bc5ea7ffefb 100644 --- a/ddtrace/contrib/mongoengine/trace.py +++ b/ddtrace/contrib/mongoengine/trace.py @@ -1,10 +1,11 @@ # 3p # project +import wrapt + import ddtrace from ddtrace.contrib.pymongo.client import TracedMongoClient from ddtrace.ext import mongo as mongox from ddtrace.internal.schema import schematize_service_name -from ddtrace.vendor import wrapt # TODO(Benjamin): we should instrument register_connection instead, because more generic diff --git a/ddtrace/contrib/mysql/patch.py b/ddtrace/contrib/mysql/patch.py index 911bea92528..1e50d464baa 100644 --- a/ddtrace/contrib/mysql/patch.py +++ b/ddtrace/contrib/mysql/patch.py @@ -1,11 +1,11 @@ import os import mysql.connector +import wrapt from ddtrace import Pin from ddtrace import config from ddtrace.contrib.dbapi import TracedConnection -from ddtrace.vendor import wrapt from ...ext import db from ...ext import net diff --git a/ddtrace/contrib/mysqldb/patch.py b/ddtrace/contrib/mysqldb/patch.py index 878280d16a0..cb94e588316 100644 --- a/ddtrace/contrib/mysqldb/patch.py +++ b/ddtrace/contrib/mysqldb/patch.py @@ -1,6 +1,7 @@ import os import MySQLdb +from wrapt import wrap_function_wrapper as _w from ddtrace import Pin from ddtrace import config @@ -10,7 +11,6 @@ from ddtrace.contrib.trace_utils import ext_service from ddtrace.internal.constants import COMPONENT from ddtrace.internal.schema import schematize_database_operation -from ddtrace.vendor.wrapt import wrap_function_wrapper as _w from ...ext import SpanKind from ...ext import SpanTypes diff --git a/ddtrace/contrib/psycopg/extensions.py b/ddtrace/contrib/psycopg/extensions.py index 094cb8e8a9b..df9955b4d0d 100644 --- a/ddtrace/contrib/psycopg/extensions.py +++ b/ddtrace/contrib/psycopg/extensions.py @@ -3,10 +3,11 @@ """ import functools +import wrapt + from ddtrace import config from ddtrace.internal.constants import COMPONENT from ddtrace.internal.schema import schematize_database_operation -from ddtrace.vendor import wrapt from ...constants import SPAN_KIND from ...constants import SPAN_MEASURED_KEY diff --git a/ddtrace/contrib/psycopg/patch.py b/ddtrace/contrib/psycopg/patch.py index b7877ac5148..0ced7aa7503 100644 --- a/ddtrace/contrib/psycopg/patch.py +++ b/ddtrace/contrib/psycopg/patch.py @@ -15,6 +15,8 @@ # catch async function syntax errors when using Python<3.7 with no async support except SyntaxError: pass +from wrapt import wrap_function_wrapper as _w + from ddtrace.contrib.psycopg.connection import patched_connect_factory from ddtrace.contrib.psycopg.cursor import Psycopg3FetchTracedCursor from ddtrace.contrib.psycopg.cursor import Psycopg3TracedCursor @@ -22,7 +24,6 @@ from ddtrace.contrib.psycopg.extensions import _unpatch_extensions from ddtrace.contrib.psycopg.extensions import get_psycopg2_extensions from ddtrace.propagation._database_monitoring import default_sql_injector as _default_sql_injector -from ddtrace.vendor.wrapt import wrap_function_wrapper as _w from ...internal.schema import schematize_database_operation from ...internal.schema import schematize_service_name diff --git a/ddtrace/contrib/pylibmc/client.py b/ddtrace/contrib/pylibmc/client.py index 832356b9c10..8966fd0639f 100644 --- a/ddtrace/contrib/pylibmc/client.py +++ b/ddtrace/contrib/pylibmc/client.py @@ -2,6 +2,7 @@ import random import pylibmc +from wrapt import ObjectProxy # project import ddtrace @@ -20,7 +21,6 @@ from ddtrace.internal.logger import get_logger from ddtrace.internal.schema import schematize_cache_operation from ddtrace.internal.schema import schematize_service_name -from ddtrace.vendor.wrapt import ObjectProxy # Original Client class diff --git a/ddtrace/contrib/pylons/patch.py b/ddtrace/contrib/pylons/patch.py index f1456c5a7ca..2a7838b45b1 100644 --- a/ddtrace/contrib/pylons/patch.py +++ b/ddtrace/contrib/pylons/patch.py @@ -2,11 +2,11 @@ import pylons import pylons.wsgiapp +import wrapt from ddtrace import Pin from ddtrace import config from ddtrace import tracer -from ddtrace.vendor import wrapt from ...internal.utils.formats import asbool from ...internal.utils.wrappers import unwrap as _u diff --git a/ddtrace/contrib/pylons/renderer.py b/ddtrace/contrib/pylons/renderer.py index 5658970664f..84b34564471 100644 --- a/ddtrace/contrib/pylons/renderer.py +++ b/ddtrace/contrib/pylons/renderer.py @@ -1,9 +1,9 @@ import pylons from pylons import config +from wrapt import wrap_function_wrapper as _w from ddtrace import config as ddconfig from ddtrace.internal.constants import COMPONENT -from ddtrace.vendor.wrapt import wrap_function_wrapper as _w from ...internal.utils import get_argument_value from .compat import legacy_pylons diff --git a/ddtrace/contrib/pymemcache/client.py b/ddtrace/contrib/pymemcache/client.py index bb8cdd4efdd..b8bedb0d14a 100644 --- a/ddtrace/contrib/pymemcache/client.py +++ b/ddtrace/contrib/pymemcache/client.py @@ -10,11 +10,11 @@ from pymemcache.exceptions import MemcacheServerError from pymemcache.exceptions import MemcacheUnknownCommandError from pymemcache.exceptions import MemcacheUnknownError +import wrapt # 3p from ddtrace import config from ddtrace.internal.constants import COMPONENT -from ddtrace.vendor import wrapt # project from ...constants import ANALYTICS_SAMPLE_RATE_KEY diff --git a/ddtrace/contrib/pymongo/client.py b/ddtrace/contrib/pymongo/client.py index 16ef93d50fd..9d72e7c6e89 100644 --- a/ddtrace/contrib/pymongo/client.py +++ b/ddtrace/contrib/pymongo/client.py @@ -5,12 +5,12 @@ # 3p import pymongo +from wrapt import ObjectProxy # project import ddtrace from ddtrace import config from ddtrace.internal.constants import COMPONENT -from ddtrace.vendor.wrapt import ObjectProxy from ...constants import ANALYTICS_SAMPLE_RATE_KEY from ...constants import SPAN_KIND diff --git a/ddtrace/contrib/pymongo/patch.py b/ddtrace/contrib/pymongo/patch.py index 13ee461689e..963a6428b8e 100644 --- a/ddtrace/contrib/pymongo/patch.py +++ b/ddtrace/contrib/pymongo/patch.py @@ -1,12 +1,12 @@ import contextlib import pymongo +from wrapt import wrap_function_wrapper as _w from ddtrace import Pin from ddtrace import config from ddtrace.contrib import trace_utils from ddtrace.internal.constants import COMPONENT -from ddtrace.vendor.wrapt import wrap_function_wrapper as _w from ...constants import SPAN_KIND from ...constants import SPAN_MEASURED_KEY diff --git a/ddtrace/contrib/pymysql/patch.py b/ddtrace/contrib/pymysql/patch.py index fe2fdcec843..b08bcfa3207 100644 --- a/ddtrace/contrib/pymysql/patch.py +++ b/ddtrace/contrib/pymysql/patch.py @@ -1,11 +1,11 @@ import os import pymysql +import wrapt from ddtrace import Pin from ddtrace import config from ddtrace.contrib.dbapi import TracedConnection -from ddtrace.vendor import wrapt from ...ext import db from ...ext import net diff --git a/ddtrace/contrib/pynamodb/patch.py b/ddtrace/contrib/pynamodb/patch.py index da8685e648f..e6d01eb9f5d 100644 --- a/ddtrace/contrib/pynamodb/patch.py +++ b/ddtrace/contrib/pynamodb/patch.py @@ -3,12 +3,12 @@ """ import pynamodb.connection.base +import wrapt from ddtrace import config from ddtrace.internal.constants import COMPONENT from ddtrace.internal.schema import schematize_cloud_api_operation from ddtrace.internal.schema import schematize_service_name -from ddtrace.vendor import wrapt from .. import trace_utils from ...constants import ANALYTICS_SAMPLE_RATE_KEY diff --git a/ddtrace/contrib/pyramid/patch.py b/ddtrace/contrib/pyramid/patch.py index 2a5f9421909..c7b48b24c98 100644 --- a/ddtrace/contrib/pyramid/patch.py +++ b/ddtrace/contrib/pyramid/patch.py @@ -2,9 +2,9 @@ import pyramid import pyramid.config +import wrapt from ddtrace import config -from ddtrace.vendor import wrapt from ...internal.utils.formats import asbool from .constants import SETTINGS_ANALYTICS_ENABLED diff --git a/ddtrace/contrib/pyramid/trace.py b/ddtrace/contrib/pyramid/trace.py index 40697251289..e7452dc4c97 100644 --- a/ddtrace/contrib/pyramid/trace.py +++ b/ddtrace/contrib/pyramid/trace.py @@ -1,13 +1,13 @@ from pyramid.httpexceptions import HTTPException import pyramid.renderers from pyramid.settings import asbool +import wrapt # project import ddtrace from ddtrace import config from ddtrace.internal.constants import COMPONENT from ddtrace.internal.schema.span_attribute_schema import SpanDirection -from ddtrace.vendor import wrapt from .. import trace_utils from ...constants import ANALYTICS_SAMPLE_RATE_KEY diff --git a/ddtrace/contrib/redis/patch.py b/ddtrace/contrib/redis/patch.py index b1d9fafcf9a..a162c9973ca 100644 --- a/ddtrace/contrib/redis/patch.py +++ b/ddtrace/contrib/redis/patch.py @@ -2,9 +2,9 @@ import redis from six import PY3 +import wrapt from ddtrace import config -from ddtrace.vendor import wrapt from ...internal.schema import schematize_service_name from ...internal.utils.formats import CMD_MAX_LEN diff --git a/ddtrace/contrib/rediscluster/patch.py b/ddtrace/contrib/rediscluster/patch.py index 5b5c624c43c..6c67f192654 100644 --- a/ddtrace/contrib/rediscluster/patch.py +++ b/ddtrace/contrib/rediscluster/patch.py @@ -2,6 +2,7 @@ # 3p import rediscluster +import wrapt # project from ddtrace import config @@ -21,7 +22,6 @@ from ddtrace.internal.utils.formats import stringify_cache_args from ddtrace.internal.utils.wrappers import unwrap from ddtrace.pin import Pin -from ddtrace.vendor import wrapt from .. import trace_utils diff --git a/ddtrace/contrib/requests/patch.py b/ddtrace/contrib/requests/patch.py index 100ddefe4e1..786c530673d 100644 --- a/ddtrace/contrib/requests/patch.py +++ b/ddtrace/contrib/requests/patch.py @@ -1,9 +1,9 @@ import os import requests +from wrapt import wrap_function_wrapper as _w from ddtrace import config -from ddtrace.vendor.wrapt import wrap_function_wrapper as _w from ...internal.schema import schematize_service_name from ...internal.utils.formats import asbool diff --git a/ddtrace/contrib/requests/session.py b/ddtrace/contrib/requests/session.py index 1e603fb39e5..9551c70226c 100644 --- a/ddtrace/contrib/requests/session.py +++ b/ddtrace/contrib/requests/session.py @@ -1,8 +1,8 @@ import requests +from wrapt import wrap_function_wrapper as _w from ddtrace import Pin from ddtrace import config -from ddtrace.vendor.wrapt import wrap_function_wrapper as _w from .connection import _wrap_send diff --git a/ddtrace/contrib/sanic/patch.py b/ddtrace/contrib/sanic/patch.py index 80dcb473cd3..f324ae787ae 100644 --- a/ddtrace/contrib/sanic/patch.py +++ b/ddtrace/contrib/sanic/patch.py @@ -1,6 +1,8 @@ import asyncio import sanic +import wrapt +from wrapt import wrap_function_wrapper as _w import ddtrace from ddtrace import config @@ -14,8 +16,6 @@ from ddtrace.internal.schema.span_attribute_schema import SpanDirection from ddtrace.internal.utils.wrappers import unwrap as _u from ddtrace.pin import Pin -from ddtrace.vendor import wrapt -from ddtrace.vendor.wrapt import wrap_function_wrapper as _w from .. import trace_utils from ...internal.logger import get_logger diff --git a/ddtrace/contrib/snowflake/patch.py b/ddtrace/contrib/snowflake/patch.py index 607854f3a0d..24b1581c0b6 100644 --- a/ddtrace/contrib/snowflake/patch.py +++ b/ddtrace/contrib/snowflake/patch.py @@ -1,8 +1,9 @@ import os +import wrapt + from ddtrace import Pin from ddtrace import config -from ddtrace.vendor import wrapt from ...ext import db from ...ext import net diff --git a/ddtrace/contrib/sqlalchemy/patch.py b/ddtrace/contrib/sqlalchemy/patch.py index edd1c43192c..c6162c19006 100644 --- a/ddtrace/contrib/sqlalchemy/patch.py +++ b/ddtrace/contrib/sqlalchemy/patch.py @@ -1,6 +1,5 @@ import sqlalchemy - -from ddtrace.vendor.wrapt import wrap_function_wrapper as _w +from wrapt import wrap_function_wrapper as _w from ..trace_utils import unwrap from .engine import _wrap_create_engine diff --git a/ddtrace/contrib/sqlite3/patch.py b/ddtrace/contrib/sqlite3/patch.py index b5e357b3a22..49ae92f519c 100644 --- a/ddtrace/contrib/sqlite3/patch.py +++ b/ddtrace/contrib/sqlite3/patch.py @@ -3,8 +3,9 @@ import sqlite3.dbapi2 import sys +import wrapt + from ddtrace import config -from ddtrace.vendor import wrapt from ...contrib.dbapi import FetchTracedCursor from ...contrib.dbapi import TracedConnection diff --git a/ddtrace/contrib/starlette/patch.py b/ddtrace/contrib/starlette/patch.py index 55c5cf74f2d..4d966c64345 100644 --- a/ddtrace/contrib/starlette/patch.py +++ b/ddtrace/contrib/starlette/patch.py @@ -5,6 +5,8 @@ import starlette from starlette.middleware import Middleware +from wrapt import ObjectProxy +from wrapt import wrap_function_wrapper as _w from ddtrace import config from ddtrace.contrib.asgi.middleware import TraceMiddleware @@ -14,8 +16,6 @@ from ddtrace.internal.utils import get_argument_value from ddtrace.internal.utils.wrappers import unwrap as _u from ddtrace.span import Span -from ddtrace.vendor.wrapt import ObjectProxy -from ddtrace.vendor.wrapt import wrap_function_wrapper as _w log = get_logger(__name__) diff --git a/ddtrace/contrib/tornado/patch.py b/ddtrace/contrib/tornado/patch.py index f0de14770ac..c131c7d11b2 100644 --- a/ddtrace/contrib/tornado/patch.py +++ b/ddtrace/contrib/tornado/patch.py @@ -1,10 +1,10 @@ import os import tornado +from wrapt import wrap_function_wrapper as _w import ddtrace from ddtrace import config -from ddtrace.vendor.wrapt import wrap_function_wrapper as _w from . import application from . import context_provider diff --git a/ddtrace/contrib/trace_utils.py b/ddtrace/contrib/trace_utils.py index 8bfeb22fd53..b49ba72a5cf 100644 --- a/ddtrace/contrib/trace_utils.py +++ b/ddtrace/contrib/trace_utils.py @@ -17,6 +17,8 @@ from typing import Union from typing import cast +import wrapt + from ddtrace import Pin from ddtrace import config from ddtrace.ext import SpanTypes @@ -34,7 +36,6 @@ from ddtrace.internal.utils.http import strip_query_string import ddtrace.internal.utils.wrappers from ddtrace.propagation.http import HTTPPropagator -from ddtrace.vendor import wrapt if TYPE_CHECKING: # pragma: no cover diff --git a/ddtrace/contrib/unittest/patch.py b/ddtrace/contrib/unittest/patch.py index 83fbb7f93bf..6d3cc3af4c6 100644 --- a/ddtrace/contrib/unittest/patch.py +++ b/ddtrace/contrib/unittest/patch.py @@ -2,6 +2,8 @@ import os import unittest +import wrapt + import ddtrace from ddtrace import config from ddtrace.constants import SPAN_KIND @@ -14,7 +16,6 @@ from ddtrace.internal.ci_visibility.constants import EVENT_TYPE as _EVENT_TYPE from ddtrace.internal.constants import COMPONENT from ddtrace.internal.utils.wrappers import unwrap as _u -from ddtrace.vendor import wrapt # unittest default settings diff --git a/ddtrace/contrib/urllib3/patch.py b/ddtrace/contrib/urllib3/patch.py index f3fd37ceaeb..cd3fb7f4a70 100644 --- a/ddtrace/contrib/urllib3/patch.py +++ b/ddtrace/contrib/urllib3/patch.py @@ -1,12 +1,12 @@ import os import urllib3 +from wrapt import wrap_function_wrapper as _w from ddtrace import config from ddtrace.internal.constants import COMPONENT from ddtrace.internal.schema.span_attribute_schema import SpanDirection from ddtrace.pin import Pin -from ddtrace.vendor.wrapt import wrap_function_wrapper as _w from .. import trace_utils from ...constants import ANALYTICS_SAMPLE_RATE_KEY diff --git a/ddtrace/contrib/vertica/patch.py b/ddtrace/contrib/vertica/patch.py index ecbc88161fd..0e5147b10bd 100644 --- a/ddtrace/contrib/vertica/patch.py +++ b/ddtrace/contrib/vertica/patch.py @@ -1,9 +1,10 @@ import importlib +import wrapt + import ddtrace from ddtrace import config from ddtrace.internal.constants import COMPONENT -from ddtrace.vendor import wrapt from .. import trace_utils from ...constants import ANALYTICS_SAMPLE_RATE_KEY diff --git a/ddtrace/contrib/wsgi/wsgi.py b/ddtrace/contrib/wsgi/wsgi.py index 86315d594ff..6e529e4a7db 100644 --- a/ddtrace/contrib/wsgi/wsgi.py +++ b/ddtrace/contrib/wsgi/wsgi.py @@ -17,6 +17,7 @@ from ddtrace.settings import Config from six.moves.urllib.parse import quote +import wrapt import ddtrace from ddtrace import config @@ -26,7 +27,6 @@ from ddtrace.propagation._utils import from_wsgi_header from ddtrace.propagation.http import HTTPPropagator from ddtrace.tracing import trace_handlers -from ddtrace.vendor import wrapt from ...internal import core diff --git a/ddtrace/contrib/yaaredis/patch.py b/ddtrace/contrib/yaaredis/patch.py index daa54169bbf..09d5193ed64 100644 --- a/ddtrace/contrib/yaaredis/patch.py +++ b/ddtrace/contrib/yaaredis/patch.py @@ -1,9 +1,9 @@ import os +import wrapt import yaaredis from ddtrace import config -from ddtrace.vendor import wrapt from ...internal.schema import schematize_service_name from ...internal.utils.formats import CMD_MAX_LEN diff --git a/ddtrace/debugging/_function/discovery.py b/ddtrace/debugging/_function/discovery.py index e72cd14f799..7196a68976b 100644 --- a/ddtrace/debugging/_function/discovery.py +++ b/ddtrace/debugging/_function/discovery.py @@ -2,8 +2,7 @@ from collections import deque from six import PY2 - -from ddtrace.vendor.wrapt.wrappers import FunctionWrapper +from wrapt.wrappers import FunctionWrapper try: diff --git a/ddtrace/internal/compat.py b/ddtrace/internal/compat.py index 6feae9534df..b2e3d0dec66 100644 --- a/ddtrace/internal/compat.py +++ b/ddtrace/internal/compat.py @@ -23,9 +23,8 @@ import warnings import six - -from ddtrace.vendor.wrapt.wrappers import BoundFunctionWrapper -from ddtrace.vendor.wrapt.wrappers import FunctionWrapper +from wrapt.wrappers import BoundFunctionWrapper +from wrapt.wrappers import FunctionWrapper __all__ = [ diff --git a/ddtrace/internal/forksafe.py b/ddtrace/internal/forksafe.py index 8f1a2846088..12abee3be2d 100644 --- a/ddtrace/internal/forksafe.py +++ b/ddtrace/internal/forksafe.py @@ -7,7 +7,7 @@ import typing import weakref -from ddtrace.vendor import wrapt +import wrapt log = logging.getLogger(__name__) diff --git a/ddtrace/internal/runtime/metric_collectors.py b/ddtrace/internal/runtime/metric_collectors.py index a250a8e21f9..8dc4e597543 100644 --- a/ddtrace/internal/runtime/metric_collectors.py +++ b/ddtrace/internal/runtime/metric_collectors.py @@ -49,7 +49,7 @@ class PSUtilRuntimeMetricCollector(RuntimeMetricCollector): for more information. """ - required_modules = ["ddtrace.vendor.psutil"] + required_modules = ["psutil"] delta_funs = { CPU_TIME_SYS: lambda p: p.cpu_times().system, CPU_TIME_USER: lambda p: p.cpu_times().user, @@ -63,7 +63,7 @@ class PSUtilRuntimeMetricCollector(RuntimeMetricCollector): } def _on_modules_load(self): - self.proc = self.modules["ddtrace.vendor.psutil"].Process(os.getpid()) + self.proc = self.modules["psutil"].Process(os.getpid()) self.stored_values = {key: 0 for key in self.delta_funs.keys()} def collect_fn(self, keys): diff --git a/ddtrace/internal/safety.py b/ddtrace/internal/safety.py index 1766c51656b..339bdc4f012 100644 --- a/ddtrace/internal/safety.py +++ b/ddtrace/internal/safety.py @@ -7,11 +7,12 @@ from typing import Type from typing import Union +import wrapt + from ddtrace.internal.compat import BUILTIN from ddtrace.internal.compat import PY3 from ddtrace.internal.utils.attrdict import AttrDict from ddtrace.internal.utils.cache import cached -from ddtrace.vendor import wrapt NoneType = type(None) diff --git a/ddtrace/internal/utils/wrappers.py b/ddtrace/internal/utils/wrappers.py index 146329ff596..fa7c51adadd 100644 --- a/ddtrace/internal/utils/wrappers.py +++ b/ddtrace/internal/utils/wrappers.py @@ -3,7 +3,7 @@ from typing import Optional from typing import TypeVar -from ddtrace.vendor import wrapt +import wrapt F = TypeVar("F", bound=Callable[..., Any]) diff --git a/ddtrace/pin.py b/ddtrace/pin.py index 3147af38f13..ce4b1065b25 100644 --- a/ddtrace/pin.py +++ b/ddtrace/pin.py @@ -3,10 +3,11 @@ from typing import Optional from typing import TYPE_CHECKING +import wrapt + import ddtrace from .internal.logger import get_logger -from .vendor import wrapt if TYPE_CHECKING: # pragma: no cover diff --git a/ddtrace/profiling/collector/_lock.py b/ddtrace/profiling/collector/_lock.py index a008ed2af78..0620800fc72 100644 --- a/ddtrace/profiling/collector/_lock.py +++ b/ddtrace/profiling/collector/_lock.py @@ -7,6 +7,7 @@ import attr from six.moves import _thread +import wrapt from ddtrace.internal import compat from ddtrace.profiling import _threading @@ -15,7 +16,6 @@ from ddtrace.profiling.collector import _task from ddtrace.profiling.collector import _traceback from ddtrace.settings.profiling import config -from ddtrace.vendor import wrapt @event.event_class @@ -52,7 +52,7 @@ def _current_thread(): WRAPT_C_EXT = False else: try: - import ddtrace.vendor.wrapt._wrappers as _w # noqa: F401 + import wrapt._wrappers as _w # noqa: F401 except ImportError: WRAPT_C_EXT = False else: diff --git a/ddtrace/profiling/collector/_task.pyx b/ddtrace/profiling/collector/_task.pyx index 8aaa24f2c1a..d5d50b2b247 100644 --- a/ddtrace/profiling/collector/_task.pyx +++ b/ddtrace/profiling/collector/_task.pyx @@ -2,7 +2,7 @@ import sys from types import ModuleType import weakref -from ddtrace.vendor.wrapt.importer import when_imported +from wrapt.importer import when_imported from .. import _asyncio from .. import _threading diff --git a/ddtrace/settings/profiling.py b/ddtrace/settings/profiling.py index b6c8819ebc8..facf3f9d8a2 100644 --- a/ddtrace/settings/profiling.py +++ b/ddtrace/settings/profiling.py @@ -21,7 +21,7 @@ def _derive_default_heap_sample_size(heap_config, default_heap_sample_size=1024 return 0 try: - from ddtrace.vendor import psutil + import psutil total_mem = psutil.swap_memory().total + psutil.virtual_memory().total except Exception: diff --git a/ddtrace/sourcecode/setuptools_auto.py b/ddtrace/sourcecode/setuptools_auto.py index 9289c4b6b03..a47ed5d1d0c 100644 --- a/ddtrace/sourcecode/setuptools_auto.py +++ b/ddtrace/sourcecode/setuptools_auto.py @@ -1,4 +1,4 @@ -from ddtrace.vendor.wrapt import wrap_function_wrapper as _w +from wrapt import wrap_function_wrapper as _w try: diff --git a/ddtrace/tracing/trace_handlers.py b/ddtrace/tracing/trace_handlers.py index 9e07d85f3dd..81a6baf7f43 100644 --- a/ddtrace/tracing/trace_handlers.py +++ b/ddtrace/tracing/trace_handlers.py @@ -1,6 +1,8 @@ import functools import sys +import wrapt + from ddtrace.constants import ANALYTICS_SAMPLE_RATE_KEY from ddtrace.constants import SPAN_KIND from ddtrace.constants import SPAN_MEASURED_KEY @@ -21,7 +23,6 @@ from ddtrace.internal.constants import RESPONSE_HEADERS from ddtrace.internal.logger import get_logger from ddtrace.internal.utils import http as http_utils -from ddtrace.vendor import wrapt log = get_logger(__name__) diff --git a/ddtrace/vendor/__init__.py b/ddtrace/vendor/__init__.py index 1150cf0aa3b..58cf2013714 100644 --- a/ddtrace/vendor/__init__.py +++ b/ddtrace/vendor/__init__.py @@ -8,17 +8,6 @@ Dependencies ============ -wrapt ------ - -Website: https://wrapt.readthedocs.io/en/latest/ -Source: https://github.com/GrahamDumpleton/wrapt/ -Version: 1.14.1 -License: BSD 2-Clause "Simplified" License - -Notes: - `setup.py` will attempt to build the `wrapt/_wrappers.c` C module - dogstatsd --------- @@ -63,15 +52,6 @@ Removed dependency on `pbr` and manually set `__version__` -psutil ------- - -Website: https://github.com/giampaolo/psutil -Source: https://github.com/giampaolo/psutil -Version: 5.6.7 -License: BSD 3 - - contextvars ------------- diff --git a/ddtrace/vendor/debtcollector/moves.py b/ddtrace/vendor/debtcollector/moves.py index 8fac7543ff6..d3c7f18ac5c 100644 --- a/ddtrace/vendor/debtcollector/moves.py +++ b/ddtrace/vendor/debtcollector/moves.py @@ -17,7 +17,7 @@ import inspect import six -from .. import wrapt +import wrapt from . import _utils diff --git a/ddtrace/vendor/debtcollector/removals.py b/ddtrace/vendor/debtcollector/removals.py index ea2b4903005..bfd357e1973 100644 --- a/ddtrace/vendor/debtcollector/removals.py +++ b/ddtrace/vendor/debtcollector/removals.py @@ -16,7 +16,7 @@ import inspect import six -from .. import wrapt +import wrapt from . import _utils diff --git a/ddtrace/vendor/debtcollector/renames.py b/ddtrace/vendor/debtcollector/renames.py index d31853aa6fe..df66e843066 100644 --- a/ddtrace/vendor/debtcollector/renames.py +++ b/ddtrace/vendor/debtcollector/renames.py @@ -14,7 +14,7 @@ # License for the specific language governing permissions and limitations # under the License. -from .. import wrapt +import wrapt from . import _utils diff --git a/ddtrace/vendor/debtcollector/updating.py b/ddtrace/vendor/debtcollector/updating.py index 67e5f847492..aab252298d1 100644 --- a/ddtrace/vendor/debtcollector/updating.py +++ b/ddtrace/vendor/debtcollector/updating.py @@ -15,7 +15,7 @@ # under the License. import six -from .. import wrapt +import wrapt if six.PY3: import inspect Parameter = inspect.Parameter diff --git a/ddtrace/vendor/psutil/__init__.py b/ddtrace/vendor/psutil/__init__.py deleted file mode 100644 index b267239e285..00000000000 --- a/ddtrace/vendor/psutil/__init__.py +++ /dev/null @@ -1,2516 +0,0 @@ -# -*- coding: utf-8 -*- - -# 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. - -"""psutil is a cross-platform library for retrieving information on -running processes and system utilization (CPU, memory, disks, network, -sensors) in Python. Supported platforms: - - - Linux - - Windows - - macOS - - FreeBSD - - OpenBSD - - NetBSD - - Sun Solaris - - AIX - -Works with Python versions from 2.6 to 3.4+. -""" - -from __future__ import division - -import collections -import contextlib -import datetime -import functools -import os -import signal -import subprocess -import sys -import threading -import time -try: - import pwd -except ImportError: - pwd = None - -from . import _common -from ._common import deprecated_method -from ._common import memoize -from ._common import memoize_when_activated -from ._common import wrap_numbers as _wrap_numbers -from ._compat import long -from ._compat import PermissionError -from ._compat import ProcessLookupError -from ._compat import PY3 as _PY3 - -from ._common import STATUS_DEAD -from ._common import STATUS_DISK_SLEEP -from ._common import STATUS_IDLE -from ._common import STATUS_LOCKED -from ._common import STATUS_PARKED -from ._common import STATUS_RUNNING -from ._common import STATUS_SLEEPING -from ._common import STATUS_STOPPED -from ._common import STATUS_TRACING_STOP -from ._common import STATUS_WAITING -from ._common import STATUS_WAKING -from ._common import STATUS_ZOMBIE - -from ._common import CONN_CLOSE -from ._common import CONN_CLOSE_WAIT -from ._common import CONN_CLOSING -from ._common import CONN_ESTABLISHED -from ._common import CONN_FIN_WAIT1 -from ._common import CONN_FIN_WAIT2 -from ._common import CONN_LAST_ACK -from ._common import CONN_LISTEN -from ._common import CONN_NONE -from ._common import CONN_SYN_RECV -from ._common import CONN_SYN_SENT -from ._common import CONN_TIME_WAIT -from ._common import NIC_DUPLEX_FULL -from ._common import NIC_DUPLEX_HALF -from ._common import NIC_DUPLEX_UNKNOWN - -from ._common import AIX -from ._common import BSD -from ._common import FREEBSD # NOQA -from ._common import LINUX -from ._common import MACOS -from ._common import NETBSD # NOQA -from ._common import OPENBSD # NOQA -from ._common import OSX # deprecated alias -from ._common import POSIX # NOQA -from ._common import SUNOS -from ._common import WINDOWS - -if LINUX: - # This is public API and it will be retrieved from _pslinux.py - # via sys.modules. - PROCFS_PATH = "/proc" - - from . import _pslinux as _psplatform - - from ._pslinux import IOPRIO_CLASS_BE # NOQA - from ._pslinux import IOPRIO_CLASS_IDLE # NOQA - from ._pslinux import IOPRIO_CLASS_NONE # NOQA - from ._pslinux import IOPRIO_CLASS_RT # NOQA - # Linux >= 2.6.36 - if _psplatform.HAS_PRLIMIT: - from ._psutil_linux import RLIM_INFINITY # NOQA - from ._psutil_linux import RLIMIT_AS # NOQA - from ._psutil_linux import RLIMIT_CORE # NOQA - from ._psutil_linux import RLIMIT_CPU # NOQA - from ._psutil_linux import RLIMIT_DATA # NOQA - from ._psutil_linux import RLIMIT_FSIZE # NOQA - from ._psutil_linux import RLIMIT_LOCKS # NOQA - from ._psutil_linux import RLIMIT_MEMLOCK # NOQA - from ._psutil_linux import RLIMIT_NOFILE # NOQA - from ._psutil_linux import RLIMIT_NPROC # NOQA - from ._psutil_linux import RLIMIT_RSS # NOQA - from ._psutil_linux import RLIMIT_STACK # NOQA - # Kinda ugly but considerably faster than using hasattr() and - # setattr() against the module object (we are at import time: - # speed matters). - from . import _psutil_linux - try: - RLIMIT_MSGQUEUE = _psutil_linux.RLIMIT_MSGQUEUE - except AttributeError: - pass - try: - RLIMIT_NICE = _psutil_linux.RLIMIT_NICE - except AttributeError: - pass - try: - RLIMIT_RTPRIO = _psutil_linux.RLIMIT_RTPRIO - except AttributeError: - pass - try: - RLIMIT_RTTIME = _psutil_linux.RLIMIT_RTTIME - except AttributeError: - pass - try: - RLIMIT_SIGPENDING = _psutil_linux.RLIMIT_SIGPENDING - except AttributeError: - pass - -elif WINDOWS: - from . import _pswindows as _psplatform - from ._psutil_windows import ABOVE_NORMAL_PRIORITY_CLASS # NOQA - from ._psutil_windows import BELOW_NORMAL_PRIORITY_CLASS # NOQA - from ._psutil_windows import HIGH_PRIORITY_CLASS # NOQA - from ._psutil_windows import IDLE_PRIORITY_CLASS # NOQA - from ._psutil_windows import NORMAL_PRIORITY_CLASS # NOQA - from ._psutil_windows import REALTIME_PRIORITY_CLASS # NOQA - from ._pswindows import CONN_DELETE_TCB # NOQA - from ._pswindows import IOPRIO_VERYLOW # NOQA - from ._pswindows import IOPRIO_LOW # NOQA - from ._pswindows import IOPRIO_NORMAL # NOQA - from ._pswindows import IOPRIO_HIGH # NOQA - -elif MACOS: - from . import _psosx as _psplatform - -elif BSD: - from . import _psbsd as _psplatform - -elif SUNOS: - from . import _pssunos as _psplatform - from ._pssunos import CONN_BOUND # NOQA - from ._pssunos import CONN_IDLE # NOQA - - # This is public writable API which is read from _pslinux.py and - # _pssunos.py via sys.modules. - PROCFS_PATH = "/proc" - -elif AIX: - from . import _psaix as _psplatform - - # This is public API and it will be retrieved from _pslinux.py - # via sys.modules. - PROCFS_PATH = "/proc" - -else: # pragma: no cover - raise NotImplementedError('platform %s is not supported' % sys.platform) - - -__all__ = [ - # exceptions - "Error", "NoSuchProcess", "ZombieProcess", "AccessDenied", - "TimeoutExpired", - - # constants - "version_info", "__version__", - - "STATUS_RUNNING", "STATUS_IDLE", "STATUS_SLEEPING", "STATUS_DISK_SLEEP", - "STATUS_STOPPED", "STATUS_TRACING_STOP", "STATUS_ZOMBIE", "STATUS_DEAD", - "STATUS_WAKING", "STATUS_LOCKED", "STATUS_WAITING", "STATUS_LOCKED", - "STATUS_PARKED", - - "CONN_ESTABLISHED", "CONN_SYN_SENT", "CONN_SYN_RECV", "CONN_FIN_WAIT1", - "CONN_FIN_WAIT2", "CONN_TIME_WAIT", "CONN_CLOSE", "CONN_CLOSE_WAIT", - "CONN_LAST_ACK", "CONN_LISTEN", "CONN_CLOSING", "CONN_NONE", - - "AF_LINK", - - "NIC_DUPLEX_FULL", "NIC_DUPLEX_HALF", "NIC_DUPLEX_UNKNOWN", - - "POWER_TIME_UNKNOWN", "POWER_TIME_UNLIMITED", - - "BSD", "FREEBSD", "LINUX", "NETBSD", "OPENBSD", "MACOS", "OSX", "POSIX", - "SUNOS", "WINDOWS", "AIX", - - # classes - "Process", "Popen", - - # functions - "pid_exists", "pids", "process_iter", "wait_procs", # proc - "virtual_memory", "swap_memory", # memory - "cpu_times", "cpu_percent", "cpu_times_percent", "cpu_count", # cpu - "cpu_stats", # "cpu_freq", "getloadavg" - "net_io_counters", "net_connections", "net_if_addrs", # network - "net_if_stats", - "disk_io_counters", "disk_partitions", "disk_usage", # disk - # "sensors_temperatures", "sensors_battery", "sensors_fans" # sensors - "users", "boot_time", # others -] - - -__all__.extend(_psplatform.__extra__all__) -__author__ = "Giampaolo Rodola'" -__version__ = "5.6.7" -version_info = tuple([int(num) for num in __version__.split('.')]) - -_timer = getattr(time, 'monotonic', time.time) -AF_LINK = _psplatform.AF_LINK -POWER_TIME_UNLIMITED = _common.POWER_TIME_UNLIMITED -POWER_TIME_UNKNOWN = _common.POWER_TIME_UNKNOWN -_TOTAL_PHYMEM = None -_LOWEST_PID = None - -# Sanity check in case the user messed up with psutil installation -# or did something weird with sys.path. In this case we might end -# up importing a python module using a C extension module which -# was compiled for a different version of psutil. -# We want to prevent that by failing sooner rather than later. -# See: https://github.com/giampaolo/psutil/issues/564 -if (int(__version__.replace('.', '')) != - getattr(_psplatform.cext, 'version', None)): - msg = "version conflict: %r C extension module was built for another " \ - "version of psutil" % getattr(_psplatform.cext, "__file__") - if hasattr(_psplatform.cext, 'version'): - msg += " (%s instead of %s)" % ( - '.'.join([x for x in str(_psplatform.cext.version)]), __version__) - else: - msg += " (different than %s)" % __version__ - msg += "; you may try to 'pip uninstall psutil', manually remove %s" % ( - getattr(_psplatform.cext, "__file__", - "the existing psutil install directory")) - msg += " or clean the virtual env somehow, then reinstall" - raise ImportError(msg) - - -# ===================================================================== -# --- Exceptions -# ===================================================================== - - -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 macOS, 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 - - -# Push exception classes into platform specific module namespace. -_psplatform.NoSuchProcess = NoSuchProcess -_psplatform.ZombieProcess = ZombieProcess -_psplatform.AccessDenied = AccessDenied -_psplatform.TimeoutExpired = TimeoutExpired -if POSIX: - from . import _psposix - _psposix.TimeoutExpired = TimeoutExpired - - -# ===================================================================== -# --- Utils -# ===================================================================== - - -if hasattr(_psplatform, 'ppid_map'): - # Faster version (Windows and Linux). - _ppid_map = _psplatform.ppid_map -else: - def _ppid_map(): - """Return a {pid: ppid, ...} dict for all running processes in - one shot. Used to speed up Process.children(). - """ - ret = {} - for pid in pids(): - try: - ret[pid] = _psplatform.Process(pid).ppid() - except (NoSuchProcess, ZombieProcess): - pass - return ret - - -def _assert_pid_not_reused(fun): - """Decorator which raises NoSuchProcess in case a process is no - longer running or its PID has been reused. - """ - @functools.wraps(fun) - def wrapper(self, *args, **kwargs): - if not self.is_running(): - raise NoSuchProcess(self.pid, self._name) - return fun(self, *args, **kwargs) - return wrapper - - -def _pprint_secs(secs): - """Format seconds in a human readable form.""" - now = time.time() - secs_ago = int(now - secs) - if secs_ago < 60 * 60 * 24: - fmt = "%H:%M:%S" - else: - fmt = "%Y-%m-%d %H:%M:%S" - return datetime.datetime.fromtimestamp(secs).strftime(fmt) - - -# ===================================================================== -# --- Process class -# ===================================================================== - - -class Process(object): - """Represents an OS process with the given PID. - If PID is omitted current process PID (os.getpid()) is used. - Raise NoSuchProcess if PID does not exist. - - Note that most of the methods of this class do not make sure - the PID of the process being queried has been reused over time. - That means you might end up retrieving an information referring - to another process in case the original one this instance - refers to is gone in the meantime. - - The only exceptions for which process identity is pre-emptively - checked and guaranteed are: - - - parent() - - children() - - nice() (set) - - ionice() (set) - - rlimit() (set) - - cpu_affinity (set) - - suspend() - - resume() - - send_signal() - - terminate() - - kill() - - To prevent this problem for all other methods you can: - - use is_running() before querying the process - - if you're continuously iterating over a set of Process - instances use process_iter() which pre-emptively checks - process identity for every yielded instance - """ - - def __init__(self, pid=None): - self._init(pid) - - def _init(self, pid, _ignore_nsp=False): - if pid is None: - pid = os.getpid() - else: - if not _PY3 and not isinstance(pid, (int, long)): - raise TypeError('pid must be an integer (got %r)' % pid) - if pid < 0: - raise ValueError('pid must be a positive integer (got %s)' - % pid) - self._pid = pid - self._name = None - self._exe = None - self._create_time = None - self._gone = False - self._hash = None - self._lock = threading.RLock() - # used for caching on Windows only (on POSIX ppid may change) - self._ppid = None - # platform-specific modules define an _psplatform.Process - # implementation class - self._proc = _psplatform.Process(pid) - self._last_sys_cpu_times = None - self._last_proc_cpu_times = None - # cache creation time for later use in is_running() method - try: - self.create_time() - except AccessDenied: - # We should never get here as AFAIK we're able to get - # process creation time on all platforms even as a - # limited user. - pass - except ZombieProcess: - # Zombies can still be queried by this class (although - # not always) and pids() return them so just go on. - pass - except NoSuchProcess: - if not _ignore_nsp: - msg = 'no process found with pid %s' % pid - raise NoSuchProcess(pid, None, msg) - else: - self._gone = True - # This pair is supposed to indentify a Process instance - # univocally over time (the PID alone is not enough as - # it might refer to a process whose PID has been reused). - # This will be used later in __eq__() and is_running(). - self._ident = (self.pid, self._create_time) - - def __str__(self): - try: - info = collections.OrderedDict() - except AttributeError: - info = {} # Python 2.6 - info["pid"] = self.pid - try: - info["name"] = self.name() - if self._create_time: - info['started'] = _pprint_secs(self._create_time) - except ZombieProcess: - info["status"] = "zombie" - except NoSuchProcess: - info["status"] = "terminated" - except AccessDenied: - pass - return "%s.%s(%s)" % ( - self.__class__.__module__, - self.__class__.__name__, - ", ".join(["%s=%r" % (k, v) for k, v in info.items()])) - - __repr__ = __str__ - - def __eq__(self, other): - # Test for equality with another Process object based - # on PID and creation time. - if not isinstance(other, Process): - return NotImplemented - return self._ident == other._ident - - def __ne__(self, other): - return not self == other - - def __hash__(self): - if self._hash is None: - self._hash = hash(self._ident) - return self._hash - - @property - def pid(self): - """The process PID.""" - return self._pid - - # --- utility methods - - @contextlib.contextmanager - def oneshot(self): - """Utility context manager which considerably speeds up the - retrieval of multiple process information at the same time. - - Internally different process info (e.g. name, ppid, uids, - gids, ...) may be fetched by using the same routine, but - only one information is returned and the others are discarded. - When using this context manager the internal routine is - executed once (in the example below on name()) and the - other info are cached. - - The cache is cleared when exiting the context manager block. - The advice is to use this every time you retrieve more than - one information about the process. If you're lucky, you'll - get a hell of a speedup. - - >>> import psutil - >>> p = psutil.Process() - >>> with p.oneshot(): - ... p.name() # collect multiple info - ... p.cpu_times() # return cached value - ... p.cpu_percent() # return cached value - ... p.create_time() # return cached value - ... - >>> - """ - with self._lock: - if hasattr(self, "_cache"): - # NOOP: this covers the use case where the user enters the - # context twice: - # - # >>> with p.oneshot(): - # ... with p.oneshot(): - # ... - # - # Also, since as_dict() internally uses oneshot() - # I expect that the code below will be a pretty common - # "mistake" that the user will make, so let's guard - # against that: - # - # >>> with p.oneshot(): - # ... p.as_dict() - # ... - yield - else: - try: - # cached in case cpu_percent() is used - self.cpu_times.cache_activate(self) - # cached in case memory_percent() is used - self.memory_info.cache_activate(self) - # cached in case parent() is used - self.ppid.cache_activate(self) - # cached in case username() is used - if POSIX: - self.uids.cache_activate(self) - # specific implementation cache - self._proc.oneshot_enter() - yield - finally: - self.cpu_times.cache_deactivate(self) - self.memory_info.cache_deactivate(self) - self.ppid.cache_deactivate(self) - if POSIX: - self.uids.cache_deactivate(self) - self._proc.oneshot_exit() - - def as_dict(self, attrs=None, ad_value=None): - """Utility method returning process information as a - hashable dictionary. - If *attrs* is specified it must be a list of strings - reflecting available Process class' attribute names - (e.g. ['cpu_times', 'name']) else all public (read - only) attributes are assumed. - *ad_value* is the value which gets assigned in case - AccessDenied or ZombieProcess exception is raised when - retrieving that particular process information. - """ - valid_names = _as_dict_attrnames - if attrs is not None: - if not isinstance(attrs, (list, tuple, set, frozenset)): - raise TypeError("invalid attrs type %s" % type(attrs)) - attrs = set(attrs) - invalid_names = attrs - valid_names - if invalid_names: - raise ValueError("invalid attr name%s %s" % ( - "s" if len(invalid_names) > 1 else "", - ", ".join(map(repr, invalid_names)))) - - retdict = dict() - ls = attrs or valid_names - with self.oneshot(): - for name in ls: - try: - if name == 'pid': - ret = self.pid - else: - meth = getattr(self, name) - ret = meth() - except (AccessDenied, ZombieProcess): - ret = ad_value - except NotImplementedError: - # in case of not implemented functionality (may happen - # on old or exotic systems) we want to crash only if - # the user explicitly asked for that particular attr - if attrs: - raise - continue - retdict[name] = ret - return retdict - - def parent(self): - """Return the parent process as a Process object pre-emptively - checking whether PID has been reused. - If no parent is known return None. - """ - lowest_pid = _LOWEST_PID if _LOWEST_PID is not None else pids()[0] - if self.pid == lowest_pid: - return None - ppid = self.ppid() - if ppid is not None: - ctime = self.create_time() - try: - parent = Process(ppid) - if parent.create_time() <= ctime: - return parent - # ...else ppid has been reused by another process - except NoSuchProcess: - pass - - def parents(self): - """Return the parents of this process as a list of Process - instances. If no parents are known return an empty list. - """ - parents = [] - proc = self.parent() - while proc is not None: - parents.append(proc) - proc = proc.parent() - return parents - - def is_running(self): - """Return whether this process is running. - It also checks if PID has been reused by another process in - which case return False. - """ - if self._gone: - return False - try: - # Checking if PID is alive is not enough as the PID might - # have been reused by another process: we also want to - # verify process identity. - # Process identity / uniqueness over time is guaranteed by - # (PID + creation time) and that is verified in __eq__. - return self == Process(self.pid) - except ZombieProcess: - # We should never get here as it's already handled in - # Process.__init__; here just for extra safety. - return True - except NoSuchProcess: - self._gone = True - return False - - # --- actual API - - @memoize_when_activated - def ppid(self): - """The process parent PID. - On Windows the return value is cached after first call. - """ - # On POSIX we don't want to cache the ppid as it may unexpectedly - # change to 1 (init) in case this process turns into a zombie: - # https://github.com/giampaolo/psutil/issues/321 - # http://stackoverflow.com/questions/356722/ - - # XXX should we check creation time here rather than in - # Process.parent()? - if POSIX: - return self._proc.ppid() - else: # pragma: no cover - self._ppid = self._ppid or self._proc.ppid() - return self._ppid - - def name(self): - """The process name. The return value is cached after first call.""" - # Process name is only cached on Windows as on POSIX it may - # change, see: - # https://github.com/giampaolo/psutil/issues/692 - if WINDOWS and self._name is not None: - return self._name - name = self._proc.name() - if POSIX and len(name) >= 15: - # On UNIX the name gets truncated to the first 15 characters. - # If it matches the first part of the cmdline we return that - # one instead because it's usually more explicative. - # Examples are "gnome-keyring-d" vs. "gnome-keyring-daemon". - try: - cmdline = self.cmdline() - except AccessDenied: - pass - else: - if cmdline: - extended_name = os.path.basename(cmdline[0]) - if extended_name.startswith(name): - name = extended_name - self._name = name - self._proc._name = name - return name - - def exe(self): - """The process executable as an absolute path. - May also be an empty string. - The return value is cached after first call. - """ - def guess_it(fallback): - # try to guess exe from cmdline[0] in absence of a native - # exe representation - cmdline = self.cmdline() - if cmdline and hasattr(os, 'access') and hasattr(os, 'X_OK'): - exe = cmdline[0] # the possible exe - # Attempt to guess only in case of an absolute path. - # It is not safe otherwise as the process might have - # changed cwd. - if (os.path.isabs(exe) and - os.path.isfile(exe) and - os.access(exe, os.X_OK)): - return exe - if isinstance(fallback, AccessDenied): - raise fallback - return fallback - - if self._exe is None: - try: - exe = self._proc.exe() - except AccessDenied as err: - return guess_it(fallback=err) - else: - if not exe: - # underlying implementation can legitimately return an - # empty string; if that's the case we don't want to - # raise AD while guessing from the cmdline - try: - exe = guess_it(fallback=exe) - except AccessDenied: - pass - self._exe = exe - return self._exe - - def cmdline(self): - """The command line this process has been called with.""" - return self._proc.cmdline() - - def status(self): - """The process current status as a STATUS_* constant.""" - try: - return self._proc.status() - except ZombieProcess: - return STATUS_ZOMBIE - - def username(self): - """The name of the user that owns the process. - On UNIX this is calculated by using *real* process uid. - """ - if POSIX: - if pwd is None: - # might happen if python was installed from sources - raise ImportError( - "requires pwd module shipped with standard python") - real_uid = self.uids().real - try: - return pwd.getpwuid(real_uid).pw_name - except KeyError: - # the uid can't be resolved by the system - return str(real_uid) - else: - return self._proc.username() - - def create_time(self): - """The process creation time as a floating point number - expressed in seconds since the epoch, in UTC. - The return value is cached after first call. - """ - if self._create_time is None: - self._create_time = self._proc.create_time() - return self._create_time - - def cwd(self): - """Process current working directory as an absolute path.""" - return self._proc.cwd() - - def nice(self, value=None): - """Get or set process niceness (priority).""" - if value is None: - return self._proc.nice_get() - else: - if not self.is_running(): - raise NoSuchProcess(self.pid, self._name) - self._proc.nice_set(value) - - if POSIX: - - @memoize_when_activated - def uids(self): - """Return process UIDs as a (real, effective, saved) - namedtuple. - """ - return self._proc.uids() - - def gids(self): - """Return process GIDs as a (real, effective, saved) - namedtuple. - """ - return self._proc.gids() - - def terminal(self): - """The terminal associated with this process, if any, - else None. - """ - return self._proc.terminal() - - def num_fds(self): - """Return the number of file descriptors opened by this - process (POSIX only). - """ - return self._proc.num_fds() - - # Linux, BSD, AIX and Windows only - if hasattr(_psplatform.Process, "io_counters"): - - def io_counters(self): - """Return process I/O statistics as a - (read_count, write_count, read_bytes, write_bytes) - namedtuple. - Those are the number of read/write calls performed and the - amount of bytes read and written by the process. - """ - return self._proc.io_counters() - - # Linux and Windows >= Vista only - if hasattr(_psplatform.Process, "ionice_get"): - - def ionice(self, ioclass=None, value=None): - """Get or set process I/O niceness (priority). - - On Linux *ioclass* is one of the IOPRIO_CLASS_* constants. - *value* is a number which goes from 0 to 7. The higher the - value, the lower the I/O priority of the process. - - On Windows only *ioclass* is used and it can be set to 2 - (normal), 1 (low) or 0 (very low). - - Available on Linux and Windows > Vista only. - """ - if ioclass is None: - if value is not None: - raise ValueError("'ioclass' argument must be specified") - return self._proc.ionice_get() - else: - return self._proc.ionice_set(ioclass, value) - - # Linux only - if hasattr(_psplatform.Process, "rlimit"): - - def rlimit(self, resource, limits=None): - """Get or set process resource limits as a (soft, hard) - tuple. - - *resource* is one of the RLIMIT_* constants. - *limits* is supposed to be a (soft, hard) tuple. - - See "man prlimit" for further info. - Available on Linux only. - """ - if limits is None: - return self._proc.rlimit(resource) - else: - return self._proc.rlimit(resource, limits) - - # Windows, Linux and FreeBSD only - if hasattr(_psplatform.Process, "cpu_affinity_get"): - - def cpu_affinity(self, cpus=None): - """Get or set process CPU affinity. - If specified, *cpus* must be a list of CPUs for which you - want to set the affinity (e.g. [0, 1]). - If an empty list is passed, all egible CPUs are assumed - (and set). - (Windows, Linux and BSD only). - """ - if cpus is None: - return list(set(self._proc.cpu_affinity_get())) - else: - if not cpus: - if hasattr(self._proc, "_get_eligible_cpus"): - cpus = self._proc._get_eligible_cpus() - else: - cpus = tuple(range(len(cpu_times(percpu=True)))) - self._proc.cpu_affinity_set(list(set(cpus))) - - # Linux, FreeBSD, SunOS - if hasattr(_psplatform.Process, "cpu_num"): - - def cpu_num(self): - """Return what CPU this process is currently running on. - The returned number should be <= psutil.cpu_count() - and <= len(psutil.cpu_percent(percpu=True)). - It may be used in conjunction with - psutil.cpu_percent(percpu=True) to observe the system - workload distributed across CPUs. - """ - return self._proc.cpu_num() - - # Linux, macOS, Windows, Solaris, AIX - if hasattr(_psplatform.Process, "environ"): - - def environ(self): - """The environment variables of the process as a dict. Note: this - might not reflect changes made after the process started. """ - return self._proc.environ() - - if WINDOWS: - - def num_handles(self): - """Return the number of handles opened by this process - (Windows only). - """ - return self._proc.num_handles() - - def num_ctx_switches(self): - """Return the number of voluntary and involuntary context - switches performed by this process. - """ - return self._proc.num_ctx_switches() - - def num_threads(self): - """Return the number of threads used by this process.""" - return self._proc.num_threads() - - if hasattr(_psplatform.Process, "threads"): - - def threads(self): - """Return threads opened by process as a list of - (id, user_time, system_time) namedtuples representing - thread id and thread CPU times (user/system). - On OpenBSD this method requires root access. - """ - return self._proc.threads() - - @_assert_pid_not_reused - def children(self, recursive=False): - """Return the children of this process as a list of Process - instances, pre-emptively checking whether PID has been reused. - If *recursive* is True return all the parent descendants. - - Example (A == this process): - - A ─┐ - │ - ├─ B (child) ─┐ - │ └─ X (grandchild) ─┐ - │ └─ Y (great grandchild) - ├─ C (child) - └─ D (child) - - >>> import psutil - >>> p = psutil.Process() - >>> p.children() - B, C, D - >>> p.children(recursive=True) - B, X, Y, C, D - - Note that in the example above if process X disappears - process Y won't be listed as the reference to process A - is lost. - """ - ppid_map = _ppid_map() - ret = [] - if not recursive: - for pid, ppid in ppid_map.items(): - if ppid == self.pid: - try: - child = Process(pid) - # if child happens to be older than its parent - # (self) it means child's PID has been reused - if self.create_time() <= child.create_time(): - ret.append(child) - except (NoSuchProcess, ZombieProcess): - pass - else: - # Construct a {pid: [child pids]} dict - reverse_ppid_map = collections.defaultdict(list) - for pid, ppid in ppid_map.items(): - reverse_ppid_map[ppid].append(pid) - # Recursively traverse that dict, starting from self.pid, - # such that we only call Process() on actual children - seen = set() - stack = [self.pid] - while stack: - pid = stack.pop() - if pid in seen: - # Since pids can be reused while the ppid_map is - # constructed, there may be rare instances where - # there's a cycle in the recorded process "tree". - continue - seen.add(pid) - for child_pid in reverse_ppid_map[pid]: - try: - child = Process(child_pid) - # if child happens to be older than its parent - # (self) it means child's PID has been reused - intime = self.create_time() <= child.create_time() - if intime: - ret.append(child) - stack.append(child_pid) - except (NoSuchProcess, ZombieProcess): - pass - return ret - - def cpu_percent(self, interval=None): - """Return a float representing the current process CPU - utilization as a percentage. - - When *interval* is 0.0 or None (default) compares process times - to system CPU times elapsed since last call, returning - immediately (non-blocking). That means that the first time - this is called it will return a meaningful 0.0 value. - - When *interval* is > 0.0 compares process times to system CPU - times elapsed before and after the interval (blocking). - - In this case is recommended for accuracy that this function - be called with at least 0.1 seconds between calls. - - A value > 100.0 can be returned in case of processes running - multiple threads on different CPU cores. - - The returned value is explicitly NOT split evenly between - all available logical CPUs. This means that a busy loop process - running on a system with 2 logical CPUs will be reported as - having 100% CPU utilization instead of 50%. - - Examples: - - >>> import psutil - >>> p = psutil.Process(os.getpid()) - >>> # blocking - >>> p.cpu_percent(interval=1) - 2.0 - >>> # non-blocking (percentage since last call) - >>> p.cpu_percent(interval=None) - 2.9 - >>> - """ - blocking = interval is not None and interval > 0.0 - if interval is not None and interval < 0: - raise ValueError("interval is not positive (got %r)" % interval) - num_cpus = cpu_count() or 1 - - def timer(): - return _timer() * num_cpus - - if blocking: - st1 = timer() - pt1 = self._proc.cpu_times() - time.sleep(interval) - st2 = timer() - pt2 = self._proc.cpu_times() - else: - st1 = self._last_sys_cpu_times - pt1 = self._last_proc_cpu_times - st2 = timer() - pt2 = self._proc.cpu_times() - if st1 is None or pt1 is None: - self._last_sys_cpu_times = st2 - self._last_proc_cpu_times = pt2 - return 0.0 - - delta_proc = (pt2.user - pt1.user) + (pt2.system - pt1.system) - delta_time = st2 - st1 - # reset values for next call in case of interval == None - self._last_sys_cpu_times = st2 - self._last_proc_cpu_times = pt2 - - try: - # This is the utilization split evenly between all CPUs. - # E.g. a busy loop process on a 2-CPU-cores system at this - # point is reported as 50% instead of 100%. - overall_cpus_percent = ((delta_proc / delta_time) * 100) - except ZeroDivisionError: - # interval was too low - return 0.0 - else: - # Note 1: - # in order to emulate "top" we multiply the value for the num - # of CPU cores. This way the busy process will be reported as - # having 100% (or more) usage. - # - # Note 2: - # taskmgr.exe on Windows differs in that it will show 50% - # instead. - # - # Note 3: - # a percentage > 100 is legitimate as it can result from a - # process with multiple threads running on different CPU - # cores (top does the same), see: - # http://stackoverflow.com/questions/1032357 - # https://github.com/giampaolo/psutil/issues/474 - single_cpu_percent = overall_cpus_percent * num_cpus - return round(single_cpu_percent, 1) - - @memoize_when_activated - def cpu_times(self): - """Return a (user, system, children_user, children_system) - namedtuple representing the accumulated process time, in - seconds. - This is similar to os.times() but per-process. - On macOS and Windows children_user and children_system are - always set to 0. - """ - return self._proc.cpu_times() - - @memoize_when_activated - def memory_info(self): - """Return a namedtuple with variable fields depending on the - platform, representing memory information about the process. - - The "portable" fields available on all plaforms are `rss` and `vms`. - - All numbers are expressed in bytes. - """ - return self._proc.memory_info() - - @deprecated_method(replacement="memory_info") - def memory_info_ex(self): - return self.memory_info() - - def memory_full_info(self): - """This method returns the same information as memory_info(), - plus, on some platform (Linux, macOS, Windows), also provides - additional metrics (USS, PSS and swap). - The additional metrics provide a better representation of actual - process memory usage. - - Namely USS is the memory which is unique to a process and which - would be freed if the process was terminated right now. - - It does so by passing through the whole process address. - As such it usually requires higher user privileges than - memory_info() and is considerably slower. - """ - return self._proc.memory_full_info() - - def memory_percent(self, memtype="rss"): - """Compare process memory to total physical system memory and - calculate process memory utilization as a percentage. - *memtype* argument is a string that dictates what type of - process memory you want to compare against (defaults to "rss"). - The list of available strings can be obtained like this: - - >>> psutil.Process().memory_info()._fields - ('rss', 'vms', 'shared', 'text', 'lib', 'data', 'dirty', 'uss', 'pss') - """ - valid_types = list(_psplatform.pfullmem._fields) - if memtype not in valid_types: - raise ValueError("invalid memtype %r; valid types are %r" % ( - memtype, tuple(valid_types))) - fun = self.memory_info if memtype in _psplatform.pmem._fields else \ - self.memory_full_info - metrics = fun() - value = getattr(metrics, memtype) - - # use cached value if available - total_phymem = _TOTAL_PHYMEM or virtual_memory().total - if not total_phymem > 0: - # we should never get here - raise ValueError( - "can't calculate process memory percent because " - "total physical system memory is not positive (%r)" - % total_phymem) - return (value / float(total_phymem)) * 100 - - if hasattr(_psplatform.Process, "memory_maps"): - def memory_maps(self, grouped=True): - """Return process' mapped memory regions as a list of namedtuples - whose fields are variable depending on the platform. - - If *grouped* is True the mapped regions with the same 'path' - are grouped together and the different memory fields are summed. - - If *grouped* is False every mapped region is shown as a single - entity and the namedtuple will also include the mapped region's - address space ('addr') and permission set ('perms'). - """ - it = self._proc.memory_maps() - if grouped: - d = {} - for tupl in it: - path = tupl[2] - nums = tupl[3:] - try: - d[path] = map(lambda x, y: x + y, d[path], nums) - except KeyError: - d[path] = nums - nt = _psplatform.pmmap_grouped - return [nt(path, *d[path]) for path in d] # NOQA - else: - nt = _psplatform.pmmap_ext - return [nt(*x) for x in it] - - def open_files(self): - """Return files opened by process as a list of - (path, fd) namedtuples including the absolute file name - and file descriptor number. - """ - return self._proc.open_files() - - def connections(self, kind='inet'): - """Return socket connections opened by process as a list of - (fd, family, type, laddr, raddr, status) namedtuples. - The *kind* parameter filters for connections that match the - following criteria: - - +------------+----------------------------------------------------+ - | Kind Value | Connections using | - +------------+----------------------------------------------------+ - | inet | IPv4 and IPv6 | - | inet4 | IPv4 | - | inet6 | IPv6 | - | tcp | TCP | - | tcp4 | TCP over IPv4 | - | tcp6 | TCP over IPv6 | - | udp | UDP | - | udp4 | UDP over IPv4 | - | udp6 | UDP over IPv6 | - | unix | UNIX socket (both UDP and TCP protocols) | - | all | the sum of all the possible families and protocols | - +------------+----------------------------------------------------+ - """ - return self._proc.connections(kind) - - # --- signals - - if POSIX: - def _send_signal(self, sig): - assert not self.pid < 0, self.pid - if self.pid == 0: - # see "man 2 kill" - raise ValueError( - "preventing sending signal to process with PID 0 as it " - "would affect every process in the process group of the " - "calling process (os.getpid()) instead of PID 0") - try: - os.kill(self.pid, sig) - except ProcessLookupError: - if OPENBSD and pid_exists(self.pid): - # We do this because os.kill() lies in case of - # zombie processes. - raise ZombieProcess(self.pid, self._name, self._ppid) - else: - self._gone = True - raise NoSuchProcess(self.pid, self._name) - except PermissionError: - raise AccessDenied(self.pid, self._name) - - @_assert_pid_not_reused - def send_signal(self, sig): - """Send a signal *sig* to process pre-emptively checking - whether PID has been reused (see signal module constants) . - On Windows only SIGTERM is valid and is treated as an alias - for kill(). - """ - if POSIX: - self._send_signal(sig) - else: # pragma: no cover - if sig == signal.SIGTERM: - self._proc.kill() - # py >= 2.7 - elif sig in (getattr(signal, "CTRL_C_EVENT", object()), - getattr(signal, "CTRL_BREAK_EVENT", object())): - self._proc.send_signal(sig) - else: - raise ValueError( - "only SIGTERM, CTRL_C_EVENT and CTRL_BREAK_EVENT signals " - "are supported on Windows") - - @_assert_pid_not_reused - def suspend(self): - """Suspend process execution with SIGSTOP pre-emptively checking - whether PID has been reused. - On Windows this has the effect ot suspending all process threads. - """ - if POSIX: - self._send_signal(signal.SIGSTOP) - else: # pragma: no cover - self._proc.suspend() - - @_assert_pid_not_reused - def resume(self): - """Resume process execution with SIGCONT pre-emptively checking - whether PID has been reused. - On Windows this has the effect of resuming all process threads. - """ - if POSIX: - self._send_signal(signal.SIGCONT) - else: # pragma: no cover - self._proc.resume() - - @_assert_pid_not_reused - def terminate(self): - """Terminate the process with SIGTERM pre-emptively checking - whether PID has been reused. - On Windows this is an alias for kill(). - """ - if POSIX: - self._send_signal(signal.SIGTERM) - else: # pragma: no cover - self._proc.kill() - - @_assert_pid_not_reused - def kill(self): - """Kill the current process with SIGKILL pre-emptively checking - whether PID has been reused. - """ - if POSIX: - self._send_signal(signal.SIGKILL) - else: # pragma: no cover - self._proc.kill() - - def wait(self, timeout=None): - """Wait for process to terminate and, if process is a children - of os.getpid(), also return its exit code, else None. - - If the process is already terminated immediately return None - instead of raising NoSuchProcess. - - If *timeout* (in seconds) is specified and process is still - alive raise TimeoutExpired. - - To wait for multiple Process(es) use psutil.wait_procs(). - """ - if timeout is not None and not timeout >= 0: - raise ValueError("timeout must be a positive integer") - return self._proc.wait(timeout) - - -# ===================================================================== -# --- Popen class -# ===================================================================== - - -class Popen(Process): - """A more convenient interface to stdlib subprocess.Popen class. - It starts a sub process and deals with it exactly as when using - subprocess.Popen class but in addition also provides all the - properties and methods of psutil.Process class as a unified - interface: - - >>> import psutil - >>> from subprocess import PIPE - >>> p = psutil.Popen(["python", "-c", "print 'hi'"], stdout=PIPE) - >>> p.name() - 'python' - >>> p.uids() - user(real=1000, effective=1000, saved=1000) - >>> p.username() - 'giampaolo' - >>> p.communicate() - ('hi\n', None) - >>> p.terminate() - >>> p.wait(timeout=2) - 0 - >>> - - For method names common to both classes such as kill(), terminate() - and wait(), psutil.Process implementation takes precedence. - - Unlike subprocess.Popen this class pre-emptively checks whether PID - has been reused on send_signal(), terminate() and kill() so that - you don't accidentally terminate another process, fixing - http://bugs.python.org/issue6973. - - For a complete documentation refer to: - http://docs.python.org/3/library/subprocess.html - """ - - def __init__(self, *args, **kwargs): - # Explicitly avoid to raise NoSuchProcess in case the process - # spawned by subprocess.Popen terminates too quickly, see: - # https://github.com/giampaolo/psutil/issues/193 - self.__subproc = subprocess.Popen(*args, **kwargs) - self._init(self.__subproc.pid, _ignore_nsp=True) - - def __dir__(self): - return sorted(set(dir(Popen) + dir(subprocess.Popen))) - - def __enter__(self): - if hasattr(self.__subproc, '__enter__'): - self.__subproc.__enter__() - return self - - def __exit__(self, *args, **kwargs): - if hasattr(self.__subproc, '__exit__'): - return self.__subproc.__exit__(*args, **kwargs) - else: - if self.stdout: - self.stdout.close() - if self.stderr: - self.stderr.close() - try: - # Flushing a BufferedWriter may raise an error. - if self.stdin: - self.stdin.close() - finally: - # Wait for the process to terminate, to avoid zombies. - self.wait() - - def __getattribute__(self, name): - try: - return object.__getattribute__(self, name) - except AttributeError: - try: - return object.__getattribute__(self.__subproc, name) - except AttributeError: - raise AttributeError("%s instance has no attribute '%s'" - % (self.__class__.__name__, name)) - - def wait(self, timeout=None): - if self.__subproc.returncode is not None: - return self.__subproc.returncode - ret = super(Popen, self).wait(timeout) - self.__subproc.returncode = ret - return ret - - -# The valid attr names which can be processed by Process.as_dict(). -_as_dict_attrnames = set( - [x for x in dir(Process) if not x.startswith('_') and x not in - ['send_signal', 'suspend', 'resume', 'terminate', 'kill', 'wait', - 'is_running', 'as_dict', 'parent', 'parents', 'children', 'rlimit', - 'memory_info_ex', 'oneshot']]) - - -# ===================================================================== -# --- system processes related functions -# ===================================================================== - - -def pids(): - """Return a list of current running PIDs.""" - global _LOWEST_PID - ret = sorted(_psplatform.pids()) - _LOWEST_PID = ret[0] - return ret - - -def pid_exists(pid): - """Return True if given PID exists in the current process list. - This is faster than doing "pid in psutil.pids()" and - should be preferred. - """ - if pid < 0: - return False - elif pid == 0 and POSIX: - # On POSIX we use os.kill() to determine PID existence. - # According to "man 2 kill" PID 0 has a special meaning - # though: it refers to <> and that is not we want - # to do here. - return pid in pids() - else: - return _psplatform.pid_exists(pid) - - -_pmap = {} -_lock = threading.Lock() - - -def process_iter(attrs=None, ad_value=None): - """Return a generator yielding a Process instance for all - running processes. - - Every new Process instance is only created once and then cached - into an internal table which is updated every time this is used. - - Cached Process instances are checked for identity so that you're - safe in case a PID has been reused by another process, in which - case the cached instance is updated. - - The sorting order in which processes are yielded is based on - their PIDs. - - *attrs* and *ad_value* have the same meaning as in - Process.as_dict(). If *attrs* is specified as_dict() is called - and the resulting dict is stored as a 'info' attribute attached - to returned Process instance. - If *attrs* is an empty list it will retrieve all process info - (slow). - """ - def add(pid): - proc = Process(pid) - if attrs is not None: - proc.info = proc.as_dict(attrs=attrs, ad_value=ad_value) - with _lock: - _pmap[proc.pid] = proc - return proc - - def remove(pid): - with _lock: - _pmap.pop(pid, None) - - a = set(pids()) - b = set(_pmap.keys()) - new_pids = a - b - gone_pids = b - a - for pid in gone_pids: - remove(pid) - - with _lock: - ls = sorted(list(_pmap.items()) + - list(dict.fromkeys(new_pids).items())) - - for pid, proc in ls: - try: - if proc is None: # new process - yield add(pid) - else: - # use is_running() to check whether PID has been reused by - # another process in which case yield a new Process instance - if proc.is_running(): - if attrs is not None: - proc.info = proc.as_dict( - attrs=attrs, ad_value=ad_value) - yield proc - else: - yield add(pid) - except NoSuchProcess: - remove(pid) - except AccessDenied: - # Process creation time can't be determined hence there's - # no way to tell whether the pid of the cached process - # has been reused. Just return the cached version. - if proc is None and pid in _pmap: - try: - yield _pmap[pid] - except KeyError: - # If we get here it is likely that 2 threads were - # using process_iter(). - pass - else: - raise - - -def wait_procs(procs, timeout=None, callback=None): - """Convenience function which waits for a list of processes to - terminate. - - Return a (gone, alive) tuple indicating which processes - are gone and which ones are still alive. - - The gone ones will have a new *returncode* attribute indicating - process exit status (may be None). - - *callback* is a function which gets called every time a process - terminates (a Process instance is passed as callback argument). - - Function will return as soon as all processes terminate or when - *timeout* occurs. - Differently from Process.wait() it will not raise TimeoutExpired if - *timeout* occurs. - - Typical use case is: - - - send SIGTERM to a list of processes - - give them some time to terminate - - send SIGKILL to those ones which are still alive - - Example: - - >>> def on_terminate(proc): - ... print("process {} terminated".format(proc)) - ... - >>> for p in procs: - ... p.terminate() - ... - >>> gone, alive = wait_procs(procs, timeout=3, callback=on_terminate) - >>> for p in alive: - ... p.kill() - """ - def check_gone(proc, timeout): - try: - returncode = proc.wait(timeout=timeout) - except TimeoutExpired: - pass - else: - if returncode is not None or not proc.is_running(): - proc.returncode = returncode - gone.add(proc) - if callback is not None: - callback(proc) - - if timeout is not None and not timeout >= 0: - msg = "timeout must be a positive integer, got %s" % timeout - raise ValueError(msg) - gone = set() - alive = set(procs) - if callback is not None and not callable(callback): - raise TypeError("callback %r is not a callable" % callable) - if timeout is not None: - deadline = _timer() + timeout - - while alive: - if timeout is not None and timeout <= 0: - break - for proc in alive: - # Make sure that every complete iteration (all processes) - # will last max 1 sec. - # We do this because we don't want to wait too long on a - # single process: in case it terminates too late other - # processes may disappear in the meantime and their PID - # reused. - max_timeout = 1.0 / len(alive) - if timeout is not None: - timeout = min((deadline - _timer()), max_timeout) - if timeout <= 0: - break - check_gone(proc, timeout) - else: - check_gone(proc, max_timeout) - alive = alive - gone - - if alive: - # Last attempt over processes survived so far. - # timeout == 0 won't make this function wait any further. - for proc in alive: - check_gone(proc, 0) - alive = alive - gone - - return (list(gone), list(alive)) - - -# ===================================================================== -# --- CPU related functions -# ===================================================================== - - -def cpu_count(logical=True): - """Return the number of logical CPUs in the system (same as - os.cpu_count() in Python 3.4). - - If *logical* is False return the number of physical cores only - (e.g. hyper thread CPUs are excluded). - - Return None if undetermined. - - The return value is cached after first call. - If desired cache can be cleared like this: - - >>> psutil.cpu_count.cache_clear() - """ - if logical: - ret = _psplatform.cpu_count_logical() - else: - ret = _psplatform.cpu_count_physical() - if ret is not None and ret < 1: - ret = None - return ret - - -def cpu_times(percpu=False): - """Return system-wide CPU times as a namedtuple. - Every CPU time represents the seconds the CPU has spent in the - given mode. The namedtuple's fields availability varies depending on the - platform: - - - user - - system - - idle - - nice (UNIX) - - iowait (Linux) - - irq (Linux, FreeBSD) - - softirq (Linux) - - steal (Linux >= 2.6.11) - - guest (Linux >= 2.6.24) - - guest_nice (Linux >= 3.2.0) - - When *percpu* is True return a list of namedtuples for each CPU. - First element of the list refers to first CPU, second element - to second CPU and so on. - The order of the list is consistent across calls. - """ - if not percpu: - return _psplatform.cpu_times() - else: - return _psplatform.per_cpu_times() - - -try: - _last_cpu_times = cpu_times() -except Exception: - # Don't want to crash at import time. - _last_cpu_times = None - -try: - _last_per_cpu_times = cpu_times(percpu=True) -except Exception: - # Don't want to crash at import time. - _last_per_cpu_times = None - - -def _cpu_tot_time(times): - """Given a cpu_time() ntuple calculates the total CPU time - (including idle time). - """ - tot = sum(times) - if LINUX: - # On Linux guest times are already accounted in "user" or - # "nice" times, so we subtract them from total. - # Htop does the same. References: - # https://github.com/giampaolo/psutil/pull/940 - # http://unix.stackexchange.com/questions/178045 - # https://github.com/torvalds/linux/blob/ - # 447976ef4fd09b1be88b316d1a81553f1aa7cd07/kernel/sched/ - # cputime.c#L158 - tot -= getattr(times, "guest", 0) # Linux 2.6.24+ - tot -= getattr(times, "guest_nice", 0) # Linux 3.2.0+ - return tot - - -def _cpu_busy_time(times): - """Given a cpu_time() ntuple calculates the busy CPU time. - We do so by subtracting all idle CPU times. - """ - busy = _cpu_tot_time(times) - busy -= times.idle - # Linux: "iowait" is time during which the CPU does not do anything - # (waits for IO to complete). On Linux IO wait is *not* accounted - # in "idle" time so we subtract it. Htop does the same. - # References: - # https://github.com/torvalds/linux/blob/ - # 447976ef4fd09b1be88b316d1a81553f1aa7cd07/kernel/sched/cputime.c#L244 - busy -= getattr(times, "iowait", 0) - return busy - - -def _cpu_times_deltas(t1, t2): - assert t1._fields == t2._fields, (t1, t2) - field_deltas = [] - for field in _psplatform.scputimes._fields: - field_delta = getattr(t2, field) - getattr(t1, field) - # CPU times are always supposed to increase over time - # or at least remain the same and that's because time - # cannot go backwards. - # Surprisingly sometimes this might not be the case (at - # least on Windows and Linux), see: - # https://github.com/giampaolo/psutil/issues/392 - # https://github.com/giampaolo/psutil/issues/645 - # https://github.com/giampaolo/psutil/issues/1210 - # Trim negative deltas to zero to ignore decreasing fields. - # top does the same. Reference: - # https://gitlab.com/procps-ng/procps/blob/v3.3.12/top/top.c#L5063 - field_delta = max(0, field_delta) - field_deltas.append(field_delta) - return _psplatform.scputimes(*field_deltas) - - -def cpu_percent(interval=None, percpu=False): - """Return a float representing the current system-wide CPU - utilization as a percentage. - - When *interval* is > 0.0 compares system CPU times elapsed before - and after the interval (blocking). - - When *interval* is 0.0 or None compares system CPU times elapsed - since last call or module import, returning immediately (non - blocking). That means the first time this is called it will - return a meaningless 0.0 value which you should ignore. - In this case is recommended for accuracy that this function be - called with at least 0.1 seconds between calls. - - When *percpu* is True returns a list of floats representing the - utilization as a percentage for each CPU. - First element of the list refers to first CPU, second element - to second CPU and so on. - The order of the list is consistent across calls. - - Examples: - - >>> # blocking, system-wide - >>> psutil.cpu_percent(interval=1) - 2.0 - >>> - >>> # blocking, per-cpu - >>> psutil.cpu_percent(interval=1, percpu=True) - [2.0, 1.0] - >>> - >>> # non-blocking (percentage since last call) - >>> psutil.cpu_percent(interval=None) - 2.9 - >>> - """ - global _last_cpu_times - global _last_per_cpu_times - blocking = interval is not None and interval > 0.0 - if interval is not None and interval < 0: - raise ValueError("interval is not positive (got %r)" % interval) - - def calculate(t1, t2): - times_delta = _cpu_times_deltas(t1, t2) - - all_delta = _cpu_tot_time(times_delta) - busy_delta = _cpu_busy_time(times_delta) - - try: - busy_perc = (busy_delta / all_delta) * 100 - except ZeroDivisionError: - return 0.0 - else: - return round(busy_perc, 1) - - # system-wide usage - if not percpu: - if blocking: - t1 = cpu_times() - time.sleep(interval) - else: - t1 = _last_cpu_times - if t1 is None: - # Something bad happened at import time. We'll - # get a meaningful result on the next call. See: - # https://github.com/giampaolo/psutil/pull/715 - t1 = cpu_times() - _last_cpu_times = cpu_times() - return calculate(t1, _last_cpu_times) - # per-cpu usage - else: - ret = [] - if blocking: - tot1 = cpu_times(percpu=True) - time.sleep(interval) - else: - tot1 = _last_per_cpu_times - if tot1 is None: - # Something bad happened at import time. We'll - # get a meaningful result on the next call. See: - # https://github.com/giampaolo/psutil/pull/715 - tot1 = cpu_times(percpu=True) - _last_per_cpu_times = cpu_times(percpu=True) - for t1, t2 in zip(tot1, _last_per_cpu_times): - ret.append(calculate(t1, t2)) - return ret - - -# Use separate global vars for cpu_times_percent() so that it's -# independent from cpu_percent() and they can both be used within -# the same program. -_last_cpu_times_2 = _last_cpu_times -_last_per_cpu_times_2 = _last_per_cpu_times - - -def cpu_times_percent(interval=None, percpu=False): - """Same as cpu_percent() but provides utilization percentages - for each specific CPU time as is returned by cpu_times(). - For instance, on Linux we'll get: - - >>> cpu_times_percent() - cpupercent(user=4.8, nice=0.0, system=4.8, idle=90.5, iowait=0.0, - irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0) - >>> - - *interval* and *percpu* arguments have the same meaning as in - cpu_percent(). - """ - global _last_cpu_times_2 - global _last_per_cpu_times_2 - blocking = interval is not None and interval > 0.0 - if interval is not None and interval < 0: - raise ValueError("interval is not positive (got %r)" % interval) - - def calculate(t1, t2): - nums = [] - times_delta = _cpu_times_deltas(t1, t2) - all_delta = _cpu_tot_time(times_delta) - # "scale" is the value to multiply each delta with to get percentages. - # We use "max" to avoid division by zero (if all_delta is 0, then all - # fields are 0 so percentages will be 0 too. all_delta cannot be a - # fraction because cpu times are integers) - scale = 100.0 / max(1, all_delta) - for field_delta in times_delta: - field_perc = field_delta * scale - field_perc = round(field_perc, 1) - # make sure we don't return negative values or values over 100% - field_perc = min(max(0.0, field_perc), 100.0) - nums.append(field_perc) - return _psplatform.scputimes(*nums) - - # system-wide usage - if not percpu: - if blocking: - t1 = cpu_times() - time.sleep(interval) - else: - t1 = _last_cpu_times_2 - if t1 is None: - # Something bad happened at import time. We'll - # get a meaningful result on the next call. See: - # https://github.com/giampaolo/psutil/pull/715 - t1 = cpu_times() - _last_cpu_times_2 = cpu_times() - return calculate(t1, _last_cpu_times_2) - # per-cpu usage - else: - ret = [] - if blocking: - tot1 = cpu_times(percpu=True) - time.sleep(interval) - else: - tot1 = _last_per_cpu_times_2 - if tot1 is None: - # Something bad happened at import time. We'll - # get a meaningful result on the next call. See: - # https://github.com/giampaolo/psutil/pull/715 - tot1 = cpu_times(percpu=True) - _last_per_cpu_times_2 = cpu_times(percpu=True) - for t1, t2 in zip(tot1, _last_per_cpu_times_2): - ret.append(calculate(t1, t2)) - return ret - - -def cpu_stats(): - """Return CPU statistics.""" - return _psplatform.cpu_stats() - - -if hasattr(_psplatform, "cpu_freq"): - - def cpu_freq(percpu=False): - """Return CPU frequency as a nameduple including current, - min and max frequency expressed in Mhz. - - If *percpu* is True and the system supports per-cpu frequency - retrieval (Linux only) a list of frequencies is returned for - each CPU. If not a list with one element is returned. - """ - ret = _psplatform.cpu_freq() - if percpu: - return ret - else: - num_cpus = float(len(ret)) - if num_cpus == 0: - return None - elif num_cpus == 1: - return ret[0] - else: - currs, mins, maxs = 0.0, 0.0, 0.0 - set_none = False - for cpu in ret: - currs += cpu.current - # On Linux if /proc/cpuinfo is used min/max are set - # to None. - if LINUX and cpu.min is None: - set_none = True - continue - mins += cpu.min - maxs += cpu.max - - current = currs / num_cpus - - if set_none: - min_ = max_ = None - else: - min_ = mins / num_cpus - max_ = maxs / num_cpus - - return _common.scpufreq(current, min_, max_) - - __all__.append("cpu_freq") - - -if hasattr(os, "getloadavg") or hasattr(_psplatform, "getloadavg"): - # Perform this hasattr check once on import time to either use the - # platform based code or proxy straight from the os module. - if hasattr(os, "getloadavg"): - getloadavg = os.getloadavg - else: - getloadavg = _psplatform.getloadavg - - __all__.append("getloadavg") - - -# ===================================================================== -# --- system memory related functions -# ===================================================================== - - -def virtual_memory(): - """Return statistics about system memory usage as a namedtuple - including the following fields, expressed in bytes: - - - total: - total physical memory available. - - - available: - the memory that can be given instantly to processes without the - system going into swap. - This is calculated by summing different memory values depending - on the platform and it is supposed to be used to monitor actual - memory usage in a cross platform fashion. - - - percent: - the percentage usage calculated as (total - available) / total * 100 - - - used: - memory used, calculated differently depending on the platform and - designed for informational purposes only: - macOS: active + wired - BSD: active + wired + cached - Linux: total - free - - - free: - memory not being used at all (zeroed) that is readily available; - note that this doesn't reflect the actual memory available - (use 'available' instead) - - Platform-specific fields: - - - active (UNIX): - memory currently in use or very recently used, and so it is in RAM. - - - inactive (UNIX): - memory that is marked as not used. - - - buffers (BSD, Linux): - cache for things like file system metadata. - - - cached (BSD, macOS): - cache for various things. - - - wired (macOS, BSD): - memory that is marked to always stay in RAM. It is never moved to disk. - - - shared (BSD): - memory that may be simultaneously accessed by multiple processes. - - The sum of 'used' and 'available' does not necessarily equal total. - On Windows 'available' and 'free' are the same. - """ - global _TOTAL_PHYMEM - ret = _psplatform.virtual_memory() - # cached for later use in Process.memory_percent() - _TOTAL_PHYMEM = ret.total - return ret - - -def swap_memory(): - """Return system swap memory statistics as a namedtuple including - the following fields: - - - total: total swap memory in bytes - - used: used swap memory in bytes - - free: free swap memory in bytes - - percent: the percentage usage - - sin: no. of bytes the system has swapped in from disk (cumulative) - - sout: no. of bytes the system has swapped out from disk (cumulative) - - 'sin' and 'sout' on Windows are meaningless and always set to 0. - """ - return _psplatform.swap_memory() - - -# ===================================================================== -# --- disks/paritions related functions -# ===================================================================== - - -def disk_usage(path): - """Return disk usage statistics about the given *path* as a - namedtuple including total, used and free space expressed in bytes - plus the percentage usage. - """ - return _psplatform.disk_usage(path) - - -def disk_partitions(all=False): - """Return mounted partitions as a list of - (device, mountpoint, fstype, opts) namedtuple. - 'opts' field is a raw string separated by commas indicating mount - options which may vary depending on the platform. - - If *all* parameter is False return physical devices only and ignore - all others. - """ - return _psplatform.disk_partitions(all) - - -def disk_io_counters(perdisk=False, nowrap=True): - """Return system disk I/O statistics as a namedtuple including - the following fields: - - - read_count: number of reads - - write_count: number of writes - - read_bytes: number of bytes read - - write_bytes: number of bytes written - - read_time: time spent reading from disk (in ms) - - write_time: time spent writing to disk (in ms) - - Platform specific: - - - busy_time: (Linux, FreeBSD) time spent doing actual I/Os (in ms) - - read_merged_count (Linux): number of merged reads - - write_merged_count (Linux): number of merged writes - - If *perdisk* is True return the same information for every - physical disk installed on the system as a dictionary - with partition names as the keys and the namedtuple - described above as the values. - - If *nowrap* is True it detects and adjust the numbers which overflow - and wrap (restart from 0) and add "old value" to "new value" so that - the returned numbers will always be increasing or remain the same, - but never decrease. - "disk_io_counters.cache_clear()" can be used to invalidate the - cache. - - On recent Windows versions 'diskperf -y' command may need to be - executed first otherwise this function won't find any disk. - """ - kwargs = dict(perdisk=perdisk) if LINUX else {} - rawdict = _psplatform.disk_io_counters(**kwargs) - if not rawdict: - return {} if perdisk else None - if nowrap: - rawdict = _wrap_numbers(rawdict, 'psutil.disk_io_counters') - nt = getattr(_psplatform, "sdiskio", _common.sdiskio) - if perdisk: - for disk, fields in rawdict.items(): - rawdict[disk] = nt(*fields) - return rawdict - else: - return nt(*[sum(x) for x in zip(*rawdict.values())]) - - -disk_io_counters.cache_clear = functools.partial( - _wrap_numbers.cache_clear, 'psutil.disk_io_counters') -disk_io_counters.cache_clear.__doc__ = "Clears nowrap argument cache" - - -# ===================================================================== -# --- network related functions -# ===================================================================== - - -def net_io_counters(pernic=False, nowrap=True): - """Return network I/O statistics as a namedtuple including - the following fields: - - - bytes_sent: number of bytes sent - - bytes_recv: number of bytes received - - packets_sent: number of packets sent - - packets_recv: number of packets received - - errin: total number of errors while receiving - - errout: total number of errors while sending - - dropin: total number of incoming packets which were dropped - - dropout: total number of outgoing packets which were dropped - (always 0 on macOS and BSD) - - If *pernic* is True return the same information for every - network interface installed on the system as a dictionary - with network interface names as the keys and the namedtuple - described above as the values. - - If *nowrap* is True it detects and adjust the numbers which overflow - and wrap (restart from 0) and add "old value" to "new value" so that - the returned numbers will always be increasing or remain the same, - but never decrease. - "disk_io_counters.cache_clear()" can be used to invalidate the - cache. - """ - rawdict = _psplatform.net_io_counters() - if not rawdict: - return {} if pernic else None - if nowrap: - rawdict = _wrap_numbers(rawdict, 'psutil.net_io_counters') - if pernic: - for nic, fields in rawdict.items(): - rawdict[nic] = _common.snetio(*fields) - return rawdict - else: - return _common.snetio(*[sum(x) for x in zip(*rawdict.values())]) - - -net_io_counters.cache_clear = functools.partial( - _wrap_numbers.cache_clear, 'psutil.net_io_counters') -net_io_counters.cache_clear.__doc__ = "Clears nowrap argument cache" - - -def net_connections(kind='inet'): - """Return system-wide socket connections as a list of - (fd, family, type, laddr, raddr, status, pid) namedtuples. - In case of limited privileges 'fd' and 'pid' may be set to -1 - and None respectively. - The *kind* parameter filters for connections that fit the - following criteria: - - +------------+----------------------------------------------------+ - | Kind Value | Connections using | - +------------+----------------------------------------------------+ - | inet | IPv4 and IPv6 | - | inet4 | IPv4 | - | inet6 | IPv6 | - | tcp | TCP | - | tcp4 | TCP over IPv4 | - | tcp6 | TCP over IPv6 | - | udp | UDP | - | udp4 | UDP over IPv4 | - | udp6 | UDP over IPv6 | - | unix | UNIX socket (both UDP and TCP protocols) | - | all | the sum of all the possible families and protocols | - +------------+----------------------------------------------------+ - - On macOS this function requires root privileges. - """ - return _psplatform.net_connections(kind) - - -def net_if_addrs(): - """Return the addresses associated to each NIC (network interface - card) installed on the system as a dictionary whose keys are the - NIC names and value is a list of namedtuples for each address - assigned to the NIC. Each namedtuple includes 5 fields: - - - family: can be either socket.AF_INET, socket.AF_INET6 or - psutil.AF_LINK, which refers to a MAC address. - - address: is the primary address and it is always set. - - netmask: and 'broadcast' and 'ptp' may be None. - - ptp: stands for "point to point" and references the - destination address on a point to point interface - (typically a VPN). - - broadcast: and *ptp* are mutually exclusive. - - Note: you can have more than one address of the same family - associated with each interface. - """ - has_enums = sys.version_info >= (3, 4) - if has_enums: - import socket - rawlist = _psplatform.net_if_addrs() - rawlist.sort(key=lambda x: x[1]) # sort by family - ret = collections.defaultdict(list) - for name, fam, addr, mask, broadcast, ptp in rawlist: - if has_enums: - try: - fam = socket.AddressFamily(fam) - except ValueError: - if WINDOWS and fam == -1: - fam = _psplatform.AF_LINK - elif (hasattr(_psplatform, "AF_LINK") and - _psplatform.AF_LINK == fam): - # Linux defines AF_LINK as an alias for AF_PACKET. - # We re-set the family here so that repr(family) - # will show AF_LINK rather than AF_PACKET - fam = _psplatform.AF_LINK - if fam == _psplatform.AF_LINK: - # The underlying C function may return an incomplete MAC - # address in which case we fill it with null bytes, see: - # https://github.com/giampaolo/psutil/issues/786 - separator = ":" if POSIX else "-" - while addr.count(separator) < 5: - addr += "%s00" % separator - ret[name].append(_common.snicaddr(fam, addr, mask, broadcast, ptp)) - return dict(ret) - - -def net_if_stats(): - """Return information about each NIC (network interface card) - installed on the system as a dictionary whose keys are the - NIC names and value is a namedtuple with the following fields: - - - isup: whether the interface is up (bool) - - duplex: can be either NIC_DUPLEX_FULL, NIC_DUPLEX_HALF or - NIC_DUPLEX_UNKNOWN - - speed: the NIC speed expressed in mega bits (MB); if it can't - be determined (e.g. 'localhost') it will be set to 0. - - mtu: the maximum transmission unit expressed in bytes. - """ - return _psplatform.net_if_stats() - - -# ===================================================================== -# --- sensors -# ===================================================================== - - -# Linux, macOS -if hasattr(_psplatform, "sensors_temperatures"): - - def sensors_temperatures(fahrenheit=False): - """Return hardware temperatures. Each entry is a namedtuple - representing a certain hardware sensor (it may be a CPU, an - hard disk or something else, depending on the OS and its - configuration). - All temperatures are expressed in celsius unless *fahrenheit* - is set to True. - """ - def convert(n): - if n is not None: - return (float(n) * 9 / 5) + 32 if fahrenheit else n - - ret = collections.defaultdict(list) - rawdict = _psplatform.sensors_temperatures() - - for name, values in rawdict.items(): - while values: - label, current, high, critical = values.pop(0) - current = convert(current) - high = convert(high) - critical = convert(critical) - - if high and not critical: - critical = high - elif critical and not high: - high = critical - - ret[name].append( - _common.shwtemp(label, current, high, critical)) - - return dict(ret) - - __all__.append("sensors_temperatures") - - -# Linux, macOS -if hasattr(_psplatform, "sensors_fans"): - - def sensors_fans(): - """Return fans speed. Each entry is a namedtuple - representing a certain hardware sensor. - All speed are expressed in RPM (rounds per minute). - """ - return _psplatform.sensors_fans() - - __all__.append("sensors_fans") - - -# Linux, Windows, FreeBSD, macOS -if hasattr(_psplatform, "sensors_battery"): - - def sensors_battery(): - """Return battery information. If no battery is installed - returns None. - - - percent: battery power left as a percentage. - - secsleft: a rough approximation of how many seconds are left - before the battery runs out of power. May be - POWER_TIME_UNLIMITED or POWER_TIME_UNLIMITED. - - power_plugged: True if the AC power cable is connected. - """ - return _psplatform.sensors_battery() - - __all__.append("sensors_battery") - - -# ===================================================================== -# --- other system related functions -# ===================================================================== - - -def boot_time(): - """Return the system boot time expressed in seconds since the epoch.""" - # Note: we are not caching this because it is subject to - # system clock updates. - return _psplatform.boot_time() - - -def users(): - """Return users currently connected on the system as a list of - namedtuples including the following fields. - - - user: the name of the user - - terminal: the tty or pseudo-tty associated with the user, if any. - - host: the host name associated with the entry, if any. - - started: the creation time as a floating point number expressed in - seconds since the epoch. - """ - return _psplatform.users() - - -# ===================================================================== -# --- Windows services -# ===================================================================== - - -if WINDOWS: - - def win_service_iter(): - """Return a generator yielding a WindowsService instance for all - Windows services installed. - """ - return _psplatform.win_service_iter() - - def win_service_get(name): - """Get a Windows service by *name*. - Raise NoSuchProcess if no service with such name exists. - """ - return _psplatform.win_service_get(name) - - -# ===================================================================== - - -def test(): # pragma: no cover - from ._common import bytes2human - from ._compat import get_terminal_size - - today_day = datetime.date.today() - templ = "%-10s %5s %5s %7s %7s %5s %6s %6s %6s %s" - attrs = ['pid', 'memory_percent', 'name', 'cmdline', 'cpu_times', - 'create_time', 'memory_info', 'status', 'nice', 'username'] - print(templ % ("USER", "PID", "%MEM", "VSZ", "RSS", "NICE", - "STATUS", "START", "TIME", "CMDLINE")) - for p in process_iter(attrs, ad_value=None): - if p.info['create_time']: - ctime = datetime.datetime.fromtimestamp(p.info['create_time']) - if ctime.date() == today_day: - ctime = ctime.strftime("%H:%M") - else: - ctime = ctime.strftime("%b%d") - else: - ctime = '' - if p.info['cpu_times']: - cputime = time.strftime("%M:%S", - time.localtime(sum(p.info['cpu_times']))) - else: - cputime = '' - - user = p.info['username'] or '' - if not user and POSIX: - try: - user = p.uids()[0] - except Error: - pass - if user and WINDOWS and '\\' in user: - user = user.split('\\')[1] - user = user[:9] - vms = bytes2human(p.info['memory_info'].vms) if \ - p.info['memory_info'] is not None else '' - rss = bytes2human(p.info['memory_info'].rss) if \ - p.info['memory_info'] is not None else '' - memp = round(p.info['memory_percent'], 1) if \ - p.info['memory_percent'] is not None else '' - nice = int(p.info['nice']) if p.info['nice'] else '' - if p.info['cmdline']: - cmdline = ' '.join(p.info['cmdline']) - else: - cmdline = p.info['name'] - status = p.info['status'][:5] if p.info['status'] else '' - - line = templ % ( - user[:10], - p.info['pid'], - memp, - vms, - rss, - nice, - status, - ctime, - cputime, - cmdline) - print(line[:get_terminal_size()[0]]) - - -del memoize, memoize_when_activated, division, deprecated_method -if sys.version_info[0] < 3: - del num, x - -if __name__ == "__main__": - test() diff --git a/ddtrace/vendor/psutil/_common.py b/ddtrace/vendor/psutil/_common.py deleted file mode 100644 index a0f5e751b83..00000000000 --- a/ddtrace/vendor/psutil/_common.py +++ /dev/null @@ -1,651 +0,0 @@ -# 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', 'MACOS', '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', 'STATUS_PARKED', - # named tuples - 'pconn', 'pcputimes', 'pctxsw', 'pgids', 'pio', 'pionice', 'popenfile', - 'pthread', 'puids', 'sconn', 'scpustats', 'sdiskio', 'sdiskpart', - 'sdiskusage', 'snetio', 'snicaddr', '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", - 'bytes2human', 'conn_to_ntuple', -] - - -# =================================================================== -# --- OS constants -# =================================================================== - - -POSIX = os.name == "posix" -WINDOWS = os.name == "nt" -LINUX = sys.platform.startswith("linux") -MACOS = sys.platform.startswith("darwin") -OSX = MACOS # deprecated alias -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", "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" # Linux, macOS, FreeBSD -STATUS_LOCKED = "locked" # FreeBSD -STATUS_WAITING = "waiting" # FreeBSD -STATUS_SUSPENDED = "suspended" # NetBSD -STATUS_PARKED = "parked" # Linux - -# 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() -snicaddr = namedtuple('snicaddr', - ['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_fans() -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]), - }) - - -# =================================================================== -# --- utils -# =================================================================== - - -def usage_percent(used, total, round_=None): - """Calculate percentage usage of 'used' against 'total'.""" - try: - ret = (float(used) / total) * 100 - except ZeroDivisionError: - return 0.0 - else: - if round_ is not None: - ret = round(ret, round_) - 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(self) - >>> foo() - 1 - >>> foo() - >>> foo() - >>> - """ - @functools.wraps(fun) - def wrapper(self): - try: - # case 1: we previously entered oneshot() ctx - ret = self._cache[fun] - except AttributeError: - # case 2: we never entered oneshot() ctx - return fun(self) - except KeyError: - # case 3: we entered oneshot() ctx but there's no cache - # for this entry yet - ret = self._cache[fun] = fun(self) - return ret - - def cache_activate(proc): - """Activate cache. Expects a Process instance. Cache will be - stored as a "_cache" instance attribute.""" - proc._cache = {} - - def cache_deactivate(proc): - """Deactivate and clear cache.""" - try: - del proc._cache - except AttributeError: - pass - - 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: - 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.SocketKind(num) - except ValueError: - return num - - -def conn_to_ntuple(fd, fam, type_, laddr, raddr, status, status_map, pid=None): - """Convert a raw connection tuple to a proper ntuple.""" - if fam in (socket.AF_INET, AF_INET6): - if laddr: - laddr = addr(*laddr) - if raddr: - raddr = addr(*raddr) - if type_ == socket.SOCK_STREAM and fam in (AF_INET, AF_INET6): - status = status_map.get(status, CONN_NONE) - else: - status = CONN_NONE # ignore whatever C returned to us - fam = sockfam_to_enum(fam) - type_ = socktype_to_enum(type_) - if pid is None: - return pconn(fd, fam, type_, laddr, raddr, status) - else: - return sconn(fd, fam, type_, laddr, raddr, status, pid) - - -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=DeprecationWarning, 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 - - -def open_binary(fname, **kwargs): - return open(fname, "rb", **kwargs) - - -def open_text(fname, **kwargs): - """On Python 3 opens a file in text mode by using fs encoding and - a proper en/decoding errors handler. - On Python 2 this is just an alias for open(name, 'rt'). - """ - if PY3: - # See: - # https://github.com/giampaolo/psutil/issues/675 - # https://github.com/giampaolo/psutil/pull/733 - kwargs.setdefault('encoding', ENCODING) - kwargs.setdefault('errors', ENCODING_ERRS) - return open(fname, "rt", **kwargs) - - -def bytes2human(n, format="%(value).1f%(symbol)s"): - """Used by various scripts. See: - http://goo.gl/zeJZl - - >>> bytes2human(10000) - '9.8K' - >>> bytes2human(100001221) - '95.4M' - """ - symbols = ('B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y') - prefix = {} - for i, s in enumerate(symbols[1:]): - prefix[s] = 1 << (i + 1) * 10 - for symbol in reversed(symbols[1:]): - if n >= prefix[symbol]: - value = float(n) / prefix[symbol] - return format % locals() - return format % dict(symbol=symbols[0], value=n) - - -def get_procfs_path(): - """Return updated psutil.PROCFS_PATH constant.""" - return sys.modules['ddtrace.vendor.psutil'].PROCFS_PATH - - -if PY3: - def decode(s): - return s.decode(encoding=ENCODING, errors=ENCODING_ERRS) -else: - def decode(s): - return s diff --git a/ddtrace/vendor/psutil/_compat.py b/ddtrace/vendor/psutil/_compat.py deleted file mode 100644 index 07ab909a84f..00000000000 --- a/ddtrace/vendor/psutil/_compat.py +++ /dev/null @@ -1,332 +0,0 @@ -# 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 errno -import functools -import os -import sys - -__all__ = ["PY3", "long", "xrange", "unicode", "basestring", "u", "b", - "lru_cache", "which", "get_terminal_size", - "FileNotFoundError", "PermissionError", "ProcessLookupError", - "InterruptedError", "ChildProcessError", "FileExistsError"] - -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 - - -# --- exceptions - - -if PY3: - FileNotFoundError = FileNotFoundError # NOQA - PermissionError = PermissionError # NOQA - ProcessLookupError = ProcessLookupError # NOQA - InterruptedError = InterruptedError # NOQA - ChildProcessError = ChildProcessError # NOQA - FileExistsError = FileExistsError # NOQA -else: - # https://github.com/PythonCharmers/python-future/blob/exceptions/ - # src/future/types/exceptions/pep3151.py - - def instance_checking_exception(base_exception=Exception): - def wrapped(instance_checker): - class TemporaryClass(base_exception): - - def __init__(self, *args, **kwargs): - if len(args) == 1 and isinstance(args[0], TemporaryClass): - unwrap_me = args[0] - for attr in dir(unwrap_me): - if not attr.startswith('__'): - setattr(self, attr, getattr(unwrap_me, attr)) - else: - super(TemporaryClass, self).__init__(*args, **kwargs) - - class __metaclass__(type): - def __instancecheck__(cls, inst): - return instance_checker(inst) - - def __subclasscheck__(cls, classinfo): - value = sys.exc_info()[1] - return isinstance(value, cls) - - TemporaryClass.__name__ = instance_checker.__name__ - TemporaryClass.__doc__ = instance_checker.__doc__ - return TemporaryClass - - return wrapped - - @instance_checking_exception(EnvironmentError) - def FileNotFoundError(inst): - return getattr(inst, 'errno', object()) == errno.ENOENT - - @instance_checking_exception(EnvironmentError) - def ProcessLookupError(inst): - return getattr(inst, 'errno', object()) == errno.ESRCH - - @instance_checking_exception(EnvironmentError) - def PermissionError(inst): - return getattr(inst, 'errno', object()) in ( - errno.EACCES, errno.EPERM) - - @instance_checking_exception(EnvironmentError) - def InterruptedError(inst): - return getattr(inst, 'errno', object()) == errno.EINTR - - @instance_checking_exception(EnvironmentError) - def ChildProcessError(inst): - return getattr(inst, 'errno', object()) == errno.ECHILD - - @instance_checking_exception(EnvironmentError) - def FileExistsError(inst): - return getattr(inst, 'errno', object()) == errno.EEXIST - - -# --- 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 - - -# python 3.3 -try: - from shutil import get_terminal_size -except ImportError: - def get_terminal_size(fallback=(80, 24)): - try: - import fcntl - import termios - import struct - except ImportError: - return fallback - else: - try: - # This should work on Linux. - res = struct.unpack( - 'hh', fcntl.ioctl(1, termios.TIOCGWINSZ, '1234')) - return (res[1], res[0]) - except Exception: - return fallback diff --git a/ddtrace/vendor/psutil/_psaix.py b/ddtrace/vendor/psutil/_psaix.py deleted file mode 100644 index 79e3be15a19..00000000000 --- a/ddtrace/vendor/psutil/_psaix.py +++ /dev/null @@ -1,554 +0,0 @@ -# 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 functools -import glob -import os -import re -import subprocess -import sys -from collections import namedtuple - -from . import _common -from . import _psposix -from . import _psutil_aix as cext -from . import _psutil_posix as cext_posix -from ._common import conn_to_ntuple -from ._common import get_procfs_path -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 usage_percent -from ._compat import FileNotFoundError -from ._compat import PermissionError -from ._compat import ProcessLookupError -from ._compat import PY3 - - -__extra__all__ = ["PROCFS_PATH"] - - -# ===================================================================== -# --- globals -# ===================================================================== - - -HAS_THREADS = hasattr(cext, "proc_threads") -HAS_NET_IO_COUNTERS = hasattr(cext, "net_io_counters") -HAS_PROC_IO_COUNTERS = hasattr(cext, "proc_io_counters") - -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) - -# These objects get set on "import psutil" from the __init__.py -# file, see: https://github.com/giampaolo/psutil/issues/1402 -NoSuchProcess = None -ZombieProcess = None -AccessDenied = None -TimeoutExpired = None - - -# ===================================================================== -# --- 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']) - - -# ===================================================================== -# --- 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 - -if HAS_NET_IO_COUNTERS: - 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 = [] - for item in rawlist: - fd, fam, type_, laddr, raddr, status, pid = item - if fam not in families: - continue - if type_ not in types: - continue - nt = conn_to_ntuple(fd, fam, type_, laddr, raddr, status, - TCP_STATUSES, pid=pid if _pid == -1 else None) - ret.append(nt) - return 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( - r"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. - """ - @functools.wraps(fun) - def wrapper(self, *args, **kwargs): - try: - return fun(self, *args, **kwargs) - except (FileNotFoundError, ProcessLookupError): - # 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 not pid_exists(self.pid): - raise NoSuchProcess(self.pid, self._name) - else: - raise ZombieProcess(self.pid, self._name, self._ppid) - except PermissionError: - raise AccessDenied(self.pid, self._name) - return wrapper - - -class Process(object): - """Wrapper class around underlying C implementation.""" - - __slots__ = ["pid", "_name", "_ppid", "_procfs_path", "_cache"] - - 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_basic_info.cache_activate(self) - self._proc_cred.cache_activate(self) - - def oneshot_exit(self): - self._proc_basic_info.cache_deactivate(self) - self._proc_cred.cache_deactivate(self) - - @wrap_exceptions - @memoize_when_activated - def _proc_basic_info(self): - return cext.proc_basic_info(self.pid, self._procfs_path) - - @wrap_exceptions - @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: max 16 characters - return cext.proc_name(self.pid, self._procfs_path).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 - cmdline = self.cmdline() - if not cmdline: - return '' - exe = 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 cext.proc_args(self.pid) - - @wrap_exceptions - def environ(self): - return cext.proc_environ(self.pid) - - @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 FileNotFoundError: - os.stat("%s/%s" % (procfs_path, self.pid)) # raise NSP or AD - return None - - @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(r"(\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) - - if HAS_PROC_IO_COUNTERS: - @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) diff --git a/ddtrace/vendor/psutil/_psbsd.py b/ddtrace/vendor/psutil/_psbsd.py deleted file mode 100644 index 2f41dc0be9f..00000000000 --- a/ddtrace/vendor/psutil/_psbsd.py +++ /dev/null @@ -1,905 +0,0 @@ -# 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 collections import defaultdict - -from . import _common -from . import _psposix -from . import _psutil_bsd as cext -from . import _psutil_posix as cext_posix -from ._common import conn_tmap -from ._common import conn_to_ntuple -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 usage_percent -from ._compat import FileNotFoundError -from ._compat import PermissionError -from ._compat import ProcessLookupError -from ._compat import which - - -__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 - -HAS_PER_CPU_TIMES = hasattr(cext, "per_cpu_times") -HAS_PROC_NUM_THREADS = hasattr(cext, "proc_num_threads") -HAS_PROC_OPEN_FILES = hasattr(cext, 'proc_open_files') -HAS_PROC_NUM_FDS = hasattr(cext, 'proc_num_fds') - -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, -) - -# These objects get set on "import psutil" from the __init__.py -# file, see: https://github.com/giampaolo/psutil/issues/1402 -NoSuchProcess = None -ZombieProcess = None -AccessDenied = None -TimeoutExpired = None - - -# ===================================================================== -# --- 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 HAS_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("") - 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: - try: - mtu = cext_posix.net_if_mtu(name) - isup = cext_posix.net_if_flags(name) - duplex, speed = cext_posix.net_if_duplex_speed(name) - except OSError as err: - # https://github.com/giampaolo/psutil/issues/1279 - if err.errno != errno.ENODEV: - raise - else: - 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: - nt = conn_to_ntuple(fd, fam, type, laddr, raddr, status, - TCP_STATUSES, 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) - - def sensors_temperatures(): - "Return CPU cores temperatures if available, else an empty dict." - ret = defaultdict(list) - num_cpus = cpu_count_logical() - for cpu in range(num_cpus): - try: - current, high = cext.sensors_cpu_temperature(cpu) - if high <= 0: - high = None - name = "Core %s" % cpu - ret["coretemp"].append( - _common.shwtemp(name, current, high, high)) - except NotImplementedError: - pass - - return ret - - def cpu_freq(): - """Return frequency metrics for CPUs. As of Dec 2018 only - CPU 0 appears to be supported by FreeBSD and all other cores - match the frequency of CPU 0. - """ - ret = [] - num_cpus = cpu_count_logical() - for cpu in range(num_cpus): - try: - current, available_freq = cext.cpu_frequency(cpu) - except NotImplementedError: - continue - if available_freq: - try: - min_freq = int(available_freq.split(" ")[-1].split("/")[0]) - except(IndexError, ValueError): - min_freq = None - try: - max_freq = int(available_freq.split(" ")[0].split("/")[0]) - except(IndexError, ValueError): - max_freq = None - ret.append(_common.scpufreq(current, min_freq, max_freq)) - 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 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 is_zombie(pid): - try: - st = cext.proc_oneshot_info(pid)[kinfo_proc_map['status']] - return st == cext.SZOMB - except Exception: - return False - - -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 ProcessLookupError: - if not pid_exists(self.pid): - raise NoSuchProcess(self.pid, self._name) - else: - raise ZombieProcess(self.pid, self._name, self._ppid) - except PermissionError: - raise AccessDenied(self.pid, self._name) - except OSError: - if self.pid == 0: - if 0 in pids(): - raise AccessDenied(self.pid, self._name) - else: - raise - raise - return wrapper - - -@contextlib.contextmanager -def wrap_exceptions_procfs(inst): - """Same as above, for routines relying on reading /proc fs.""" - try: - yield - except (ProcessLookupError, FileNotFoundError): - # 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 not pid_exists(inst.pid): - raise NoSuchProcess(inst.pid, inst._name) - else: - raise ZombieProcess(inst.pid, inst._name, inst._ppid) - except PermissionError: - raise AccessDenied(inst.pid, inst._name) - - -class Process(object): - """Wrapper class around underlying C implementation.""" - - __slots__ = ["pid", "_name", "_ppid", "_cache"] - - def __init__(self, pid): - self.pid = pid - self._name = None - self._ppid = None - - def _assert_alive(self): - """Raise NSP if the process disappeared on us.""" - # For those C function who do not raise NSP, possibly returning - # incorrect or incomplete result. - cext.proc_name(self.pid) - - @wrap_exceptions - @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(self) - - def oneshot_exit(self): - self.oneshot.cache_deactivate(self) - - @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 is_zombie(self.pid): - raise ZombieProcess(self.pid, self._name, self._ppid) - elif not pid_exists(self.pid): - raise NoSuchProcess(self.pid, self._name, self._ppid) - else: - # XXX: this happens with unicode tests. It means the C - # routine is unable to decode invalid unicode chars. - return [] - 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 HAS_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: - self._assert_alive() - 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 = [] - 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: - nt = conn_to_ntuple(fd, fam, type, laddr, raddr, status, - TCP_STATUSES) - ret.append(nt) - self._assert_alive() - 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 - nt = conn_to_ntuple(fd, fam, type, laddr, raddr, status, - TCP_STATUSES) - ret.append(nt) - - if OPENBSD: - self._assert_alive() - - 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 or HAS_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 HAS_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 HAS_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: - self._assert_alive() - 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: - # <> - 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) diff --git a/ddtrace/vendor/psutil/_pslinux.py b/ddtrace/vendor/psutil/_pslinux.py deleted file mode 100644 index a56ead36985..00000000000 --- a/ddtrace/vendor/psutil/_pslinux.py +++ /dev/null @@ -1,2096 +0,0 @@ -# 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. - -"""Linux platform implementation.""" - -from __future__ import division - -import base64 -import collections -import errno -import functools -import glob -import os -import re -import socket -import struct -import sys -import traceback -import warnings -from collections import defaultdict -from collections import namedtuple - -from . import _common -from . import _psposix -from . import _psutil_linux as cext -from . import _psutil_posix as cext_posix -from ._common import decode -from ._common import get_procfs_path -from ._common import isfile_strict -from ._common import memoize -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 open_binary -from ._common import open_text -from ._common import parse_environ_block -from ._common import path_exists_strict -from ._common import supports_ipv6 -from ._common import usage_percent -from ._compat import b -from ._compat import basestring -from ._compat import FileNotFoundError -from ._compat import PermissionError -from ._compat import ProcessLookupError -from ._compat import PY3 - -if sys.version_info >= (3, 4): - import enum -else: - enum = None - - -__extra__all__ = [ - # - 'PROCFS_PATH', - # io prio constants - "IOPRIO_CLASS_NONE", "IOPRIO_CLASS_RT", "IOPRIO_CLASS_BE", - "IOPRIO_CLASS_IDLE", - # connection status constants - "CONN_ESTABLISHED", "CONN_SYN_SENT", "CONN_SYN_RECV", "CONN_FIN_WAIT1", - "CONN_FIN_WAIT2", "CONN_TIME_WAIT", "CONN_CLOSE", "CONN_CLOSE_WAIT", - "CONN_LAST_ACK", "CONN_LISTEN", "CONN_CLOSING", ] - - -# ===================================================================== -# --- globals -# ===================================================================== - - -POWER_SUPPLY_PATH = "/sys/class/power_supply" -HAS_SMAPS = os.path.exists('/proc/%s/smaps' % os.getpid()) -HAS_PRLIMIT = hasattr(cext, "linux_prlimit") -HAS_PROC_IO_PRIORITY = hasattr(cext, "proc_ioprio_get") -HAS_CPU_AFFINITY = hasattr(cext, "proc_cpu_affinity_get") -_DEFAULT = object() - -# RLIMIT_* constants, not guaranteed to be present on all kernels -if HAS_PRLIMIT: - for name in dir(cext): - if name.startswith('RLIM'): - __extra__all__.append(name) - -# Number of clock ticks per second -CLOCK_TICKS = os.sysconf("SC_CLK_TCK") -PAGESIZE = os.sysconf("SC_PAGE_SIZE") -BOOT_TIME = None # set later -# Used when reading "big" files, namely /proc/{pid}/smaps and /proc/net/*. -# On Python 2, using a buffer with open() for such files may result in a -# speedup, see: https://github.com/giampaolo/psutil/issues/708 -BIGFILE_BUFFERING = -1 if PY3 else 8192 -LITTLE_ENDIAN = sys.byteorder == 'little' - -# "man iostat" states that sectors are equivalent with blocks and have -# a size of 512 bytes. Despite this value can be queried at runtime -# via /sys/block/{DISK}/queue/hw_sector_size and results may vary -# between 1k, 2k, or 4k... 512 appears to be a magic constant used -# throughout Linux source code: -# * https://stackoverflow.com/a/38136179/376587 -# * https://lists.gt.net/linux/kernel/2241060 -# * https://github.com/giampaolo/psutil/issues/1305 -# * https://github.com/torvalds/linux/blob/ -# 4f671fe2f9523a1ea206f63fe60a7c7b3a56d5c7/include/linux/bio.h#L99 -# * https://lkml.org/lkml/2015/8/17/234 -DISK_SECTOR_SIZE = 512 - -if enum is None: - AF_LINK = socket.AF_PACKET -else: - AddressFamily = enum.IntEnum('AddressFamily', - {'AF_LINK': int(socket.AF_PACKET)}) - AF_LINK = AddressFamily.AF_LINK - -# ioprio_* constants http://linux.die.net/man/2/ioprio_get -if enum is None: - IOPRIO_CLASS_NONE = 0 - IOPRIO_CLASS_RT = 1 - IOPRIO_CLASS_BE = 2 - IOPRIO_CLASS_IDLE = 3 -else: - class IOPriority(enum.IntEnum): - IOPRIO_CLASS_NONE = 0 - IOPRIO_CLASS_RT = 1 - IOPRIO_CLASS_BE = 2 - IOPRIO_CLASS_IDLE = 3 - - globals().update(IOPriority.__members__) - -# See: -# https://github.com/torvalds/linux/blame/master/fs/proc/array.c -# ...and (TASK_* constants): -# https://github.com/torvalds/linux/blob/master/include/linux/sched.h -PROC_STATUSES = { - "R": _common.STATUS_RUNNING, - "S": _common.STATUS_SLEEPING, - "D": _common.STATUS_DISK_SLEEP, - "T": _common.STATUS_STOPPED, - "t": _common.STATUS_TRACING_STOP, - "Z": _common.STATUS_ZOMBIE, - "X": _common.STATUS_DEAD, - "x": _common.STATUS_DEAD, - "K": _common.STATUS_WAKE_KILL, - "W": _common.STATUS_WAKING, - "I": _common.STATUS_IDLE, - "P": _common.STATUS_PARKED, -} - -# https://github.com/torvalds/linux/blob/master/include/net/tcp_states.h -TCP_STATUSES = { - "01": _common.CONN_ESTABLISHED, - "02": _common.CONN_SYN_SENT, - "03": _common.CONN_SYN_RECV, - "04": _common.CONN_FIN_WAIT1, - "05": _common.CONN_FIN_WAIT2, - "06": _common.CONN_TIME_WAIT, - "07": _common.CONN_CLOSE, - "08": _common.CONN_CLOSE_WAIT, - "09": _common.CONN_LAST_ACK, - "0A": _common.CONN_LISTEN, - "0B": _common.CONN_CLOSING -} - -# These objects get set on "import psutil" from the __init__.py -# file, see: https://github.com/giampaolo/psutil/issues/1402 -NoSuchProcess = None -ZombieProcess = None -AccessDenied = None -TimeoutExpired = None - - -# ===================================================================== -# --- named tuples -# ===================================================================== - - -# psutil.virtual_memory() -svmem = namedtuple( - 'svmem', ['total', 'available', 'percent', 'used', 'free', - 'active', 'inactive', 'buffers', 'cached', 'shared', 'slab']) -# psutil.disk_io_counters() -sdiskio = namedtuple( - 'sdiskio', ['read_count', 'write_count', - 'read_bytes', 'write_bytes', - 'read_time', 'write_time', - 'read_merged_count', 'write_merged_count', - 'busy_time']) -# psutil.Process().open_files() -popenfile = namedtuple( - 'popenfile', ['path', 'fd', 'position', 'mode', 'flags']) -# psutil.Process().memory_info() -pmem = namedtuple('pmem', 'rss vms shared text lib data dirty') -# psutil.Process().memory_full_info() -pfullmem = namedtuple('pfullmem', pmem._fields + ('uss', 'pss', 'swap')) -# psutil.Process().memory_maps(grouped=True) -pmmap_grouped = namedtuple( - 'pmmap_grouped', - ['path', 'rss', 'size', 'pss', 'shared_clean', 'shared_dirty', - 'private_clean', 'private_dirty', 'referenced', 'anonymous', 'swap']) -# psutil.Process().memory_maps(grouped=False) -pmmap_ext = namedtuple( - 'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields)) -# psutil.Process.io_counters() -pio = namedtuple('pio', ['read_count', 'write_count', - 'read_bytes', 'write_bytes', - 'read_chars', 'write_chars']) -# psutil.Process.cpu_times() -pcputimes = namedtuple('pcputimes', - ['user', 'system', 'children_user', 'children_system', - 'iowait']) - - -# ===================================================================== -# --- utils -# ===================================================================== - - -def readlink(path): - """Wrapper around os.readlink().""" - assert isinstance(path, basestring), path - path = os.readlink(path) - # readlink() might return paths containing null bytes ('\x00') - # resulting in "TypeError: must be encoded string without NULL - # bytes, not str" errors when the string is passed to other - # fs-related functions (os.*, open(), ...). - # Apparently everything after '\x00' is garbage (we can have - # ' (deleted)', 'new' and possibly others), see: - # https://github.com/giampaolo/psutil/issues/717 - path = path.split('\x00')[0] - # Certain paths have ' (deleted)' appended. Usually this is - # bogus as the file actually exists. Even if it doesn't we - # don't care. - if path.endswith(' (deleted)') and not path_exists_strict(path): - path = path[:-10] - return path - - -def file_flags_to_mode(flags): - """Convert file's open() flags into a readable string. - Used by Process.open_files(). - """ - modes_map = {os.O_RDONLY: 'r', os.O_WRONLY: 'w', os.O_RDWR: 'w+'} - mode = modes_map[flags & (os.O_RDONLY | os.O_WRONLY | os.O_RDWR)] - if flags & os.O_APPEND: - mode = mode.replace('w', 'a', 1) - mode = mode.replace('w+', 'r+') - # possible values: r, w, a, r+, a+ - return mode - - -def is_storage_device(name): - """Return True if the given name refers to a root device (e.g. - "sda", "nvme0n1") as opposed to a logical partition (e.g. "sda1", - "nvme0n1p1"). If name is a virtual device (e.g. "loop1", "ram") - return True. - """ - # Readapted from iostat source code, see: - # https://github.com/sysstat/sysstat/blob/ - # 97912938cd476645b267280069e83b1c8dc0e1c7/common.c#L208 - # Some devices may have a slash in their name (e.g. cciss/c0d0...). - name = name.replace('/', '!') - including_virtual = True - if including_virtual: - path = "/sys/block/%s" % name - else: - path = "/sys/block/%s/device" % name - return os.access(path, os.F_OK) - - -@memoize -def set_scputimes_ntuple(procfs_path): - """Set a namedtuple of variable fields depending on the CPU times - available on this Linux kernel version which may be: - (user, nice, system, idle, iowait, irq, softirq, [steal, [guest, - [guest_nice]]]) - Used by cpu_times() function. - """ - global scputimes - with open_binary('%s/stat' % procfs_path) as f: - values = f.readline().split()[1:] - fields = ['user', 'nice', 'system', 'idle', 'iowait', 'irq', 'softirq'] - vlen = len(values) - if vlen >= 8: - # Linux >= 2.6.11 - fields.append('steal') - if vlen >= 9: - # Linux >= 2.6.24 - fields.append('guest') - if vlen >= 10: - # Linux >= 3.2.0 - fields.append('guest_nice') - scputimes = namedtuple('scputimes', fields) - - -def cat(fname, fallback=_DEFAULT, binary=True): - """Return file content. - fallback: the value returned in case the file does not exist or - cannot be read - binary: whether to open the file in binary or text mode. - """ - try: - with open_binary(fname) if binary else open_text(fname) as f: - return f.read().strip() - except (IOError, OSError): - if fallback is not _DEFAULT: - return fallback - else: - raise - - -try: - set_scputimes_ntuple("/proc") -except Exception: - # Don't want to crash at import time. - traceback.print_exc() - scputimes = namedtuple('scputimes', 'user system idle')(0.0, 0.0, 0.0) - - -# ===================================================================== -# --- system memory -# ===================================================================== - - -def calculate_avail_vmem(mems): - """Fallback for kernels < 3.14 where /proc/meminfo does not provide - "MemAvailable:" column, see: - https://blog.famzah.net/2014/09/24/ - This code reimplements the algorithm outlined here: - https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/ - commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773 - - XXX: on recent kernels this calculation differs by ~1.5% than - "MemAvailable:" as it's calculated slightly differently, see: - https://gitlab.com/procps-ng/procps/issues/42 - https://github.com/famzah/linux-memavailable-procfs/issues/2 - It is still way more realistic than doing (free + cached) though. - """ - # Fallback for very old distros. According to - # https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/ - # commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773 - # ...long ago "avail" was calculated as (free + cached). - # We might fallback in such cases: - # "Active(file)" not available: 2.6.28 / Dec 2008 - # "Inactive(file)" not available: 2.6.28 / Dec 2008 - # "SReclaimable:" not available: 2.6.19 / Nov 2006 - # /proc/zoneinfo not available: 2.6.13 / Aug 2005 - free = mems[b'MemFree:'] - fallback = free + mems.get(b"Cached:", 0) - try: - lru_active_file = mems[b'Active(file):'] - lru_inactive_file = mems[b'Inactive(file):'] - slab_reclaimable = mems[b'SReclaimable:'] - except KeyError: - return fallback - try: - f = open_binary('%s/zoneinfo' % get_procfs_path()) - except IOError: - return fallback # kernel 2.6.13 - - watermark_low = 0 - with f: - for line in f: - line = line.strip() - if line.startswith(b'low'): - watermark_low += int(line.split()[1]) - watermark_low *= PAGESIZE - watermark_low = watermark_low - - avail = free - watermark_low - pagecache = lru_active_file + lru_inactive_file - pagecache -= min(pagecache / 2, watermark_low) - avail += pagecache - avail += slab_reclaimable - min(slab_reclaimable / 2.0, watermark_low) - return int(avail) - - -def virtual_memory(): - """Report virtual memory stats. - This implementation matches "free" and "vmstat -s" cmdline - utility values and procps-ng-3.3.12 source was used as a reference - (2016-09-18): - https://gitlab.com/procps-ng/procps/blob/ - 24fd2605c51fccc375ab0287cec33aa767f06718/proc/sysinfo.c - For reference, procps-ng-3.3.10 is the version available on Ubuntu - 16.04. - - Note about "available" memory: up until psutil 4.3 it was - calculated as "avail = (free + buffers + cached)". Now - "MemAvailable:" column (kernel 3.14) from /proc/meminfo is used as - it's more accurate. - That matches "available" column in newer versions of "free". - """ - missing_fields = [] - mems = {} - with open_binary('%s/meminfo' % get_procfs_path()) as f: - for line in f: - fields = line.split() - mems[fields[0]] = int(fields[1]) * 1024 - - # /proc doc states that the available fields in /proc/meminfo vary - # by architecture and compile options, but these 3 values are also - # returned by sysinfo(2); as such we assume they are always there. - total = mems[b'MemTotal:'] - free = mems[b'MemFree:'] - try: - buffers = mems[b'Buffers:'] - except KeyError: - # https://github.com/giampaolo/psutil/issues/1010 - buffers = 0 - missing_fields.append('buffers') - try: - cached = mems[b"Cached:"] - except KeyError: - cached = 0 - missing_fields.append('cached') - else: - # "free" cmdline utility sums reclaimable to cached. - # Older versions of procps used to add slab memory instead. - # This got changed in: - # https://gitlab.com/procps-ng/procps/commit/ - # 05d751c4f076a2f0118b914c5e51cfbb4762ad8e - cached += mems.get(b"SReclaimable:", 0) # since kernel 2.6.19 - - try: - shared = mems[b'Shmem:'] # since kernel 2.6.32 - except KeyError: - try: - shared = mems[b'MemShared:'] # kernels 2.4 - except KeyError: - shared = 0 - missing_fields.append('shared') - - try: - active = mems[b"Active:"] - except KeyError: - active = 0 - missing_fields.append('active') - - try: - inactive = mems[b"Inactive:"] - except KeyError: - try: - inactive = \ - mems[b"Inact_dirty:"] + \ - mems[b"Inact_clean:"] + \ - mems[b"Inact_laundry:"] - except KeyError: - inactive = 0 - missing_fields.append('inactive') - - try: - slab = mems[b"Slab:"] - except KeyError: - slab = 0 - - used = total - free - cached - buffers - if used < 0: - # May be symptomatic of running within a LCX container where such - # values will be dramatically distorted over those of the host. - used = total - free - - # - starting from 4.4.0 we match free's "available" column. - # Before 4.4.0 we calculated it as (free + buffers + cached) - # which matched htop. - # - free and htop available memory differs as per: - # http://askubuntu.com/a/369589 - # http://unix.stackexchange.com/a/65852/168884 - # - MemAvailable has been introduced in kernel 3.14 - try: - avail = mems[b'MemAvailable:'] - except KeyError: - avail = calculate_avail_vmem(mems) - - if avail < 0: - avail = 0 - missing_fields.append('available') - - # If avail is greater than total or our calculation overflows, - # that's symptomatic of running within a LCX container where such - # values will be dramatically distorted over those of the host. - # https://gitlab.com/procps-ng/procps/blob/ - # 24fd2605c51fccc375ab0287cec33aa767f06718/proc/sysinfo.c#L764 - if avail > total: - avail = free - - percent = usage_percent((total - avail), total, round_=1) - - # Warn about missing metrics which are set to 0. - if missing_fields: - msg = "%s memory stats couldn't be determined and %s set to 0" % ( - ", ".join(missing_fields), - "was" if len(missing_fields) == 1 else "were") - warnings.warn(msg, RuntimeWarning) - - return svmem(total, avail, percent, used, free, - active, inactive, buffers, cached, shared, slab) - - -def swap_memory(): - """Return swap memory metrics.""" - mems = {} - with open_binary('%s/meminfo' % get_procfs_path()) as f: - for line in f: - fields = line.split() - mems[fields[0]] = int(fields[1]) * 1024 - # We prefer /proc/meminfo over sysinfo() syscall so that - # psutil.PROCFS_PATH can be used in order to allow retrieval - # for linux containers, see: - # https://github.com/giampaolo/psutil/issues/1015 - try: - total = mems[b'SwapTotal:'] - free = mems[b'SwapFree:'] - except KeyError: - _, _, _, _, total, free, unit_multiplier = cext.linux_sysinfo() - total *= unit_multiplier - free *= unit_multiplier - - used = total - free - percent = usage_percent(used, total, round_=1) - # get pgin/pgouts - try: - f = open_binary("%s/vmstat" % get_procfs_path()) - except IOError as err: - # see https://github.com/giampaolo/psutil/issues/722 - msg = "'sin' and 'sout' swap memory stats couldn't " \ - "be determined and were set to 0 (%s)" % str(err) - warnings.warn(msg, RuntimeWarning) - sin = sout = 0 - else: - with f: - sin = sout = None - for line in f: - # values are expressed in 4 kilo bytes, we want - # bytes instead - if line.startswith(b'pswpin'): - sin = int(line.split(b' ')[1]) * 4 * 1024 - elif line.startswith(b'pswpout'): - sout = int(line.split(b' ')[1]) * 4 * 1024 - if sin is not None and sout is not None: - break - else: - # we might get here when dealing with exotic Linux - # flavors, see: - # https://github.com/giampaolo/psutil/issues/313 - msg = "'sin' and 'sout' swap memory stats couldn't " \ - "be determined and were set to 0" - warnings.warn(msg, RuntimeWarning) - sin = sout = 0 - return _common.sswap(total, used, free, percent, sin, sout) - - -# ===================================================================== -# --- CPU -# ===================================================================== - - -def cpu_times(): - """Return a named tuple representing the following system-wide - CPU times: - (user, nice, system, idle, iowait, irq, softirq [steal, [guest, - [guest_nice]]]) - Last 3 fields may not be available on all Linux kernel versions. - """ - procfs_path = get_procfs_path() - set_scputimes_ntuple(procfs_path) - with open_binary('%s/stat' % procfs_path) as f: - values = f.readline().split() - fields = values[1:len(scputimes._fields) + 1] - fields = [float(x) / CLOCK_TICKS for x in fields] - return scputimes(*fields) - - -def per_cpu_times(): - """Return a list of namedtuple representing the CPU times - for every CPU available on the system. - """ - procfs_path = get_procfs_path() - set_scputimes_ntuple(procfs_path) - cpus = [] - with open_binary('%s/stat' % procfs_path) as f: - # get rid of the first line which refers to system wide CPU stats - f.readline() - for line in f: - if line.startswith(b'cpu'): - values = line.split() - fields = values[1:len(scputimes._fields) + 1] - fields = [float(x) / CLOCK_TICKS for x in fields] - entry = scputimes(*fields) - cpus.append(entry) - return cpus - - -def cpu_count_logical(): - """Return the number of logical CPUs in the system.""" - try: - return os.sysconf("SC_NPROCESSORS_ONLN") - except ValueError: - # as a second fallback we try to parse /proc/cpuinfo - num = 0 - with open_binary('%s/cpuinfo' % get_procfs_path()) as f: - for line in f: - if line.lower().startswith(b'processor'): - num += 1 - - # unknown format (e.g. amrel/sparc architectures), see: - # https://github.com/giampaolo/psutil/issues/200 - # try to parse /proc/stat as a last resort - if num == 0: - search = re.compile(r'cpu\d') - with open_text('%s/stat' % get_procfs_path()) as f: - for line in f: - line = line.split(' ')[0] - if search.match(line): - num += 1 - - if num == 0: - # mimic os.cpu_count() - return None - return num - - -def cpu_count_physical(): - """Return the number of physical cores in the system.""" - # Method #1 - core_ids = set() - for path in glob.glob( - "/sys/devices/system/cpu/cpu[0-9]*/topology/core_id"): - with open_binary(path) as f: - core_ids.add(int(f.read())) - result = len(core_ids) - if result != 0: - return result - - # Method #2 - mapping = {} - current_info = {} - with open_binary('%s/cpuinfo' % get_procfs_path()) as f: - for line in f: - line = line.strip().lower() - if not line: - # new section - if (b'physical id' in current_info and - b'cpu cores' in current_info): - mapping[current_info[b'physical id']] = \ - current_info[b'cpu cores'] - current_info = {} - else: - # ongoing section - if (line.startswith(b'physical id') or - line.startswith(b'cpu cores')): - key, value = line.split(b'\t:', 1) - current_info[key] = int(value) - - result = sum(mapping.values()) - return result or None # mimic os.cpu_count() - - -def cpu_stats(): - """Return various CPU stats as a named tuple.""" - with open_binary('%s/stat' % get_procfs_path()) as f: - ctx_switches = None - interrupts = None - soft_interrupts = None - for line in f: - if line.startswith(b'ctxt'): - ctx_switches = int(line.split()[1]) - elif line.startswith(b'intr'): - interrupts = int(line.split()[1]) - elif line.startswith(b'softirq'): - soft_interrupts = int(line.split()[1]) - if ctx_switches is not None and soft_interrupts is not None \ - and interrupts is not None: - break - syscalls = 0 - return _common.scpustats( - ctx_switches, interrupts, soft_interrupts, syscalls) - - -if os.path.exists("/sys/devices/system/cpu/cpufreq/policy0") or \ - os.path.exists("/sys/devices/system/cpu/cpu0/cpufreq"): - def cpu_freq(): - """Return frequency metrics for all CPUs. - Contrarily to other OSes, Linux updates these values in - real-time. - """ - def get_path(num): - for p in ("/sys/devices/system/cpu/cpufreq/policy%s" % num, - "/sys/devices/system/cpu/cpu%s/cpufreq" % num): - if os.path.exists(p): - return p - - ret = [] - for n in range(cpu_count_logical()): - path = get_path(n) - if not path: - continue - - pjoin = os.path.join - curr = cat(pjoin(path, "scaling_cur_freq"), fallback=None) - if curr is None: - # Likely an old RedHat, see: - # https://github.com/giampaolo/psutil/issues/1071 - curr = cat(pjoin(path, "cpuinfo_cur_freq"), fallback=None) - if curr is None: - raise NotImplementedError( - "can't find current frequency file") - curr = int(curr) / 1000 - max_ = int(cat(pjoin(path, "scaling_max_freq"))) / 1000 - min_ = int(cat(pjoin(path, "scaling_min_freq"))) / 1000 - ret.append(_common.scpufreq(curr, min_, max_)) - return ret - -elif os.path.exists("/proc/cpuinfo"): - def cpu_freq(): - """Alternate implementation using /proc/cpuinfo. - min and max frequencies are not available and are set to None. - """ - ret = [] - with open_binary('%s/cpuinfo' % get_procfs_path()) as f: - for line in f: - if line.lower().startswith(b'cpu mhz'): - key, value = line.split(b'\t:', 1) - ret.append(_common.scpufreq(float(value), 0., 0.)) - return ret - -else: - def cpu_freq(): - """Dummy implementation when none of the above files are present. - """ - return [] - - -# ===================================================================== -# --- network -# ===================================================================== - - -net_if_addrs = cext_posix.net_if_addrs - - -class _Ipv6UnsupportedError(Exception): - pass - - -class Connections: - """A wrapper on top of /proc/net/* files, retrieving per-process - and system-wide open connections (TCP, UDP, UNIX) similarly to - "netstat -an". - - Note: in case of UNIX sockets we're only able to determine the - local endpoint/path, not the one it's connected to. - According to [1] it would be possible but not easily. - - [1] http://serverfault.com/a/417946 - """ - - def __init__(self): - tcp4 = ("tcp", socket.AF_INET, socket.SOCK_STREAM) - tcp6 = ("tcp6", socket.AF_INET6, socket.SOCK_STREAM) - udp4 = ("udp", socket.AF_INET, socket.SOCK_DGRAM) - udp6 = ("udp6", socket.AF_INET6, socket.SOCK_DGRAM) - unix = ("unix", socket.AF_UNIX, None) - self.tmap = { - "all": (tcp4, tcp6, udp4, udp6, unix), - "tcp": (tcp4, tcp6), - "tcp4": (tcp4,), - "tcp6": (tcp6,), - "udp": (udp4, udp6), - "udp4": (udp4,), - "udp6": (udp6,), - "unix": (unix,), - "inet": (tcp4, tcp6, udp4, udp6), - "inet4": (tcp4, udp4), - "inet6": (tcp6, udp6), - } - self._procfs_path = None - - def get_proc_inodes(self, pid): - inodes = defaultdict(list) - for fd in os.listdir("%s/%s/fd" % (self._procfs_path, pid)): - try: - inode = readlink("%s/%s/fd/%s" % (self._procfs_path, pid, fd)) - except (FileNotFoundError, ProcessLookupError): - # ENOENT == file which is gone in the meantime; - # os.stat('/proc/%s' % self.pid) will be done later - # to force NSP (if it's the case) - continue - except OSError as err: - if err.errno == errno.EINVAL: - # not a link - continue - raise - else: - if inode.startswith('socket:['): - # the process is using a socket - inode = inode[8:][:-1] - inodes[inode].append((pid, int(fd))) - return inodes - - def get_all_inodes(self): - inodes = {} - for pid in pids(): - try: - inodes.update(self.get_proc_inodes(pid)) - except (FileNotFoundError, ProcessLookupError, PermissionError): - # os.listdir() is gonna raise a lot of access denied - # exceptions in case of unprivileged user; that's fine - # as we'll just end up returning a connection with PID - # and fd set to None anyway. - # Both netstat -an and lsof does the same so it's - # unlikely we can do any better. - # ENOENT just means a PID disappeared on us. - continue - return inodes - - @staticmethod - def decode_address(addr, family): - """Accept an "ip:port" address as displayed in /proc/net/* - and convert it into a human readable form, like: - - "0500000A:0016" -> ("10.0.0.5", 22) - "0000000000000000FFFF00000100007F:9E49" -> ("::ffff:127.0.0.1", 40521) - - The IP address portion is a little or big endian four-byte - hexadecimal number; that is, the least significant byte is listed - first, so we need to reverse the order of the bytes to convert it - to an IP address. - The port is represented as a two-byte hexadecimal number. - - Reference: - http://linuxdevcenter.com/pub/a/linux/2000/11/16/LinuxAdmin.html - """ - ip, port = addr.split(':') - port = int(port, 16) - # this usually refers to a local socket in listen mode with - # no end-points connected - if not port: - return () - if PY3: - ip = ip.encode('ascii') - if family == socket.AF_INET: - # see: https://github.com/giampaolo/psutil/issues/201 - if LITTLE_ENDIAN: - ip = socket.inet_ntop(family, base64.b16decode(ip)[::-1]) - else: - ip = socket.inet_ntop(family, base64.b16decode(ip)) - else: # IPv6 - # old version - let's keep it, just in case... - # ip = ip.decode('hex') - # return socket.inet_ntop(socket.AF_INET6, - # ''.join(ip[i:i+4][::-1] for i in xrange(0, 16, 4))) - ip = base64.b16decode(ip) - try: - # see: https://github.com/giampaolo/psutil/issues/201 - if LITTLE_ENDIAN: - ip = socket.inet_ntop( - socket.AF_INET6, - struct.pack('>4I', *struct.unpack('<4I', ip))) - else: - ip = socket.inet_ntop( - socket.AF_INET6, - struct.pack('<4I', *struct.unpack('<4I', ip))) - except ValueError: - # see: https://github.com/giampaolo/psutil/issues/623 - if not supports_ipv6(): - raise _Ipv6UnsupportedError - else: - raise - return _common.addr(ip, port) - - @staticmethod - def process_inet(file, family, type_, inodes, filter_pid=None): - """Parse /proc/net/tcp* and /proc/net/udp* files.""" - if file.endswith('6') and not os.path.exists(file): - # IPv6 not supported - return - with open_text(file, buffering=BIGFILE_BUFFERING) as f: - f.readline() # skip the first line - for lineno, line in enumerate(f, 1): - try: - _, laddr, raddr, status, _, _, _, _, _, inode = \ - line.split()[:10] - except ValueError: - raise RuntimeError( - "error while parsing %s; malformed line %s %r" % ( - file, lineno, line)) - if inode in inodes: - # # We assume inet sockets are unique, so we error - # # out if there are multiple references to the - # # same inode. We won't do this for UNIX sockets. - # if len(inodes[inode]) > 1 and family != socket.AF_UNIX: - # raise ValueError("ambiguos inode with multiple " - # "PIDs references") - pid, fd = inodes[inode][0] - else: - pid, fd = None, -1 - if filter_pid is not None and filter_pid != pid: - continue - else: - if type_ == socket.SOCK_STREAM: - status = TCP_STATUSES[status] - else: - status = _common.CONN_NONE - try: - laddr = Connections.decode_address(laddr, family) - raddr = Connections.decode_address(raddr, family) - except _Ipv6UnsupportedError: - continue - yield (fd, family, type_, laddr, raddr, status, pid) - - @staticmethod - def process_unix(file, family, inodes, filter_pid=None): - """Parse /proc/net/unix files.""" - with open_text(file, buffering=BIGFILE_BUFFERING) as f: - f.readline() # skip the first line - for line in f: - tokens = line.split() - try: - _, _, _, _, type_, _, inode = tokens[0:7] - except ValueError: - if ' ' not in line: - # see: https://github.com/giampaolo/psutil/issues/766 - continue - raise RuntimeError( - "error while parsing %s; malformed line %r" % ( - file, line)) - if inode in inodes: - # With UNIX sockets we can have a single inode - # referencing many file descriptors. - pairs = inodes[inode] - else: - pairs = [(None, -1)] - for pid, fd in pairs: - if filter_pid is not None and filter_pid != pid: - continue - else: - if len(tokens) == 8: - path = tokens[-1] - else: - path = "" - type_ = _common.socktype_to_enum(int(type_)) - # XXX: determining the remote endpoint of a - # UNIX socket on Linux is not possible, see: - # https://serverfault.com/questions/252723/ - raddr = "" - status = _common.CONN_NONE - yield (fd, family, type_, path, raddr, status, pid) - - def retrieve(self, kind, pid=None): - if kind not in self.tmap: - raise ValueError("invalid %r kind argument; choose between %s" - % (kind, ', '.join([repr(x) for x in self.tmap]))) - self._procfs_path = get_procfs_path() - if pid is not None: - inodes = self.get_proc_inodes(pid) - if not inodes: - # no connections for this process - return [] - else: - inodes = self.get_all_inodes() - ret = set() - for f, family, type_ in self.tmap[kind]: - if family in (socket.AF_INET, socket.AF_INET6): - ls = self.process_inet( - "%s/net/%s" % (self._procfs_path, f), - family, type_, inodes, filter_pid=pid) - else: - ls = self.process_unix( - "%s/net/%s" % (self._procfs_path, f), - family, inodes, filter_pid=pid) - for fd, family, type_, laddr, raddr, status, bound_pid in ls: - if pid: - conn = _common.pconn(fd, family, type_, laddr, raddr, - status) - else: - conn = _common.sconn(fd, family, type_, laddr, raddr, - status, bound_pid) - ret.add(conn) - return list(ret) - - -_connections = Connections() - - -def net_connections(kind='inet'): - """Return system-wide open connections.""" - return _connections.retrieve(kind) - - -def net_io_counters(): - """Return network I/O statistics for every network interface - installed on the system as a dict of raw tuples. - """ - with open_text("%s/net/dev" % get_procfs_path()) as f: - lines = f.readlines() - retdict = {} - for line in lines[2:]: - colon = line.rfind(':') - assert colon > 0, repr(line) - name = line[:colon].strip() - fields = line[colon + 1:].strip().split() - - # in - (bytes_recv, - packets_recv, - errin, - dropin, - fifoin, # unused - framein, # unused - compressedin, # unused - multicastin, # unused - # out - bytes_sent, - packets_sent, - errout, - dropout, - fifoout, # unused - collisionsout, # unused - carrierout, # unused - compressedout) = map(int, fields) - - retdict[name] = (bytes_sent, bytes_recv, packets_sent, packets_recv, - errin, errout, dropin, dropout) - return retdict - - -def net_if_stats(): - """Get NIC stats (isup, duplex, speed, mtu).""" - duplex_map = {cext.DUPLEX_FULL: NIC_DUPLEX_FULL, - cext.DUPLEX_HALF: NIC_DUPLEX_HALF, - cext.DUPLEX_UNKNOWN: NIC_DUPLEX_UNKNOWN} - names = net_io_counters().keys() - ret = {} - for name in names: - try: - mtu = cext_posix.net_if_mtu(name) - isup = cext_posix.net_if_flags(name) - duplex, speed = cext.net_if_duplex_speed(name) - except OSError as err: - # https://github.com/giampaolo/psutil/issues/1279 - if err.errno != errno.ENODEV: - raise - else: - ret[name] = _common.snicstats(isup, duplex_map[duplex], speed, mtu) - return ret - - -# ===================================================================== -# --- disks -# ===================================================================== - - -disk_usage = _psposix.disk_usage - - -def disk_io_counters(perdisk=False): - """Return disk I/O statistics for every disk installed on the - system as a dict of raw tuples. - """ - def read_procfs(): - # OK, this is a bit confusing. The format of /proc/diskstats can - # have 3 variations. - # On Linux 2.4 each line has always 15 fields, e.g.: - # "3 0 8 hda 8 8 8 8 8 8 8 8 8 8 8" - # On Linux 2.6+ each line *usually* has 14 fields, and the disk - # name is in another position, like this: - # "3 0 hda 8 8 8 8 8 8 8 8 8 8 8" - # ...unless (Linux 2.6) the line refers to a partition instead - # of a disk, in which case the line has less fields (7): - # "3 1 hda1 8 8 8 8" - # 4.18+ has 4 fields added: - # "3 0 hda 8 8 8 8 8 8 8 8 8 8 8 0 0 0 0" - # See: - # https://www.kernel.org/doc/Documentation/iostats.txt - # https://www.kernel.org/doc/Documentation/ABI/testing/procfs-diskstats - with open_text("%s/diskstats" % get_procfs_path()) as f: - lines = f.readlines() - for line in lines: - fields = line.split() - flen = len(fields) - if flen == 15: - # Linux 2.4 - name = fields[3] - reads = int(fields[2]) - (reads_merged, rbytes, rtime, writes, writes_merged, - wbytes, wtime, _, busy_time, _) = map(int, fields[4:14]) - elif flen == 14 or flen == 18: - # Linux 2.6+, line referring to a disk - name = fields[2] - (reads, reads_merged, rbytes, rtime, writes, writes_merged, - wbytes, wtime, _, busy_time, _) = map(int, fields[3:14]) - elif flen == 7: - # Linux 2.6+, line referring to a partition - name = fields[2] - reads, rbytes, writes, wbytes = map(int, fields[3:]) - rtime = wtime = reads_merged = writes_merged = busy_time = 0 - else: - raise ValueError("not sure how to interpret line %r" % line) - yield (name, reads, writes, rbytes, wbytes, rtime, wtime, - reads_merged, writes_merged, busy_time) - - def read_sysfs(): - for block in os.listdir('/sys/block'): - for root, _, files in os.walk(os.path.join('/sys/block', block)): - if 'stat' not in files: - continue - with open_text(os.path.join(root, 'stat')) as f: - fields = f.read().strip().split() - name = os.path.basename(root) - (reads, reads_merged, rbytes, rtime, writes, writes_merged, - wbytes, wtime, _, busy_time, _) = map(int, fields) - yield (name, reads, writes, rbytes, wbytes, rtime, - wtime, reads_merged, writes_merged, busy_time) - - if os.path.exists('%s/diskstats' % get_procfs_path()): - gen = read_procfs() - elif os.path.exists('/sys/block'): - gen = read_sysfs() - else: - raise NotImplementedError( - "%s/diskstats nor /sys/block filesystem are available on this " - "system" % get_procfs_path()) - - retdict = {} - for entry in gen: - (name, reads, writes, rbytes, wbytes, rtime, wtime, reads_merged, - writes_merged, busy_time) = entry - if not perdisk and not is_storage_device(name): - # perdisk=False means we want to calculate totals so we skip - # partitions (e.g. 'sda1', 'nvme0n1p1') and only include - # base disk devices (e.g. 'sda', 'nvme0n1'). Base disks - # include a total of all their partitions + some extra size - # of their own: - # $ cat /proc/diskstats - # 259 0 sda 10485760 ... - # 259 1 sda1 5186039 ... - # 259 1 sda2 5082039 ... - # See: - # https://github.com/giampaolo/psutil/pull/1313 - continue - - rbytes *= DISK_SECTOR_SIZE - wbytes *= DISK_SECTOR_SIZE - retdict[name] = (reads, writes, rbytes, wbytes, rtime, wtime, - reads_merged, writes_merged, busy_time) - - return retdict - - -def disk_partitions(all=False): - """Return mounted disk partitions as a list of namedtuples.""" - fstypes = set() - procfs_path = get_procfs_path() - with open_text("%s/filesystems" % procfs_path) as f: - for line in f: - line = line.strip() - if not line.startswith("nodev"): - fstypes.add(line.strip()) - else: - # ignore all lines starting with "nodev" except "nodev zfs" - fstype = line.split("\t")[1] - if fstype == "zfs": - fstypes.add("zfs") - - # See: https://github.com/giampaolo/psutil/issues/1307 - if procfs_path == "/proc" and os.path.isfile('/etc/mtab'): - mounts_path = os.path.realpath("/etc/mtab") - else: - mounts_path = os.path.realpath("%s/self/mounts" % procfs_path) - - retlist = [] - partitions = cext.disk_partitions(mounts_path) - for partition in partitions: - device, mountpoint, fstype, opts = partition - if device == 'none': - device = '' - if not all: - if device == '' or fstype not in fstypes: - continue - ntuple = _common.sdiskpart(device, mountpoint, fstype, opts) - retlist.append(ntuple) - return retlist - - -# ===================================================================== -# --- sensors -# ===================================================================== - - -def sensors_temperatures(): - """Return hardware (CPU and others) temperatures as a dict - including hardware name, label, current, max and critical - temperatures. - - Implementation notes: - - /sys/class/hwmon looks like the most recent interface to - retrieve this info, and this implementation relies on it - only (old distros will probably use something else) - - lm-sensors on Ubuntu 16.04 relies on /sys/class/hwmon - - /sys/class/thermal/thermal_zone* is another one but it's more - difficult to parse - """ - ret = collections.defaultdict(list) - basenames = glob.glob('/sys/class/hwmon/hwmon*/temp*_*') - # CentOS has an intermediate /device directory: - # https://github.com/giampaolo/psutil/issues/971 - # https://github.com/nicolargo/glances/issues/1060 - basenames.extend(glob.glob('/sys/class/hwmon/hwmon*/device/temp*_*')) - basenames = sorted(set([x.split('_')[0] for x in basenames])) - - for base in basenames: - try: - path = base + '_input' - current = float(cat(path)) / 1000.0 - path = os.path.join(os.path.dirname(base), 'name') - unit_name = cat(path, binary=False) - except (IOError, OSError, ValueError) as err: - # A lot of things can go wrong here, so let's just skip the - # whole entry. Sure thing is Linux's /sys/class/hwmon really - # is a stinky broken mess. - # https://github.com/giampaolo/psutil/issues/1009 - # https://github.com/giampaolo/psutil/issues/1101 - # https://github.com/giampaolo/psutil/issues/1129 - # https://github.com/giampaolo/psutil/issues/1245 - # https://github.com/giampaolo/psutil/issues/1323 - warnings.warn("ignoring %r for file %r" % (err, path), - RuntimeWarning) - continue - - high = cat(base + '_max', fallback=None) - critical = cat(base + '_crit', fallback=None) - label = cat(base + '_label', fallback='', binary=False) - - if high is not None: - try: - high = float(high) / 1000.0 - except ValueError: - high = None - if critical is not None: - try: - critical = float(critical) / 1000.0 - except ValueError: - critical = None - - ret[unit_name].append((label, current, high, critical)) - - # Indication that no sensors were detected in /sys/class/hwmon/ - if not basenames: - basenames = glob.glob('/sys/class/thermal/thermal_zone*') - basenames = sorted(set(basenames)) - - for base in basenames: - try: - path = os.path.join(base, 'temp') - current = float(cat(path)) / 1000.0 - path = os.path.join(base, 'type') - unit_name = cat(path, binary=False) - except (IOError, OSError, ValueError) as err: - warnings.warn("ignoring %r for file %r" % (err, path), - RuntimeWarning) - continue - - trip_paths = glob.glob(base + '/trip_point*') - trip_points = set(['_'.join( - os.path.basename(p).split('_')[0:3]) for p in trip_paths]) - critical = None - high = None - for trip_point in trip_points: - path = os.path.join(base, trip_point + "_type") - trip_type = cat(path, fallback='', binary=False) - if trip_type == 'critical': - critical = cat(os.path.join(base, trip_point + "_temp"), - fallback=None) - elif trip_type == 'high': - high = cat(os.path.join(base, trip_point + "_temp"), - fallback=None) - - if high is not None: - try: - high = float(high) / 1000.0 - except ValueError: - high = None - if critical is not None: - try: - critical = float(critical) / 1000.0 - except ValueError: - critical = None - - ret[unit_name].append(('', current, high, critical)) - - return dict(ret) - - -def sensors_fans(): - """Return hardware fans info (for CPU and other peripherals) as a - dict including hardware label and current speed. - - Implementation notes: - - /sys/class/hwmon looks like the most recent interface to - retrieve this info, and this implementation relies on it - only (old distros will probably use something else) - - lm-sensors on Ubuntu 16.04 relies on /sys/class/hwmon - """ - ret = collections.defaultdict(list) - basenames = glob.glob('/sys/class/hwmon/hwmon*/fan*_*') - if not basenames: - # CentOS has an intermediate /device directory: - # https://github.com/giampaolo/psutil/issues/971 - basenames = glob.glob('/sys/class/hwmon/hwmon*/device/fan*_*') - - basenames = sorted(set([x.split('_')[0] for x in basenames])) - for base in basenames: - try: - current = int(cat(base + '_input')) - except (IOError, OSError) as err: - warnings.warn("ignoring %r" % err, RuntimeWarning) - continue - unit_name = cat(os.path.join(os.path.dirname(base), 'name'), - binary=False) - label = cat(base + '_label', fallback='', binary=False) - ret[unit_name].append(_common.sfan(label, current)) - - return dict(ret) - - -def sensors_battery(): - """Return battery information. - Implementation note: it appears /sys/class/power_supply/BAT0/ - directory structure may vary and provide files with the same - meaning but under different names, see: - https://github.com/giampaolo/psutil/issues/966 - """ - null = object() - - def multi_cat(*paths): - """Attempt to read the content of multiple files which may - not exist. If none of them exist return None. - """ - for path in paths: - ret = cat(path, fallback=null) - if ret != null: - return int(ret) if ret.isdigit() else ret - return None - - bats = [x for x in os.listdir(POWER_SUPPLY_PATH) if x.startswith('BAT')] - if not bats: - return None - # Get the first available battery. Usually this is "BAT0", except - # some rare exceptions: - # https://github.com/giampaolo/psutil/issues/1238 - root = os.path.join(POWER_SUPPLY_PATH, sorted(bats)[0]) - - # Base metrics. - energy_now = multi_cat( - root + "/energy_now", - root + "/charge_now") - power_now = multi_cat( - root + "/power_now", - root + "/current_now") - energy_full = multi_cat( - root + "/energy_full", - root + "/charge_full") - if energy_now is None or power_now is None: - return None - - # Percent. If we have energy_full the percentage will be more - # accurate compared to reading /capacity file (float vs. int). - if energy_full is not None: - try: - percent = 100.0 * energy_now / energy_full - except ZeroDivisionError: - percent = 0.0 - else: - percent = int(cat(root + "/capacity", fallback=-1)) - if percent == -1: - return None - - # Is AC power cable plugged in? - # Note: AC0 is not always available and sometimes (e.g. CentOS7) - # it's called "AC". - power_plugged = None - online = multi_cat( - os.path.join(POWER_SUPPLY_PATH, "AC0/online"), - os.path.join(POWER_SUPPLY_PATH, "AC/online")) - if online is not None: - power_plugged = online == 1 - else: - status = cat(root + "/status", fallback="", binary=False).lower() - if status == "discharging": - power_plugged = False - elif status in ("charging", "full"): - power_plugged = True - - # Seconds left. - # Note to self: we may also calculate the charging ETA as per: - # https://github.com/thialfihar/dotfiles/blob/ - # 013937745fd9050c30146290e8f963d65c0179e6/bin/battery.py#L55 - if power_plugged: - secsleft = _common.POWER_TIME_UNLIMITED - else: - try: - secsleft = int(energy_now / power_now * 3600) - except ZeroDivisionError: - secsleft = _common.POWER_TIME_UNKNOWN - - return _common.sbattery(percent, secsleft, power_plugged) - - -# ===================================================================== -# --- other system functions -# ===================================================================== - - -def users(): - """Return currently connected users as a list of namedtuples.""" - retlist = [] - rawlist = cext.users() - 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 (':0.0', ':0'): - hostname = 'localhost' - nt = _common.suser(user, tty or None, hostname, tstamp, pid) - retlist.append(nt) - return retlist - - -def boot_time(): - """Return the system boot time expressed in seconds since the epoch.""" - global BOOT_TIME - path = '%s/stat' % get_procfs_path() - with open_binary(path) as f: - for line in f: - if line.startswith(b'btime'): - ret = float(line.strip().split()[1]) - BOOT_TIME = ret - return ret - raise RuntimeError( - "line 'btime' not found in %s" % path) - - -# ===================================================================== -# --- 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. Linux TIDs are not - supported (always return False). - """ - if not _psposix.pid_exists(pid): - return False - else: - # Linux's apparently does not distinguish between PIDs and TIDs - # (thread IDs). - # listdir("/proc") won't show any TID (only PIDs) but - # os.stat("/proc/{tid}") will succeed if {tid} exists. - # os.kill() can also be passed a TID. This is quite confusing. - # In here we want to enforce this distinction and support PIDs - # only, see: - # https://github.com/giampaolo/psutil/issues/687 - try: - # Note: already checked that this is faster than using a - # regular expr. Also (a lot) faster than doing - # 'return pid in pids()' - path = "%s/%s/status" % (get_procfs_path(), pid) - with open_binary(path) as f: - for line in f: - if line.startswith(b"Tgid:"): - tgid = int(line.split()[1]) - # If tgid and pid are the same then we're - # dealing with a process PID. - return tgid == pid - raise ValueError("'Tgid' line not found in %s" % path) - except (EnvironmentError, ValueError): - return pid in pids() - - -def ppid_map(): - """Obtain a {pid: ppid, ...} dict for all running processes in - one shot. Used to speed up Process.children(). - """ - ret = {} - procfs_path = get_procfs_path() - for pid in pids(): - try: - with open_binary("%s/%s/stat" % (procfs_path, pid)) as f: - data = f.read() - except (FileNotFoundError, ProcessLookupError): - # Note: we should be able to access /stat for all processes - # aka it's unlikely we'll bump into EPERM, which is good. - pass - else: - rpar = data.rfind(b')') - dset = data[rpar + 2:].split() - ppid = int(dset[1]) - ret[pid] = ppid - return ret - - -def wrap_exceptions(fun): - """Decorator which translates bare OSError and IOError exceptions - into NoSuchProcess and AccessDenied. - """ - @functools.wraps(fun) - def wrapper(self, *args, **kwargs): - try: - return fun(self, *args, **kwargs) - except PermissionError: - raise AccessDenied(self.pid, self._name) - except ProcessLookupError: - raise NoSuchProcess(self.pid, self._name) - except FileNotFoundError: - if not os.path.exists("%s/%s" % (self._procfs_path, self.pid)): - raise NoSuchProcess(self.pid, self._name) - # Note: zombies will keep existing under /proc until they're - # gone so there's no way to distinguish them in here. - raise - return wrapper - - -class Process(object): - """Linux process implementation.""" - - __slots__ = ["pid", "_name", "_ppid", "_procfs_path", "_cache"] - - def __init__(self, pid): - self.pid = pid - self._name = None - self._ppid = None - self._procfs_path = get_procfs_path() - - def _assert_alive(self): - """Raise NSP if the process disappeared on us.""" - # For those C function who do not raise NSP, possibly returning - # incorrect or incomplete result. - os.stat('%s/%s' % (self._procfs_path, self.pid)) - - @wrap_exceptions - @memoize_when_activated - def _parse_stat_file(self): - """Parse /proc/{pid}/stat file and return a dict with various - process info. - Using "man proc" as a reference: where "man proc" refers to - position N always substract 3 (e.g ppid position 4 in - 'man proc' == position 1 in here). - The return value is cached in case oneshot() ctx manager is - in use. - """ - with open_binary("%s/%s/stat" % (self._procfs_path, self.pid)) as f: - data = f.read() - # Process name is between parentheses. It can contain spaces and - # other parentheses. This is taken into account by looking for - # the first occurrence of "(" and the last occurence of ")". - rpar = data.rfind(b')') - name = data[data.find(b'(') + 1:rpar] - fields = data[rpar + 2:].split() - - ret = {} - ret['name'] = name - ret['status'] = fields[0] - ret['ppid'] = fields[1] - ret['ttynr'] = fields[4] - ret['utime'] = fields[11] - ret['stime'] = fields[12] - ret['children_utime'] = fields[13] - ret['children_stime'] = fields[14] - ret['create_time'] = fields[19] - ret['cpu_num'] = fields[36] - ret['blkio_ticks'] = fields[39] # aka 'delayacct_blkio_ticks' - - return ret - - @wrap_exceptions - @memoize_when_activated - def _read_status_file(self): - """Read /proc/{pid}/stat file and return its content. - The return value is cached in case oneshot() ctx manager is - in use. - """ - with open_binary("%s/%s/status" % (self._procfs_path, self.pid)) as f: - return f.read() - - @wrap_exceptions - @memoize_when_activated - def _read_smaps_file(self): - with open_binary("%s/%s/smaps" % (self._procfs_path, self.pid), - buffering=BIGFILE_BUFFERING) as f: - return f.read().strip() - - def oneshot_enter(self): - self._parse_stat_file.cache_activate(self) - self._read_status_file.cache_activate(self) - self._read_smaps_file.cache_activate(self) - - def oneshot_exit(self): - self._parse_stat_file.cache_deactivate(self) - self._read_status_file.cache_deactivate(self) - self._read_smaps_file.cache_deactivate(self) - - @wrap_exceptions - def name(self): - name = self._parse_stat_file()['name'] - if PY3: - name = decode(name) - # XXX - gets changed later and probably needs refactoring - return name - - def exe(self): - try: - return readlink("%s/%s/exe" % (self._procfs_path, self.pid)) - except (FileNotFoundError, ProcessLookupError): - # no such file error; might be raised also if the - # path actually exists for system processes with - # low pids (about 0-20) - if os.path.lexists("%s/%s" % (self._procfs_path, self.pid)): - return "" - else: - if not pid_exists(self.pid): - raise NoSuchProcess(self.pid, self._name) - else: - raise ZombieProcess(self.pid, self._name, self._ppid) - except PermissionError: - raise AccessDenied(self.pid, self._name) - - @wrap_exceptions - def cmdline(self): - with open_text("%s/%s/cmdline" % (self._procfs_path, self.pid)) as f: - data = f.read() - if not data: - # may happen in case of zombie process - return [] - # 'man proc' states that args are separated by null bytes '\0' - # and last char is supposed to be a null byte. Nevertheless - # some processes may change their cmdline after being started - # (via setproctitle() or similar), they are usually not - # compliant with this rule and use spaces instead. Google - # Chrome process is an example. See: - # https://github.com/giampaolo/psutil/issues/1179 - sep = '\x00' if data.endswith('\x00') else ' ' - if data.endswith(sep): - data = data[:-1] - cmdline = data.split(sep) - # Sometimes last char is a null byte '\0' but the args are - # separated by spaces, see: https://github.com/giampaolo/psutil/ - # issues/1179#issuecomment-552984549 - if sep == '\x00' and len(cmdline) == 1 and ' ' in data: - cmdline = data.split(' ') - return cmdline - - @wrap_exceptions - def environ(self): - with open_text("%s/%s/environ" % (self._procfs_path, self.pid)) as f: - data = f.read() - return parse_environ_block(data) - - @wrap_exceptions - def terminal(self): - tty_nr = int(self._parse_stat_file()['ttynr']) - tmap = _psposix.get_terminal_map() - try: - return tmap[tty_nr] - except KeyError: - return None - - # May not be available on old kernels. - if os.path.exists('/proc/%s/io' % os.getpid()): - @wrap_exceptions - def io_counters(self): - fname = "%s/%s/io" % (self._procfs_path, self.pid) - fields = {} - with open_binary(fname) as f: - for line in f: - # https://github.com/giampaolo/psutil/issues/1004 - line = line.strip() - if line: - try: - name, value = line.split(b': ') - except ValueError: - # https://github.com/giampaolo/psutil/issues/1004 - continue - else: - fields[name] = int(value) - if not fields: - raise RuntimeError("%s file was empty" % fname) - try: - return pio( - fields[b'syscr'], # read syscalls - fields[b'syscw'], # write syscalls - fields[b'read_bytes'], # read bytes - fields[b'write_bytes'], # write bytes - fields[b'rchar'], # read chars - fields[b'wchar'], # write chars - ) - except KeyError as err: - raise ValueError("%r field was not found in %s; found fields " - "are %r" % (err[0], fname, fields)) - - @wrap_exceptions - def cpu_times(self): - values = self._parse_stat_file() - utime = float(values['utime']) / CLOCK_TICKS - stime = float(values['stime']) / CLOCK_TICKS - children_utime = float(values['children_utime']) / CLOCK_TICKS - children_stime = float(values['children_stime']) / CLOCK_TICKS - iowait = float(values['blkio_ticks']) / CLOCK_TICKS - return pcputimes(utime, stime, children_utime, children_stime, iowait) - - @wrap_exceptions - def cpu_num(self): - """What CPU the process is on.""" - return int(self._parse_stat_file()['cpu_num']) - - @wrap_exceptions - def wait(self, timeout=None): - return _psposix.wait_pid(self.pid, timeout, self._name) - - @wrap_exceptions - def create_time(self): - ctime = float(self._parse_stat_file()['create_time']) - # According to documentation, starttime is in field 21 and the - # unit is jiffies (clock ticks). - # We first divide it for clock ticks and then add uptime returning - # seconds since the epoch, in UTC. - # Also use cached value if available. - bt = BOOT_TIME or boot_time() - return (ctime / CLOCK_TICKS) + bt - - @wrap_exceptions - def memory_info(self): - # ============================================================ - # | FIELD | DESCRIPTION | AKA | TOP | - # ============================================================ - # | rss | resident set size | | RES | - # | vms | total program size | size | VIRT | - # | shared | shared pages (from shared mappings) | | SHR | - # | text | text ('code') | trs | CODE | - # | lib | library (unused in Linux 2.6) | lrs | | - # | data | data + stack | drs | DATA | - # | dirty | dirty pages (unused in Linux 2.6) | dt | | - # ============================================================ - with open_binary("%s/%s/statm" % (self._procfs_path, self.pid)) as f: - vms, rss, shared, text, lib, data, dirty = \ - [int(x) * PAGESIZE for x in f.readline().split()[:7]] - return pmem(rss, vms, shared, text, lib, data, dirty) - - # /proc/pid/smaps does not exist on kernels < 2.6.14 or if - # CONFIG_MMU kernel configuration option is not enabled. - if HAS_SMAPS: - - @wrap_exceptions - def memory_full_info( - self, - # Gets Private_Clean, Private_Dirty, Private_Hugetlb. - _private_re=re.compile(br"\nPrivate.*:\s+(\d+)"), - _pss_re=re.compile(br"\nPss\:\s+(\d+)"), - _swap_re=re.compile(br"\nSwap\:\s+(\d+)")): - basic_mem = self.memory_info() - # Note: using 3 regexes is faster than reading the file - # line by line. - # XXX: on Python 3 the 2 regexes are 30% slower than on - # Python 2 though. Figure out why. - # - # You might be tempted to calculate USS by subtracting - # the "shared" value from the "resident" value in - # /proc//statm. But at least on Linux, statm's "shared" - # value actually counts pages backed by files, which has - # little to do with whether the pages are actually shared. - # /proc/self/smaps on the other hand appears to give us the - # correct information. - smaps_data = self._read_smaps_file() - # Note: smaps file can be empty for certain processes. - # The code below will not crash though and will result to 0. - uss = sum(map(int, _private_re.findall(smaps_data))) * 1024 - pss = sum(map(int, _pss_re.findall(smaps_data))) * 1024 - swap = sum(map(int, _swap_re.findall(smaps_data))) * 1024 - return pfullmem(*basic_mem + (uss, pss, swap)) - - else: - memory_full_info = memory_info - - if HAS_SMAPS: - - @wrap_exceptions - def memory_maps(self): - """Return process's mapped memory regions as a list of named - tuples. Fields are explained in 'man proc'; here is an updated - (Apr 2012) version: http://goo.gl/fmebo - - /proc/{PID}/smaps does not exist on kernels < 2.6.14 or if - CONFIG_MMU kernel configuration option is not enabled. - """ - def get_blocks(lines, current_block): - data = {} - for line in lines: - fields = line.split(None, 5) - if not fields[0].endswith(b':'): - # new block section - yield (current_block.pop(), data) - current_block.append(line) - else: - try: - data[fields[0]] = int(fields[1]) * 1024 - except ValueError: - if fields[0].startswith(b'VmFlags:'): - # see issue #369 - continue - else: - raise ValueError("don't know how to inte" - "rpret line %r" % line) - yield (current_block.pop(), data) - - data = self._read_smaps_file() - # Note: smaps file can be empty for certain processes. - if not data: - return [] - lines = data.split(b'\n') - ls = [] - first_line = lines.pop(0) - current_block = [first_line] - for header, data in get_blocks(lines, current_block): - hfields = header.split(None, 5) - try: - addr, perms, offset, dev, inode, path = hfields - except ValueError: - addr, perms, offset, dev, inode, path = \ - hfields + [''] - if not path: - path = '[anon]' - else: - if PY3: - path = decode(path) - path = path.strip() - if (path.endswith(' (deleted)') and not - path_exists_strict(path)): - path = path[:-10] - ls.append(( - decode(addr), decode(perms), path, - data[b'Rss:'], - data.get(b'Size:', 0), - data.get(b'Pss:', 0), - data.get(b'Shared_Clean:', 0), - data.get(b'Shared_Dirty:', 0), - data.get(b'Private_Clean:', 0), - data.get(b'Private_Dirty:', 0), - data.get(b'Referenced:', 0), - data.get(b'Anonymous:', 0), - data.get(b'Swap:', 0) - )) - return ls - - @wrap_exceptions - def cwd(self): - try: - return readlink("%s/%s/cwd" % (self._procfs_path, self.pid)) - except (FileNotFoundError, ProcessLookupError): - # https://github.com/giampaolo/psutil/issues/986 - if not pid_exists(self.pid): - raise NoSuchProcess(self.pid, self._name) - else: - raise ZombieProcess(self.pid, self._name, self._ppid) - - @wrap_exceptions - def num_ctx_switches(self, - _ctxsw_re=re.compile(br'ctxt_switches:\t(\d+)')): - data = self._read_status_file() - ctxsw = _ctxsw_re.findall(data) - if not ctxsw: - raise NotImplementedError( - "'voluntary_ctxt_switches' and 'nonvoluntary_ctxt_switches'" - "lines were not found in %s/%s/status; the kernel is " - "probably older than 2.6.23" % ( - self._procfs_path, self.pid)) - else: - return _common.pctxsw(int(ctxsw[0]), int(ctxsw[1])) - - @wrap_exceptions - def num_threads(self, _num_threads_re=re.compile(br'Threads:\t(\d+)')): - # Note: on Python 3 using a re is faster than iterating over file - # line by line. On Python 2 is the exact opposite, and iterating - # over a file on Python 3 is slower than on Python 2. - data = self._read_status_file() - return int(_num_threads_re.findall(data)[0]) - - @wrap_exceptions - def threads(self): - thread_ids = os.listdir("%s/%s/task" % (self._procfs_path, self.pid)) - thread_ids.sort() - retlist = [] - hit_enoent = False - for thread_id in thread_ids: - fname = "%s/%s/task/%s/stat" % ( - self._procfs_path, self.pid, thread_id) - try: - with open_binary(fname) as f: - st = f.read().strip() - except FileNotFoundError: - # no such file or directory; it means thread - # disappeared on us - hit_enoent = True - continue - # ignore the first two values ("pid (exe)") - st = st[st.find(b')') + 2:] - values = st.split(b' ') - utime = float(values[11]) / CLOCK_TICKS - stime = float(values[12]) / CLOCK_TICKS - ntuple = _common.pthread(int(thread_id), utime, stime) - retlist.append(ntuple) - if hit_enoent: - self._assert_alive() - return retlist - - @wrap_exceptions - def nice_get(self): - # with open_text('%s/%s/stat' % (self._procfs_path, self.pid)) as f: - # data = f.read() - # return int(data.split()[18]) - - # Use C implementation - return cext_posix.getpriority(self.pid) - - @wrap_exceptions - def nice_set(self, value): - return cext_posix.setpriority(self.pid, value) - - # starting from CentOS 6. - if HAS_CPU_AFFINITY: - - @wrap_exceptions - def cpu_affinity_get(self): - return cext.proc_cpu_affinity_get(self.pid) - - def _get_eligible_cpus( - self, _re=re.compile(br"Cpus_allowed_list:\t(\d+)-(\d+)")): - # See: https://github.com/giampaolo/psutil/issues/956 - data = self._read_status_file() - match = _re.findall(data) - if match: - return list(range(int(match[0][0]), int(match[0][1]) + 1)) - else: - return list(range(len(per_cpu_times()))) - - @wrap_exceptions - def cpu_affinity_set(self, cpus): - try: - cext.proc_cpu_affinity_set(self.pid, cpus) - except (OSError, ValueError) as err: - if isinstance(err, ValueError) or err.errno == errno.EINVAL: - eligible_cpus = self._get_eligible_cpus() - all_cpus = tuple(range(len(per_cpu_times()))) - for cpu in cpus: - if cpu not in all_cpus: - raise ValueError( - "invalid CPU number %r; choose between %s" % ( - cpu, eligible_cpus)) - if cpu not in eligible_cpus: - raise ValueError( - "CPU number %r is not eligible; choose " - "between %s" % (cpu, eligible_cpus)) - raise - - # only starting from kernel 2.6.13 - if HAS_PROC_IO_PRIORITY: - - @wrap_exceptions - def ionice_get(self): - ioclass, value = cext.proc_ioprio_get(self.pid) - if enum is not None: - ioclass = IOPriority(ioclass) - return _common.pionice(ioclass, value) - - @wrap_exceptions - def ionice_set(self, ioclass, value): - if value is None: - value = 0 - if value and ioclass in (IOPRIO_CLASS_IDLE, IOPRIO_CLASS_NONE): - raise ValueError("%r ioclass accepts no value" % ioclass) - if value < 0 or value > 7: - raise ValueError("value not in 0-7 range") - return cext.proc_ioprio_set(self.pid, ioclass, value) - - if HAS_PRLIMIT: - - @wrap_exceptions - def rlimit(self, resource, limits=None): - # If pid is 0 prlimit() applies to the calling process and - # we don't want that. We should never get here though as - # PID 0 is not supported on Linux. - if self.pid == 0: - raise ValueError("can't use prlimit() against PID 0 process") - try: - if limits is None: - # get - return cext.linux_prlimit(self.pid, resource) - else: - # set - if len(limits) != 2: - raise ValueError( - "second argument must be a (soft, hard) tuple, " - "got %s" % repr(limits)) - soft, hard = limits - cext.linux_prlimit(self.pid, resource, soft, hard) - except OSError as err: - if err.errno == errno.ENOSYS and pid_exists(self.pid): - # I saw this happening on Travis: - # https://travis-ci.org/giampaolo/psutil/jobs/51368273 - raise ZombieProcess(self.pid, self._name, self._ppid) - else: - raise - - @wrap_exceptions - def status(self): - letter = self._parse_stat_file()['status'] - if PY3: - letter = letter.decode() - # XXX is '?' legit? (we're not supposed to return it anyway) - return PROC_STATUSES.get(letter, '?') - - @wrap_exceptions - def open_files(self): - retlist = [] - files = os.listdir("%s/%s/fd" % (self._procfs_path, self.pid)) - hit_enoent = False - for fd in files: - file = "%s/%s/fd/%s" % (self._procfs_path, self.pid, fd) - try: - path = readlink(file) - except (FileNotFoundError, ProcessLookupError): - # ENOENT == file which is gone in the meantime - hit_enoent = True - continue - except OSError as err: - if err.errno == errno.EINVAL: - # not a link - continue - raise - else: - # If path is not an absolute there's no way to tell - # whether it's a regular file or not, so we skip it. - # A regular file is always supposed to be have an - # absolute path though. - if path.startswith('/') and isfile_strict(path): - # Get file position and flags. - file = "%s/%s/fdinfo/%s" % ( - self._procfs_path, self.pid, fd) - try: - with open_binary(file) as f: - pos = int(f.readline().split()[1]) - flags = int(f.readline().split()[1], 8) - except FileNotFoundError: - # fd gone in the meantime; process may - # still be alive - hit_enoent = True - else: - mode = file_flags_to_mode(flags) - ntuple = popenfile( - path, int(fd), int(pos), mode, flags) - retlist.append(ntuple) - if hit_enoent: - self._assert_alive() - return retlist - - @wrap_exceptions - def connections(self, kind='inet'): - ret = _connections.retrieve(kind, self.pid) - self._assert_alive() - return ret - - @wrap_exceptions - def num_fds(self): - return len(os.listdir("%s/%s/fd" % (self._procfs_path, self.pid))) - - @wrap_exceptions - def ppid(self): - return int(self._parse_stat_file()['ppid']) - - @wrap_exceptions - def uids(self, _uids_re=re.compile(br'Uid:\t(\d+)\t(\d+)\t(\d+)')): - data = self._read_status_file() - real, effective, saved = _uids_re.findall(data)[0] - return _common.puids(int(real), int(effective), int(saved)) - - @wrap_exceptions - def gids(self, _gids_re=re.compile(br'Gid:\t(\d+)\t(\d+)\t(\d+)')): - data = self._read_status_file() - real, effective, saved = _gids_re.findall(data)[0] - return _common.pgids(int(real), int(effective), int(saved)) diff --git a/ddtrace/vendor/psutil/_psosx.py b/ddtrace/vendor/psutil/_psosx.py deleted file mode 100644 index 7f28447bb18..00000000000 --- a/ddtrace/vendor/psutil/_psosx.py +++ /dev/null @@ -1,568 +0,0 @@ -# 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. - -"""macOS platform implementation.""" - -import contextlib -import errno -import functools -import os -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 conn_tmap -from ._common import conn_to_ntuple -from ._common import isfile_strict -from ._common import memoize_when_activated -from ._common import parse_environ_block -from ._compat import PermissionError -from ._compat import ProcessLookupError -from ._common import usage_percent - - -__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, -) - -# These objects get set on "import psutil" from the __init__.py -# file, see: https://github.com/giampaolo/psutil/issues/1402 -NoSuchProcess = None -ZombieProcess = None -AccessDenied = None -TimeoutExpired = None - - -# ===================================================================== -# --- 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', )) - - -# ===================================================================== -# --- memory -# ===================================================================== - - -def virtual_memory(): - """System virtual memory as a namedtuple.""" - total, active, inactive, wired, free, speculative = cext.virtual_mem() - # This is how Zabbix calculate avail and used mem: - # https://github.com/zabbix/zabbix/blob/trunk/src/libs/zbxsysinfo/ - # osx/memory.c - # Also see: https://github.com/giampaolo/psutil/issues/1277 - avail = inactive + free - used = active + wired - # This is NOT how Zabbix calculates free mem but it matches "free" - # cmdline utility. - free -= speculative - 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 macOS 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 macOS 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: - try: - mtu = cext_posix.net_if_mtu(name) - isup = cext_posix.net_if_flags(name) - duplex, speed = cext_posix.net_if_duplex_speed(name) - except OSError as err: - # https://github.com/giampaolo/psutil/issues/1279 - if err.errno != errno.ENODEV: - raise - else: - 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 macOS 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.insert(0, 0) - except NoSuchProcess: - pass - except AccessDenied: - ls.insert(0, 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 ProcessLookupError: - raise NoSuchProcess(self.pid, self._name) - except PermissionError: - raise AccessDenied(self.pid, self._name) - except cext.ZombieProcessError: - raise ZombieProcess(self.pid, self._name, self._ppid) - 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", "_cache"] - - def __init__(self, pid): - self.pid = pid - self._name = None - self._ppid = None - - @wrap_exceptions - @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 - - @wrap_exceptions - @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) - self._get_pidtaskinfo.cache_activate(self) - - def oneshot_exit(self): - self._get_kinfo_proc.cache_deactivate(self) - self._get_pidtaskinfo.cache_deactivate(self) - - @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 - nt = conn_to_ntuple(fd, fam, type, laddr, raddr, status, - TCP_STATUSES) - 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): - 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 diff --git a/ddtrace/vendor/psutil/_psposix.py b/ddtrace/vendor/psutil/_psposix.py deleted file mode 100644 index 24570224fe9..00000000000 --- a/ddtrace/vendor/psutil/_psposix.py +++ /dev/null @@ -1,179 +0,0 @@ -# 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 glob -import os -import sys -import time - -from ._common import memoize -from ._common import sdiskusage -from ._common import usage_percent -from ._compat import ChildProcessError -from ._compat import FileNotFoundError -from ._compat import InterruptedError -from ._compat import PermissionError -from ._compat import ProcessLookupError -from ._compat import PY3 -from ._compat import unicode - - -__all__ = ['pid_exists', 'wait_pid', 'disk_usage', 'get_terminal_map'] - - -# This object gets set on "import psutil" from the __init__.py -# file, see: https://github.com/giampaolo/psutil/issues/1402 -TimeoutExpired = None - - -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 <> 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 ProcessLookupError: - return False - except PermissionError: - # EPERM clearly means there's a process to deny access to - return True - # According to "man 2 kill" possible error values are - # (EINVAL, EPERM, ESRCH) - 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 InterruptedError: - delay = check_timeout(delay) - except ChildProcessError: - # 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: - 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 FileNotFoundError: - pass - return ret diff --git a/ddtrace/vendor/psutil/_pssunos.py b/ddtrace/vendor/psutil/_pssunos.py deleted file mode 100644 index 2aa2a86615d..00000000000 --- a/ddtrace/vendor/psutil/_pssunos.py +++ /dev/null @@ -1,720 +0,0 @@ -# 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 functools -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 get_procfs_path -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 FileNotFoundError -from ._compat import PermissionError -from ._compat import ProcessLookupError -from ._compat import PY3 - - -__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, - uid=8, - euid=9, - gid=10, - egid=11) - -# These objects get set on "import psutil" from the __init__.py -# file, see: https://github.com/giampaolo/psutil/issues/1402 -NoSuchProcess = None -ZombieProcess = None -AccessDenied = None -TimeoutExpired = None - - -# ===================================================================== -# --- 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)) - - -# ===================================================================== -# --- 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 - # TODO: refactor and use _common.conn_to_ntuple. - 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. - """ - @functools.wraps(fun) - def wrapper(self, *args, **kwargs): - try: - return fun(self, *args, **kwargs) - except (FileNotFoundError, ProcessLookupError): - # 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 not pid_exists(self.pid): - raise NoSuchProcess(self.pid, self._name) - else: - raise ZombieProcess(self.pid, self._name, self._ppid) - except PermissionError: - raise AccessDenied(self.pid, self._name) - except OSError: - if self.pid == 0: - if 0 in pids(): - raise AccessDenied(self.pid, self._name) - else: - raise - raise - return wrapper - - -class Process(object): - """Wrapper class around underlying C implementation.""" - - __slots__ = ["pid", "_name", "_ppid", "_procfs_path", "_cache"] - - def __init__(self, pid): - self.pid = pid - self._name = None - self._ppid = None - self._procfs_path = get_procfs_path() - - def _assert_alive(self): - """Raise NSP if the process disappeared on us.""" - # For those C function who do not raise NSP, possibly returning - # incorrect or incomplete result. - os.stat('%s/%s' % (self._procfs_path, self.pid)) - - def oneshot_enter(self): - self._proc_name_and_args.cache_activate(self) - self._proc_basic_info.cache_activate(self) - self._proc_cred.cache_activate(self) - - def oneshot_exit(self): - self._proc_name_and_args.cache_deactivate(self) - self._proc_basic_info.cache_deactivate(self) - self._proc_cred.cache_deactivate(self) - - @wrap_exceptions - @memoize_when_activated - def _proc_name_and_args(self): - return cext.proc_name_and_args(self.pid, self._procfs_path) - - @wrap_exceptions - @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 - - @wrap_exceptions - @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: getpriority(3) doesn't work for realtime processes. - # Psinfo is what ps uses, see: - # https://github.com/giampaolo/psutil/issues/1194 - return self._proc_basic_info()[proc_info_map['nice']] - - @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): - try: - real, effective, saved, _, _, _ = self._proc_cred() - except AccessDenied: - real = self._proc_basic_info()[proc_info_map['uid']] - effective = self._proc_basic_info()[proc_info_map['euid']] - saved = None - return _common.puids(real, effective, saved) - - @wrap_exceptions - def gids(self): - try: - _, _, _, real, effective, saved = self._proc_cred() - except AccessDenied: - real = self._proc_basic_info()[proc_info_map['gid']] - effective = self._proc_basic_info()[proc_info_map['egid']] - saved = None - 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 FileNotFoundError: - hit_enoent = True - continue - if hit_enoent: - self._assert_alive() - - @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 FileNotFoundError: - os.stat("%s/%s" % (procfs_path, self.pid)) # raise NSP or AD - return None - - @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: - self._assert_alive() - 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 FileNotFoundError: - hit_enoent = True - continue - else: - if isfile_strict(file): - retlist.append(_common.popenfile(file, int(fd))) - if hit_enoent: - self._assert_alive() - 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: - self._assert_alive() - 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) diff --git a/ddtrace/vendor/psutil/_psutil_aix.c b/ddtrace/vendor/psutil/_psutil_aix.c deleted file mode 100644 index 9f58f606b0c..00000000000 --- a/ddtrace/vendor/psutil/_psutil_aix.c +++ /dev/null @@ -1,1137 +0,0 @@ -/* - * 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 support is experimental at this time. - * The following functions and methods are unsupported on the AIX platform: - * - psutil.Process.memory_maps - * - * Known limitations: - * - psutil.Process.io_counters read count is always 0 - * - psutil.Process.io_counters may not be available on older AIX versions - * - psutil.Process.threads may not be available on older AIX versions - # - psutil.net_io_counters may not be available on older AIX versions - * - reading basic process info may fail or return incorrect values when - * process is starting (see IBM APAR IV58499 - fixed in newer AIX versions) - * - sockets and pipes may not be counted in num_fds (fixed in newer AIX - * versions) - * - * Useful resources: - * - proc filesystem: http://www-01.ibm.com/support/knowledgecenter/ - * ssw_aix_72/com.ibm.aix.files/proc.htm - * - libperfstat: http://www-01.ibm.com/support/knowledgecenter/ - * ssw_aix_72/com.ibm.aix.files/libperfstat.h.htm - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "arch/aix/ifaddrs.h" -#include "arch/aix/net_connections.h" -#include "arch/aix/common.h" -#include "_psutil_common.h" -#include "_psutil_posix.h" - - -#define TV2DOUBLE(t) (((t).tv_nsec * 0.000000001) + (t).tv_sec) - -/* - * Read a file content and fills a C structure with it. - */ -int -psutil_file_to_struct(char *path, void *fstruct, size_t size) { - int fd; - size_t nbytes; - fd = open(path, O_RDONLY); - if (fd == -1) { - PyErr_SetFromErrnoWithFilename(PyExc_OSError, path); - return 0; - } - nbytes = read(fd, fstruct, size); - if (nbytes <= 0) { - close(fd); - PyErr_SetFromErrno(PyExc_OSError); - return 0; - } - if (nbytes != size) { - close(fd); - PyErr_SetString(PyExc_RuntimeError, "structure size mismatch"); - return 0; - } - close(fd); - return nbytes; -} - - -/* - * Return process ppid, rss, vms, ctime, nice, nthreads, status and tty - * as a Python tuple. - */ -static PyObject * -psutil_proc_basic_info(PyObject *self, PyObject *args) { - int pid; - char path[100]; - psinfo_t info; - pstatus_t status; - const char *procfs_path; - - if (! PyArg_ParseTuple(args, "is", &pid, &procfs_path)) - return NULL; - - sprintf(path, "%s/%i/psinfo", procfs_path, pid); - if (! psutil_file_to_struct(path, (void *)&info, sizeof(info))) - return NULL; - - if (info.pr_nlwp == 0 && info.pr_lwp.pr_lwpid == 0) { - // From the /proc docs: "If the process is a zombie, the pr_nlwp - // and pr_lwp.pr_lwpid flags are zero." - status.pr_stat = SZOMB; - } else if (info.pr_flag & SEXIT) { - // "exiting" processes don't have /proc//status - // There are other "exiting" processes that 'ps' shows as "active" - status.pr_stat = SACTIVE; - } else { - sprintf(path, "%s/%i/status", procfs_path, pid); - if (! psutil_file_to_struct(path, (void *)&status, sizeof(status))) - return NULL; - } - - return Py_BuildValue("KKKdiiiK", - (unsigned long long) info.pr_ppid, // parent pid - (unsigned long long) info.pr_rssize, // rss - (unsigned long long) info.pr_size, // vms - TV2DOUBLE(info.pr_start), // create time - (int) info.pr_lwp.pr_nice, // nice - (int) info.pr_nlwp, // no. of threads - (int) status.pr_stat, // status code - (unsigned long long)info.pr_ttydev // tty nr - ); -} - - -/* - * Return process name as a Python string. - */ -static PyObject * -psutil_proc_name(PyObject *self, PyObject *args) { - int pid; - char path[100]; - psinfo_t info; - const char *procfs_path; - - if (! PyArg_ParseTuple(args, "is", &pid, &procfs_path)) - return NULL; - sprintf(path, "%s/%i/psinfo", procfs_path, pid); - if (! psutil_file_to_struct(path, (void *)&info, sizeof(info))) - return NULL; - - return PyUnicode_DecodeFSDefaultAndSize(info.pr_fname, PRFNSZ); -} - - -/* - * Return process command line arguments as a Python list - */ -static PyObject * -psutil_proc_args(PyObject *self, PyObject *args) { - int pid; - PyObject *py_retlist = PyList_New(0); - PyObject *py_arg = NULL; - struct procsinfo procbuf; - long arg_max; - char *argbuf = NULL; - char *curarg = NULL; - int ret; - - if (py_retlist == NULL) - return NULL; - if (!PyArg_ParseTuple(args, "i", &pid)) - goto error; - arg_max = sysconf(_SC_ARG_MAX); - argbuf = malloc(arg_max); - if (argbuf == NULL) { - PyErr_NoMemory(); - goto error; - } - - procbuf.pi_pid = pid; - ret = getargs(&procbuf, sizeof(procbuf), argbuf, ARG_MAX); - if (ret == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - curarg = argbuf; - /* getargs will always append an extra NULL to end the arg list, - * even if the buffer is not big enough (even though it is supposed - * to be) so the following 'while' is safe */ - while (*curarg != '\0') { - py_arg = PyUnicode_DecodeFSDefault(curarg); - if (!py_arg) - goto error; - if (PyList_Append(py_retlist, py_arg)) - goto error; - Py_DECREF(py_arg); - curarg = strchr(curarg, '\0') + 1; - } - - free(argbuf); - - return py_retlist; - -error: - if (argbuf != NULL) - free(argbuf); - Py_XDECREF(py_retlist); - Py_XDECREF(py_arg); - return NULL; -} - - -/* - * Return process environment variables as a Python dict - */ -static PyObject * -psutil_proc_environ(PyObject *self, PyObject *args) { - int pid; - PyObject *py_retdict = PyDict_New(); - PyObject *py_key = NULL; - PyObject *py_val = NULL; - struct procsinfo procbuf; - long env_max; - char *envbuf = NULL; - char *curvar = NULL; - char *separator = NULL; - int ret; - - if (py_retdict == NULL) - return NULL; - if (!PyArg_ParseTuple(args, "i", &pid)) - goto error; - env_max = sysconf(_SC_ARG_MAX); - envbuf = malloc(env_max); - if (envbuf == NULL) { - PyErr_NoMemory(); - goto error; - } - - procbuf.pi_pid = pid; - ret = getevars(&procbuf, sizeof(procbuf), envbuf, ARG_MAX); - if (ret == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - curvar = envbuf; - /* getevars will always append an extra NULL to end the arg list, - * even if the buffer is not big enough (even though it is supposed - * to be) so the following 'while' is safe */ - while (*curvar != '\0') { - separator = strchr(curvar, '='); - if (separator != NULL) { - py_key = PyUnicode_DecodeFSDefaultAndSize( - curvar, - (Py_ssize_t)(separator - curvar) - ); - if (!py_key) - goto error; - py_val = PyUnicode_DecodeFSDefault(separator + 1); - if (!py_val) - goto error; - if (PyDict_SetItem(py_retdict, py_key, py_val)) - goto error; - Py_CLEAR(py_key); - Py_CLEAR(py_val); - } - curvar = strchr(curvar, '\0') + 1; - } - - free(envbuf); - - return py_retdict; - -error: - if (envbuf != NULL) - free(envbuf); - Py_XDECREF(py_retdict); - Py_XDECREF(py_key); - Py_XDECREF(py_val); - return NULL; -} - - -#ifdef CURR_VERSION_THREAD - -/* - * Retrieves all threads used by process returning a list of tuples - * including thread id, user time and system time. - */ -static PyObject * -psutil_proc_threads(PyObject *self, PyObject *args) { - long pid; - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - perfstat_thread_t *threadt = NULL; - perfstat_id_t id; - int i, rc, thread_count; - - if (py_retlist == NULL) - return NULL; - if (! PyArg_ParseTuple(args, "l", &pid)) - goto error; - - /* Get the count of threads */ - thread_count = perfstat_thread(NULL, NULL, sizeof(perfstat_thread_t), 0); - if (thread_count <= 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - /* Allocate enough memory */ - threadt = (perfstat_thread_t *)calloc(thread_count, - sizeof(perfstat_thread_t)); - if (threadt == NULL) { - PyErr_NoMemory(); - goto error; - } - - strcpy(id.name, ""); - rc = perfstat_thread(&id, threadt, sizeof(perfstat_thread_t), - thread_count); - if (rc <= 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (i = 0; i < thread_count; i++) { - if (threadt[i].pid != pid) - continue; - - py_tuple = Py_BuildValue("Idd", - threadt[i].tid, - threadt[i].ucpu_time, - threadt[i].scpu_time); - if (py_tuple == NULL) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_tuple); - } - free(threadt); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (threadt != NULL) - free(threadt); - return NULL; -} - -#endif - - -#ifdef CURR_VERSION_PROCESS - -static PyObject * -psutil_proc_io_counters(PyObject *self, PyObject *args) { - long pid; - int rc; - perfstat_process_t procinfo; - perfstat_id_t id; - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - snprintf(id.name, sizeof(id.name), "%ld", pid); - rc = perfstat_process(&id, &procinfo, sizeof(perfstat_process_t), 1); - if (rc <= 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - return Py_BuildValue("(KKKK)", - procinfo.inOps, // XXX always 0 - procinfo.outOps, - procinfo.inBytes, // XXX always 0 - procinfo.outBytes); -} - -#endif - - -/* - * Return process user and system CPU times as a Python tuple. - */ -static PyObject * -psutil_proc_cpu_times(PyObject *self, PyObject *args) { - int pid; - char path[100]; - pstatus_t info; - const char *procfs_path; - - if (! PyArg_ParseTuple(args, "is", &pid, &procfs_path)) - return NULL; - sprintf(path, "%s/%i/status", procfs_path, pid); - if (! psutil_file_to_struct(path, (void *)&info, sizeof(info))) - return NULL; - // results are more precise than os.times() - return Py_BuildValue("dddd", - TV2DOUBLE(info.pr_utime), - TV2DOUBLE(info.pr_stime), - TV2DOUBLE(info.pr_cutime), - TV2DOUBLE(info.pr_cstime)); -} - - -/* - * Return process uids/gids as a Python tuple. - */ -static PyObject * -psutil_proc_cred(PyObject *self, PyObject *args) { - int pid; - char path[100]; - prcred_t info; - const char *procfs_path; - - if (! PyArg_ParseTuple(args, "is", &pid, &procfs_path)) - return NULL; - sprintf(path, "%s/%i/cred", procfs_path, pid); - if (! psutil_file_to_struct(path, (void *)&info, sizeof(info))) - return NULL; - return Py_BuildValue("iiiiii", - info.pr_ruid, info.pr_euid, info.pr_suid, - info.pr_rgid, info.pr_egid, info.pr_sgid); -} - - -/* - * Return process voluntary and involuntary context switches as a Python tuple. - */ -static PyObject * -psutil_proc_num_ctx_switches(PyObject *self, PyObject *args) { - PyObject *py_tuple = NULL; - pid32_t requested_pid; - pid32_t pid = 0; - int np = 0; - struct procentry64 *processes = (struct procentry64 *)NULL; - struct procentry64 *p; - - if (! PyArg_ParseTuple(args, "i", &requested_pid)) - return NULL; - - processes = psutil_read_process_table(&np); - if (!processes) - return NULL; - - /* Loop through processes */ - for (p = processes; np > 0; np--, p++) { - pid = p->pi_pid; - if (requested_pid != pid) - continue; - py_tuple = Py_BuildValue("LL", - (long long) p->pi_ru.ru_nvcsw, /* voluntary context switches */ - (long long) p->pi_ru.ru_nivcsw); /* involuntary */ - free(processes); - return py_tuple; - } - - /* finished iteration without finding requested pid */ - free(processes); - return NoSuchProcess(""); -} - - -/* - * Return users currently connected on the system. - */ -static PyObject * -psutil_users(PyObject *self, PyObject *args) { - struct utmpx *ut; - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - PyObject *py_username = NULL; - PyObject *py_tty = NULL; - PyObject *py_hostname = NULL; - PyObject *py_user_proc = NULL; - - if (py_retlist == NULL) - return NULL; - - setutxent(); - while (NULL != (ut = getutxent())) { - if (ut->ut_type == USER_PROCESS) - py_user_proc = Py_True; - else - py_user_proc = Py_False; - py_username = PyUnicode_DecodeFSDefault(ut->ut_user); - if (! py_username) - goto error; - py_tty = PyUnicode_DecodeFSDefault(ut->ut_line); - if (! py_tty) - goto error; - py_hostname = PyUnicode_DecodeFSDefault(ut->ut_host); - if (! py_hostname) - goto error; - py_tuple = Py_BuildValue( - "(OOOfOi)", - py_username, // username - py_tty, // tty - py_hostname, // hostname - (float)ut->ut_tv.tv_sec, // tstamp - py_user_proc, // (bool) user process - ut->ut_pid // process id - ); - if (py_tuple == NULL) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_username); - Py_CLEAR(py_tty); - Py_CLEAR(py_hostname); - Py_CLEAR(py_tuple); - } - endutxent(); - - return py_retlist; - -error: - Py_XDECREF(py_username); - Py_XDECREF(py_tty); - Py_XDECREF(py_hostname); - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (ut != NULL) - endutxent(); - return NULL; -} - - -/* - * Return disk mounted partitions as a list of tuples including device, - * mount point and filesystem type. - */ -static PyObject * -psutil_disk_partitions(PyObject *self, PyObject *args) { - FILE *file = NULL; - struct mntent * mt = NULL; - PyObject *py_dev = NULL; - PyObject *py_mountp = NULL; - PyObject *py_tuple = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - - file = setmntent(MNTTAB, "rb"); - if (file == NULL) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - mt = getmntent(file); - while (mt != NULL) { - py_dev = PyUnicode_DecodeFSDefault(mt->mnt_fsname); - if (! py_dev) - goto error; - py_mountp = PyUnicode_DecodeFSDefault(mt->mnt_dir); - if (! py_mountp) - goto error; - py_tuple = Py_BuildValue( - "(OOss)", - py_dev, // device - py_mountp, // mount point - mt->mnt_type, // fs type - mt->mnt_opts); // options - if (py_tuple == NULL) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_dev); - Py_CLEAR(py_mountp); - Py_CLEAR(py_tuple); - mt = getmntent(file); - } - endmntent(file); - return py_retlist; - -error: - Py_XDECREF(py_dev); - Py_XDECREF(py_mountp); - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (file != NULL) - endmntent(file); - return NULL; -} - - -#if defined(CURR_VERSION_NETINTERFACE) && CURR_VERSION_NETINTERFACE >= 3 - -/* - * Return a list of tuples for network I/O statistics. - */ -static PyObject * -psutil_net_io_counters(PyObject *self, PyObject *args) { - perfstat_netinterface_t *statp = NULL; - int tot, i; - perfstat_id_t first; - - PyObject *py_retdict = PyDict_New(); - PyObject *py_ifc_info = NULL; - - if (py_retdict == NULL) - return NULL; - - /* check how many perfstat_netinterface_t structures are available */ - tot = perfstat_netinterface( - NULL, NULL, sizeof(perfstat_netinterface_t), 0); - if (tot == 0) { - // no network interfaces - return empty dict - return py_retdict; - } - if (tot < 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - statp = (perfstat_netinterface_t *) - malloc(tot * sizeof(perfstat_netinterface_t)); - if (statp == NULL) { - PyErr_NoMemory(); - goto error; - } - strcpy(first.name, FIRST_NETINTERFACE); - tot = perfstat_netinterface(&first, statp, - sizeof(perfstat_netinterface_t), tot); - if (tot < 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (i = 0; i < tot; i++) { - py_ifc_info = Py_BuildValue("(KKKKKKKK)", - statp[i].obytes, /* number of bytes sent on interface */ - statp[i].ibytes, /* number of bytes received on interface */ - statp[i].opackets, /* number of packets sent on interface */ - statp[i].ipackets, /* number of packets received on interface */ - statp[i].ierrors, /* number of input errors on interface */ - statp[i].oerrors, /* number of output errors on interface */ - statp[i].if_iqdrops, /* Dropped on input, this interface */ - statp[i].xmitdrops /* number of packets not transmitted */ - ); - if (!py_ifc_info) - goto error; - if (PyDict_SetItemString(py_retdict, statp[i].name, py_ifc_info)) - goto error; - Py_DECREF(py_ifc_info); - } - - free(statp); - return py_retdict; - -error: - if (statp != NULL) - free(statp); - Py_XDECREF(py_ifc_info); - Py_DECREF(py_retdict); - return NULL; -} - -#endif - - -static PyObject* -psutil_net_if_stats(PyObject* self, PyObject* args) { - char *nic_name; - int sock = 0; - int ret; - int mtu; - struct ifreq ifr; - PyObject *py_is_up = NULL; - PyObject *py_retlist = NULL; - - if (! PyArg_ParseTuple(args, "s", &nic_name)) - return NULL; - - sock = socket(AF_INET, SOCK_DGRAM, 0); - if (sock == -1) - goto error; - - strncpy(ifr.ifr_name, nic_name, sizeof(ifr.ifr_name)); - - // is up? - ret = ioctl(sock, SIOCGIFFLAGS, &ifr); - if (ret == -1) - goto error; - if ((ifr.ifr_flags & IFF_UP) != 0) - py_is_up = Py_True; - else - py_is_up = Py_False; - Py_INCREF(py_is_up); - - // MTU - ret = ioctl(sock, SIOCGIFMTU, &ifr); - if (ret == -1) - goto error; - mtu = ifr.ifr_mtu; - - close(sock); - py_retlist = Py_BuildValue("[Oi]", py_is_up, mtu); - if (!py_retlist) - goto error; - Py_DECREF(py_is_up); - return py_retlist; - -error: - Py_XDECREF(py_is_up); - if (sock != 0) - close(sock); - PyErr_SetFromErrno(PyExc_OSError); - return NULL; -} - - -static PyObject * -psutil_boot_time(PyObject *self, PyObject *args) { - float boot_time = 0.0; - struct utmpx *ut; - - setutxent(); - while (NULL != (ut = getutxent())) { - if (ut->ut_type == BOOT_TIME) { - boot_time = (float)ut->ut_tv.tv_sec; - break; - } - } - endutxent(); - if (boot_time == 0.0) { - /* could not find BOOT_TIME in getutxent loop */ - PyErr_SetString(PyExc_RuntimeError, "can't determine boot time"); - return NULL; - } - return Py_BuildValue("f", boot_time); -} - - -/* - * Return a Python list of tuple representing per-cpu times - */ -static PyObject * -psutil_per_cpu_times(PyObject *self, PyObject *args) { - int ncpu, rc, i; - long ticks; - perfstat_cpu_t *cpu = NULL; - perfstat_id_t id; - PyObject *py_retlist = PyList_New(0); - PyObject *py_cputime = NULL; - - if (py_retlist == NULL) - return NULL; - - /* get the number of ticks per second */ - ticks = sysconf(_SC_CLK_TCK); - if (ticks < 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - /* get the number of cpus in ncpu */ - ncpu = perfstat_cpu(NULL, NULL, sizeof(perfstat_cpu_t), 0); - if (ncpu <= 0){ - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - /* allocate enough memory to hold the ncpu structures */ - cpu = (perfstat_cpu_t *) malloc(ncpu * sizeof(perfstat_cpu_t)); - if (cpu == NULL) { - PyErr_NoMemory(); - goto error; - } - - strcpy(id.name, ""); - rc = perfstat_cpu(&id, cpu, sizeof(perfstat_cpu_t), ncpu); - - if (rc <= 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (i = 0; i < ncpu; i++) { - py_cputime = Py_BuildValue( - "(dddd)", - (double)cpu[i].user / ticks, - (double)cpu[i].sys / ticks, - (double)cpu[i].idle / ticks, - (double)cpu[i].wait / ticks); - if (!py_cputime) - goto error; - if (PyList_Append(py_retlist, py_cputime)) - goto error; - Py_DECREF(py_cputime); - } - free(cpu); - return py_retlist; - -error: - Py_XDECREF(py_cputime); - Py_DECREF(py_retlist); - if (cpu != NULL) - free(cpu); - return NULL; -} - - -/* - * Return disk IO statistics. - */ -static PyObject * -psutil_disk_io_counters(PyObject *self, PyObject *args) { - PyObject *py_retdict = PyDict_New(); - PyObject *py_disk_info = NULL; - perfstat_disk_t *diskt = NULL; - perfstat_id_t id; - int i, rc, disk_count; - - if (py_retdict == NULL) - return NULL; - - /* Get the count of disks */ - disk_count = perfstat_disk(NULL, NULL, sizeof(perfstat_disk_t), 0); - if (disk_count <= 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - /* Allocate enough memory */ - diskt = (perfstat_disk_t *)calloc(disk_count, - sizeof(perfstat_disk_t)); - if (diskt == NULL) { - PyErr_NoMemory(); - goto error; - } - - strcpy(id.name, FIRST_DISK); - rc = perfstat_disk(&id, diskt, sizeof(perfstat_disk_t), - disk_count); - if (rc <= 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (i = 0; i < disk_count; i++) { - py_disk_info = Py_BuildValue( - "KKKKKK", - diskt[i].__rxfers, - diskt[i].xfers - diskt[i].__rxfers, - diskt[i].rblks * diskt[i].bsize, - diskt[i].wblks * diskt[i].bsize, - diskt[i].rserv / 1000 / 1000, // from nano to milli secs - diskt[i].wserv / 1000 / 1000 // from nano to milli secs - ); - if (py_disk_info == NULL) - goto error; - if (PyDict_SetItemString(py_retdict, diskt[i].name, - py_disk_info)) - goto error; - Py_DECREF(py_disk_info); - } - free(diskt); - return py_retdict; - -error: - Py_XDECREF(py_disk_info); - Py_DECREF(py_retdict); - if (diskt != NULL) - free(diskt); - return NULL; -} - - -/* - * Return virtual memory usage statistics. - */ -static PyObject * -psutil_virtual_mem(PyObject *self, PyObject *args) { - int rc; - int pagesize = getpagesize(); - perfstat_memory_total_t memory; - - rc = perfstat_memory_total( - NULL, &memory, sizeof(perfstat_memory_total_t), 1); - if (rc <= 0){ - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - return Py_BuildValue("KKKKK", - (unsigned long long) memory.real_total * pagesize, - (unsigned long long) memory.real_avail * pagesize, - (unsigned long long) memory.real_free * pagesize, - (unsigned long long) memory.real_pinned * pagesize, - (unsigned long long) memory.real_inuse * pagesize - ); -} - - -/* - * Return stats about swap memory. - */ -static PyObject * -psutil_swap_mem(PyObject *self, PyObject *args) { - int rc; - int pagesize = getpagesize(); - perfstat_memory_total_t memory; - - rc = perfstat_memory_total( - NULL, &memory, sizeof(perfstat_memory_total_t), 1); - if (rc <= 0){ - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - return Py_BuildValue("KKKK", - (unsigned long long) memory.pgsp_total * pagesize, - (unsigned long long) memory.pgsp_free * pagesize, - (unsigned long long) memory.pgins * pagesize, - (unsigned long long) memory.pgouts * pagesize - ); -} - - -/* - * Return CPU statistics. - */ -static PyObject * -psutil_cpu_stats(PyObject *self, PyObject *args) { - int ncpu, rc, i; - // perfstat_cpu_total_t doesn't have invol/vol cswitch, only pswitch - // which is apparently something else. We have to sum over all cpus - perfstat_cpu_t *cpu = NULL; - perfstat_id_t id; - u_longlong_t cswitches = 0; - u_longlong_t devintrs = 0; - u_longlong_t softintrs = 0; - u_longlong_t syscall = 0; - - /* get the number of cpus in ncpu */ - ncpu = perfstat_cpu(NULL, NULL, sizeof(perfstat_cpu_t), 0); - if (ncpu <= 0){ - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - /* allocate enough memory to hold the ncpu structures */ - cpu = (perfstat_cpu_t *) malloc(ncpu * sizeof(perfstat_cpu_t)); - if (cpu == NULL) { - PyErr_NoMemory(); - goto error; - } - - strcpy(id.name, ""); - rc = perfstat_cpu(&id, cpu, sizeof(perfstat_cpu_t), ncpu); - - if (rc <= 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (i = 0; i < ncpu; i++) { - cswitches += cpu[i].invol_cswitch + cpu[i].vol_cswitch; - devintrs += cpu[i].devintrs; - softintrs += cpu[i].softintrs; - syscall += cpu[i].syscall; - } - - free(cpu); - - return Py_BuildValue( - "KKKK", - cswitches, - devintrs, - softintrs, - syscall - ); - -error: - if (cpu != NULL) - free(cpu); - return NULL; -} - - -/* - * define the psutil C module methods and initialize the module. - */ -static PyMethodDef -PsutilMethods[] = -{ - // --- process-related functions - {"proc_basic_info", psutil_proc_basic_info, METH_VARARGS, - "Return process ppid, rss, vms, ctime, nice, nthreads, status and tty"}, - {"proc_name", psutil_proc_name, METH_VARARGS, - "Return process name."}, - {"proc_args", psutil_proc_args, METH_VARARGS, - "Return process command line arguments."}, - {"proc_environ", psutil_proc_environ, METH_VARARGS, - "Return process environment variables."}, - {"proc_cpu_times", psutil_proc_cpu_times, METH_VARARGS, - "Return process user and system CPU times."}, - {"proc_cred", psutil_proc_cred, METH_VARARGS, - "Return process uids/gids."}, -#ifdef CURR_VERSION_THREAD - {"proc_threads", psutil_proc_threads, METH_VARARGS, - "Return process threads"}, -#endif -#ifdef CURR_VERSION_PROCESS - {"proc_io_counters", psutil_proc_io_counters, METH_VARARGS, - "Get process I/O counters."}, -#endif - {"proc_num_ctx_switches", psutil_proc_num_ctx_switches, METH_VARARGS, - "Get process I/O counters."}, - - // --- system-related functions - {"users", psutil_users, METH_VARARGS, - "Return currently connected users."}, - {"disk_partitions", psutil_disk_partitions, METH_VARARGS, - "Return disk partitions."}, - {"boot_time", psutil_boot_time, METH_VARARGS, - "Return system boot time in seconds since the EPOCH."}, - {"per_cpu_times", psutil_per_cpu_times, METH_VARARGS, - "Return system per-cpu times as a list of tuples"}, - {"disk_io_counters", psutil_disk_io_counters, METH_VARARGS, - "Return a Python dict of tuples for disk I/O statistics."}, - {"virtual_mem", psutil_virtual_mem, METH_VARARGS, - "Return system virtual memory usage statistics"}, - {"swap_mem", psutil_swap_mem, METH_VARARGS, - "Return stats about swap memory, in bytes"}, -#if defined(CURR_VERSION_NETINTERFACE) && CURR_VERSION_NETINTERFACE >= 3 - {"net_io_counters", psutil_net_io_counters, METH_VARARGS, - "Return a Python dict of tuples for network I/O statistics."}, -#endif - {"net_connections", psutil_net_connections, METH_VARARGS, - "Return system-wide connections"}, - {"net_if_stats", psutil_net_if_stats, METH_VARARGS, - "Return NIC stats (isup, mtu)"}, - {"cpu_stats", psutil_cpu_stats, METH_VARARGS, - "Return CPU statistics"}, - - // --- others - {"set_testing", psutil_set_testing, METH_NOARGS, - "Set psutil in testing mode"}, - - {NULL, NULL, 0, NULL} -}; - - -struct module_state { - PyObject *error; -}; - -#if PY_MAJOR_VERSION >= 3 -#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) -#else -#define GETSTATE(m) (&_state) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#if PY_MAJOR_VERSION >= 3 - -static int -psutil_aix_traverse(PyObject *m, visitproc visit, void *arg) { - Py_VISIT(GETSTATE(m)->error); - return 0; -} - -static int -psutil_aix_clear(PyObject *m) { - Py_CLEAR(GETSTATE(m)->error); - return 0; -} - -static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, - "psutil_aix", - NULL, - sizeof(struct module_state), - PsutilMethods, - NULL, - psutil_aix_traverse, - psutil_aix_clear, - NULL -}; - -#define INITERROR return NULL - -PyMODINIT_FUNC PyInit__psutil_aix(void) - -#else -#define INITERROR return - -void init_psutil_aix(void) -#endif -{ -#if PY_MAJOR_VERSION >= 3 - PyObject *module = PyModule_Create(&moduledef); -#else - PyObject *module = Py_InitModule("_psutil_aix", PsutilMethods); -#endif - PyModule_AddIntConstant(module, "version", PSUTIL_VERSION); - - PyModule_AddIntConstant(module, "SIDL", SIDL); - PyModule_AddIntConstant(module, "SZOMB", SZOMB); - PyModule_AddIntConstant(module, "SACTIVE", SACTIVE); - PyModule_AddIntConstant(module, "SSWAP", SSWAP); - PyModule_AddIntConstant(module, "SSTOP", SSTOP); - - PyModule_AddIntConstant(module, "TCPS_CLOSED", TCPS_CLOSED); - PyModule_AddIntConstant(module, "TCPS_CLOSING", TCPS_CLOSING); - PyModule_AddIntConstant(module, "TCPS_CLOSE_WAIT", TCPS_CLOSE_WAIT); - PyModule_AddIntConstant(module, "TCPS_LISTEN", TCPS_LISTEN); - PyModule_AddIntConstant(module, "TCPS_ESTABLISHED", TCPS_ESTABLISHED); - PyModule_AddIntConstant(module, "TCPS_SYN_SENT", TCPS_SYN_SENT); - PyModule_AddIntConstant(module, "TCPS_SYN_RCVD", TCPS_SYN_RECEIVED); - PyModule_AddIntConstant(module, "TCPS_FIN_WAIT_1", TCPS_FIN_WAIT_1); - PyModule_AddIntConstant(module, "TCPS_FIN_WAIT_2", TCPS_FIN_WAIT_2); - PyModule_AddIntConstant(module, "TCPS_LAST_ACK", TCPS_LAST_ACK); - PyModule_AddIntConstant(module, "TCPS_TIME_WAIT", TCPS_TIME_WAIT); - PyModule_AddIntConstant(module, "PSUTIL_CONN_NONE", PSUTIL_CONN_NONE); - - psutil_setup(); - - if (module == NULL) - INITERROR; -#if PY_MAJOR_VERSION >= 3 - return module; -#endif -} - -#ifdef __cplusplus -} -#endif diff --git a/ddtrace/vendor/psutil/_psutil_bsd.c b/ddtrace/vendor/psutil/_psutil_bsd.c deleted file mode 100644 index 723d6198c35..00000000000 --- a/ddtrace/vendor/psutil/_psutil_bsd.c +++ /dev/null @@ -1,1093 +0,0 @@ -/* - * Copyright (c) 2009, Giampaolo Rodola', Landry Breuil (OpenBSD). - * All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Platform-specific module methods for FreeBSD and OpenBSD. - - * OpenBSD references: - * - OpenBSD source code: https://github.com/openbsd/src - * - * OpenBSD / NetBSD: missing APIs compared to FreeBSD implementation: - * - psutil.net_connections() - * - psutil.Process.get/set_cpu_affinity() (not supported natively) - * - psutil.Process.memory_maps() - */ - -#if defined(PSUTIL_NETBSD) - #define _KMEMUSER -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if !defined(__NetBSD__) -#include -#endif -#include -#include -#include -#include -#include // for struct xsocket -#include -#include -// for xinpcb struct -#include -#include -#include -#include -#include -#include -#include -#include // for struct xtcpcb -#include // for TCP connection states -#include // for inet_ntop() - -#include - -#include // net io counters -#include -#include - -#include // process open files/connections -#include - -#include "_psutil_common.h" -#include "_psutil_posix.h" - -#ifdef PSUTIL_FREEBSD - #include "arch/freebsd/specific.h" - #include "arch/freebsd/sys_socks.h" - #include "arch/freebsd/proc_socks.h" - - #include - #include // get io counters - #include // process open files, shared libs (kinfo_getvmmap) - #if __FreeBSD_version < 900000 - #include // system users - #else - #include - #endif -#elif PSUTIL_OPENBSD - #include "arch/openbsd/specific.h" - - #include - #include // for VREG - #define _KERNEL // for DTYPE_VNODE - #include - #undef _KERNEL - #include // for CPUSTATES & CP_* -#elif PSUTIL_NETBSD - #include "arch/netbsd/specific.h" - #include "arch/netbsd/socks.h" - - #include - #include // for VREG - #include // for CPUSTATES & CP_* - #ifndef DTYPE_VNODE - #define DTYPE_VNODE 1 - #endif -#endif - - - -// convert a timeval struct to a double -#define PSUTIL_TV2DOUBLE(t) ((t).tv_sec + (t).tv_usec / 1000000.0) - -#ifdef PSUTIL_FREEBSD - // convert a bintime struct to milliseconds - #define PSUTIL_BT2MSEC(bt) (bt.sec * 1000 + (((uint64_t) 1000000000 * \ - (uint32_t) (bt.frac >> 32) ) >> 32 ) / 1000000) -#endif - -#if defined(PSUTIL_OPENBSD) || defined (PSUTIL_NETBSD) - #define PSUTIL_KPT2DOUBLE(t) (t ## _sec + t ## _usec / 1000000.0) -#endif - - -/* - * Return a Python list of all the PIDs running on the system. - */ -static PyObject * -psutil_pids(PyObject *self, PyObject *args) { - kinfo_proc *proclist = NULL; - kinfo_proc *orig_address = NULL; - size_t num_processes; - size_t idx; - PyObject *py_retlist = PyList_New(0); - PyObject *py_pid = NULL; - - if (py_retlist == NULL) - return NULL; - - // TODO: RuntimeError is inappropriate here; we could return the - // original error instead. - if (psutil_get_proc_list(&proclist, &num_processes) != 0) { - if (errno != 0) { - PyErr_SetFromErrno(PyExc_OSError); - } - else { - PyErr_SetString(PyExc_RuntimeError, - "failed to retrieve process list"); - } - goto error; - } - - if (num_processes > 0) { - orig_address = proclist; // save so we can free it after we're done - for (idx = 0; idx < num_processes; idx++) { -#ifdef PSUTIL_FREEBSD - py_pid = Py_BuildValue("i", proclist->ki_pid); -#elif defined(PSUTIL_OPENBSD) || defined(PSUTIL_NETBSD) - py_pid = Py_BuildValue("i", proclist->p_pid); -#endif - if (!py_pid) - goto error; - if (PyList_Append(py_retlist, py_pid)) - goto error; - Py_CLEAR(py_pid); - proclist++; - } - free(orig_address); - } - - return py_retlist; - -error: - Py_XDECREF(py_pid); - Py_DECREF(py_retlist); - if (orig_address != NULL) - free(orig_address); - return NULL; -} - - -/* - * Return a Python float indicating the system boot time expressed in - * seconds since the epoch. - */ -static PyObject * -psutil_boot_time(PyObject *self, PyObject *args) { - // fetch sysctl "kern.boottime" - static int request[2] = { CTL_KERN, KERN_BOOTTIME }; - struct timeval boottime; - size_t len = sizeof(boottime); - - if (sysctl(request, 2, &boottime, &len, NULL, 0) == -1) - return PyErr_SetFromErrno(PyExc_OSError); - return Py_BuildValue("d", (double)boottime.tv_sec); -} - - -/* - * Collect different info about a process in one shot and return - * them as a big Python tuple. - */ -static PyObject * -psutil_proc_oneshot_info(PyObject *self, PyObject *args) { - long pid; - long rss; - long vms; - long memtext; - long memdata; - long memstack; - int oncpu; - kinfo_proc kp; - long pagesize = sysconf(_SC_PAGESIZE); - char str[1000]; - PyObject *py_name; - PyObject *py_retlist; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (psutil_kinfo_proc(pid, &kp) == -1) - return NULL; - - // Process -#ifdef PSUTIL_FREEBSD - sprintf(str, "%s", kp.ki_comm); -#elif defined(PSUTIL_OPENBSD) || defined(PSUTIL_NETBSD) - sprintf(str, "%s", kp.p_comm); -#endif - py_name = PyUnicode_DecodeFSDefault(str); - if (! py_name) { - // Likely a decoding error. We don't want to fail the whole - // operation. The python module may retry with proc_name(). - PyErr_Clear(); - py_name = Py_None; - } - // Py_INCREF(py_name); - - // Calculate memory. -#ifdef PSUTIL_FREEBSD - rss = (long)kp.ki_rssize * pagesize; - vms = (long)kp.ki_size; - memtext = (long)kp.ki_tsize * pagesize; - memdata = (long)kp.ki_dsize * pagesize; - memstack = (long)kp.ki_ssize * pagesize; -#else - rss = (long)kp.p_vm_rssize * pagesize; - #ifdef PSUTIL_OPENBSD - // VMS, this is how ps determines it on OpenBSD: - // https://github.com/openbsd/src/blob/ - // 588f7f8c69786211f2d16865c552afb91b1c7cba/bin/ps/print.c#L505 - vms = (long)(kp.p_vm_dsize + kp.p_vm_ssize + kp.p_vm_tsize) * pagesize; - #elif PSUTIL_NETBSD - // VMS, this is how top determines it on NetBSD: - // https://github.com/IIJ-NetBSD/netbsd-src/blob/master/external/ - // bsd/top/dist/machine/m_netbsd.c - vms = (long)kp.p_vm_msize * pagesize; - #endif - memtext = (long)kp.p_vm_tsize * pagesize; - memdata = (long)kp.p_vm_dsize * pagesize; - memstack = (long)kp.p_vm_ssize * pagesize; -#endif - -#ifdef PSUTIL_FREEBSD - // what CPU we're on; top was used as an example: - // https://svnweb.freebsd.org/base/head/usr.bin/top/machine.c? - // view=markup&pathrev=273835 - // XXX - note: for "intr" PID this is -1. - if (kp.ki_stat == SRUN && kp.ki_oncpu != NOCPU) - oncpu = kp.ki_oncpu; - else - oncpu = kp.ki_lastcpu; -#else - // On Net/OpenBSD we have kp.p_cpuid but it appears it's always - // set to KI_NOCPU. Even if it's not, ki_lastcpu does not exist - // so there's no way to determine where "sleeping" processes - // were. Not supported. - oncpu = -1; -#endif - - // Return a single big tuple with all process info. - py_retlist = Py_BuildValue( - "(lillllllidllllddddlllllbO)", -#ifdef PSUTIL_FREEBSD - // - (long)kp.ki_ppid, // (long) ppid - (int)kp.ki_stat, // (int) status - // UIDs - (long)kp.ki_ruid, // (long) real uid - (long)kp.ki_uid, // (long) effective uid - (long)kp.ki_svuid, // (long) saved uid - // GIDs - (long)kp.ki_rgid, // (long) real gid - (long)kp.ki_groups[0], // (long) effective gid - (long)kp.ki_svuid, // (long) saved gid - // - kp.ki_tdev, // (int) tty nr - PSUTIL_TV2DOUBLE(kp.ki_start), // (double) create time - // ctx switches - kp.ki_rusage.ru_nvcsw, // (long) ctx switches (voluntary) - kp.ki_rusage.ru_nivcsw, // (long) ctx switches (unvoluntary) - // IO count - kp.ki_rusage.ru_inblock, // (long) read io count - kp.ki_rusage.ru_oublock, // (long) write io count - // CPU times: convert from micro seconds to seconds. - PSUTIL_TV2DOUBLE(kp.ki_rusage.ru_utime), // (double) user time - PSUTIL_TV2DOUBLE(kp.ki_rusage.ru_stime), // (double) sys time - PSUTIL_TV2DOUBLE(kp.ki_rusage_ch.ru_utime), // (double) children utime - PSUTIL_TV2DOUBLE(kp.ki_rusage_ch.ru_stime), // (double) children stime - // memory - rss, // (long) rss - vms, // (long) vms - memtext, // (long) mem text - memdata, // (long) mem data - memstack, // (long) mem stack - // others - oncpu, // (int) the CPU we are on -#elif defined(PSUTIL_OPENBSD) || defined(PSUTIL_NETBSD) - // - (long)kp.p_ppid, // (long) ppid - (int)kp.p_stat, // (int) status - // UIDs - (long)kp.p_ruid, // (long) real uid - (long)kp.p_uid, // (long) effective uid - (long)kp.p_svuid, // (long) saved uid - // GIDs - (long)kp.p_rgid, // (long) real gid - (long)kp.p_groups[0], // (long) effective gid - (long)kp.p_svuid, // (long) saved gid - // - kp.p_tdev, // (int) tty nr - PSUTIL_KPT2DOUBLE(kp.p_ustart), // (double) create time - // ctx switches - kp.p_uru_nvcsw, // (long) ctx switches (voluntary) - kp.p_uru_nivcsw, // (long) ctx switches (unvoluntary) - // IO count - kp.p_uru_inblock, // (long) read io count - kp.p_uru_oublock, // (long) write io count - // CPU times: convert from micro seconds to seconds. - PSUTIL_KPT2DOUBLE(kp.p_uutime), // (double) user time - PSUTIL_KPT2DOUBLE(kp.p_ustime), // (double) sys time - // OpenBSD and NetBSD provide children user + system times summed - // together (no distinction). - kp.p_uctime_sec + kp.p_uctime_usec / 1000000.0, // (double) ch utime - kp.p_uctime_sec + kp.p_uctime_usec / 1000000.0, // (double) ch stime - // memory - rss, // (long) rss - vms, // (long) vms - memtext, // (long) mem text - memdata, // (long) mem data - memstack, // (long) mem stack - // others - oncpu, // (int) the CPU we are on -#endif - py_name // (pystr) name - ); - - Py_DECREF(py_name); - return py_retlist; -} - - -/* - * Return process name from kinfo_proc as a Python string. - */ -static PyObject * -psutil_proc_name(PyObject *self, PyObject *args) { - long pid; - kinfo_proc kp; - char str[1000]; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (psutil_kinfo_proc(pid, &kp) == -1) - return NULL; - -#ifdef PSUTIL_FREEBSD - sprintf(str, "%s", kp.ki_comm); -#elif defined(PSUTIL_OPENBSD) || defined(PSUTIL_NETBSD) - sprintf(str, "%s", kp.p_comm); -#endif - return PyUnicode_DecodeFSDefault(str); -} - - -/* - * Return process cmdline as a Python list of cmdline arguments. - */ -static PyObject * -psutil_proc_cmdline(PyObject *self, PyObject *args) { - long pid; - PyObject *py_retlist = NULL; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - py_retlist = psutil_get_cmdline(pid); - if (py_retlist == NULL) - return NULL; - return Py_BuildValue("N", py_retlist); -} - - -/* - * Return the number of logical CPUs in the system. - * XXX this could be shared with macOS - */ -static PyObject * -psutil_cpu_count_logical(PyObject *self, PyObject *args) { - int mib[2]; - int ncpu; - size_t len; - - mib[0] = CTL_HW; - mib[1] = HW_NCPU; - len = sizeof(ncpu); - - if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1) - Py_RETURN_NONE; // mimic os.cpu_count() - else - return Py_BuildValue("i", ncpu); -} - - -/* - * Return a Python tuple representing user, kernel and idle CPU times - */ -static PyObject * -psutil_cpu_times(PyObject *self, PyObject *args) { -#ifdef PSUTIL_NETBSD - u_int64_t cpu_time[CPUSTATES]; -#else - long cpu_time[CPUSTATES]; -#endif - size_t size = sizeof(cpu_time); - int ret; - -#if defined(PSUTIL_FREEBSD) || defined(PSUTIL_NETBSD) - ret = sysctlbyname("kern.cp_time", &cpu_time, &size, NULL, 0); -#elif PSUTIL_OPENBSD - int mib[] = {CTL_KERN, KERN_CPTIME}; - ret = sysctl(mib, 2, &cpu_time, &size, NULL, 0); -#endif - if (ret == -1) - return PyErr_SetFromErrno(PyExc_OSError); - return Py_BuildValue("(ddddd)", - (double)cpu_time[CP_USER] / CLOCKS_PER_SEC, - (double)cpu_time[CP_NICE] / CLOCKS_PER_SEC, - (double)cpu_time[CP_SYS] / CLOCKS_PER_SEC, - (double)cpu_time[CP_IDLE] / CLOCKS_PER_SEC, - (double)cpu_time[CP_INTR] / CLOCKS_PER_SEC - ); -} - - - /* - * Return files opened by process as a list of (path, fd) tuples. - * TODO: this is broken as it may report empty paths. 'procstat' - * utility has the same problem see: - * https://github.com/giampaolo/psutil/issues/595 - */ -#if (defined(__FreeBSD_version) && __FreeBSD_version >= 800000) || PSUTIL_OPENBSD || defined(PSUTIL_NETBSD) -static PyObject * -psutil_proc_open_files(PyObject *self, PyObject *args) { - long pid; - int i; - int cnt; - int regular; - int fd; - char *path; - struct kinfo_file *freep = NULL; - struct kinfo_file *kif; - kinfo_proc kipp; - PyObject *py_tuple = NULL; - PyObject *py_path = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - if (! PyArg_ParseTuple(args, "l", &pid)) - goto error; - if (psutil_kinfo_proc(pid, &kipp) == -1) - goto error; - - errno = 0; - freep = kinfo_getfile(pid, &cnt); - if (freep == NULL) { - psutil_raise_for_pid(pid, "kinfo_getfile()"); - goto error; - } - - for (i = 0; i < cnt; i++) { - kif = &freep[i]; - -#ifdef PSUTIL_FREEBSD - regular = (kif->kf_type == KF_TYPE_VNODE) && \ - (kif->kf_vnode_type == KF_VTYPE_VREG); - fd = kif->kf_fd; - path = kif->kf_path; -#elif PSUTIL_OPENBSD - regular = (kif->f_type == DTYPE_VNODE) && (kif->v_type == VREG); - fd = kif->fd_fd; - // XXX - it appears path is not exposed in the kinfo_file struct. - path = ""; -#elif PSUTIL_NETBSD - regular = (kif->ki_ftype == DTYPE_VNODE) && (kif->ki_vtype == VREG); - fd = kif->ki_fd; - // XXX - it appears path is not exposed in the kinfo_file struct. - path = ""; -#endif - if (regular == 1) { - py_path = PyUnicode_DecodeFSDefault(path); - if (! py_path) - goto error; - py_tuple = Py_BuildValue("(Oi)", py_path, fd); - if (py_tuple == NULL) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_path); - Py_CLEAR(py_tuple); - } - } - free(freep); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (freep != NULL) - free(freep); - return NULL; -} -#endif - - -/* - * Return a list of tuples including device, mount point and fs type - * for all partitions mounted on the system. - */ -static PyObject * -psutil_disk_partitions(PyObject *self, PyObject *args) { - int num; - int i; - long len; - uint64_t flags; - char opts[200]; -#ifdef PSUTIL_NETBSD - struct statvfs *fs = NULL; -#else - struct statfs *fs = NULL; -#endif - PyObject *py_retlist = PyList_New(0); - PyObject *py_dev = NULL; - PyObject *py_mountp = NULL; - PyObject *py_tuple = NULL; - - if (py_retlist == NULL) - return NULL; - - // get the number of mount points - Py_BEGIN_ALLOW_THREADS -#ifdef PSUTIL_NETBSD - num = getvfsstat(NULL, 0, MNT_NOWAIT); -#else - num = getfsstat(NULL, 0, MNT_NOWAIT); -#endif - Py_END_ALLOW_THREADS - if (num == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - len = sizeof(*fs) * num; - fs = malloc(len); - if (fs == NULL) { - PyErr_NoMemory(); - goto error; - } - - Py_BEGIN_ALLOW_THREADS -#ifdef PSUTIL_NETBSD - num = getvfsstat(fs, len, MNT_NOWAIT); -#else - num = getfsstat(fs, len, MNT_NOWAIT); -#endif - Py_END_ALLOW_THREADS - if (num == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (i = 0; i < num; i++) { - py_tuple = NULL; - opts[0] = 0; -#ifdef PSUTIL_NETBSD - flags = fs[i].f_flag; -#else - flags = fs[i].f_flags; -#endif - - // see sys/mount.h - if (flags & MNT_RDONLY) - strlcat(opts, "ro", sizeof(opts)); - else - strlcat(opts, "rw", sizeof(opts)); - if (flags & MNT_SYNCHRONOUS) - strlcat(opts, ",sync", sizeof(opts)); - if (flags & MNT_NOEXEC) - strlcat(opts, ",noexec", sizeof(opts)); - if (flags & MNT_NOSUID) - strlcat(opts, ",nosuid", sizeof(opts)); - if (flags & MNT_ASYNC) - strlcat(opts, ",async", sizeof(opts)); - if (flags & MNT_NOATIME) - strlcat(opts, ",noatime", sizeof(opts)); - if (flags & MNT_SOFTDEP) - strlcat(opts, ",softdep", sizeof(opts)); -#ifdef PSUTIL_FREEBSD - if (flags & MNT_UNION) - strlcat(opts, ",union", sizeof(opts)); - if (flags & MNT_SUIDDIR) - strlcat(opts, ",suiddir", sizeof(opts)); - if (flags & MNT_SOFTDEP) - strlcat(opts, ",softdep", sizeof(opts)); - if (flags & MNT_NOSYMFOLLOW) - strlcat(opts, ",nosymfollow", sizeof(opts)); - if (flags & MNT_GJOURNAL) - strlcat(opts, ",gjournal", sizeof(opts)); - if (flags & MNT_MULTILABEL) - strlcat(opts, ",multilabel", sizeof(opts)); - if (flags & MNT_ACLS) - strlcat(opts, ",acls", sizeof(opts)); - if (flags & MNT_NOCLUSTERR) - strlcat(opts, ",noclusterr", sizeof(opts)); - if (flags & MNT_NOCLUSTERW) - strlcat(opts, ",noclusterw", sizeof(opts)); - if (flags & MNT_NFS4ACLS) - strlcat(opts, ",nfs4acls", sizeof(opts)); -#elif PSUTIL_NETBSD - if (flags & MNT_NODEV) - strlcat(opts, ",nodev", sizeof(opts)); - if (flags & MNT_UNION) - strlcat(opts, ",union", sizeof(opts)); - if (flags & MNT_NOCOREDUMP) - strlcat(opts, ",nocoredump", sizeof(opts)); -#ifdef MNT_RELATIME - if (flags & MNT_RELATIME) - strlcat(opts, ",relatime", sizeof(opts)); -#endif - if (flags & MNT_IGNORE) - strlcat(opts, ",ignore", sizeof(opts)); -#ifdef MNT_DISCARD - if (flags & MNT_DISCARD) - strlcat(opts, ",discard", sizeof(opts)); -#endif -#ifdef MNT_EXTATTR - if (flags & MNT_EXTATTR) - strlcat(opts, ",extattr", sizeof(opts)); -#endif - if (flags & MNT_LOG) - strlcat(opts, ",log", sizeof(opts)); - if (flags & MNT_SYMPERM) - strlcat(opts, ",symperm", sizeof(opts)); - if (flags & MNT_NODEVMTIME) - strlcat(opts, ",nodevmtime", sizeof(opts)); -#endif - py_dev = PyUnicode_DecodeFSDefault(fs[i].f_mntfromname); - if (! py_dev) - goto error; - py_mountp = PyUnicode_DecodeFSDefault(fs[i].f_mntonname); - if (! py_mountp) - goto error; - py_tuple = Py_BuildValue("(OOss)", - py_dev, // device - py_mountp, // mount point - fs[i].f_fstypename, // fs type - opts); // options - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_dev); - Py_CLEAR(py_mountp); - Py_CLEAR(py_tuple); - } - - free(fs); - return py_retlist; - -error: - Py_XDECREF(py_dev); - Py_XDECREF(py_mountp); - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (fs != NULL) - free(fs); - return NULL; -} - - -/* - * Return a Python list of named tuples with overall network I/O information - */ -static PyObject * -psutil_net_io_counters(PyObject *self, PyObject *args) { - char *buf = NULL, *lim, *next; - struct if_msghdr *ifm; - int mib[6]; - size_t len; - PyObject *py_retdict = PyDict_New(); - PyObject *py_ifc_info = NULL; - if (py_retdict == NULL) - return NULL; - - mib[0] = CTL_NET; // networking subsystem - mib[1] = PF_ROUTE; // type of information - mib[2] = 0; // protocol (IPPROTO_xxx) - mib[3] = 0; // address family - mib[4] = NET_RT_IFLIST; // operation - mib[5] = 0; - - if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - buf = malloc(len); - if (buf == NULL) { - PyErr_NoMemory(); - goto error; - } - - if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - lim = buf + len; - - for (next = buf; next < lim; ) { - py_ifc_info = NULL; - ifm = (struct if_msghdr *)next; - next += ifm->ifm_msglen; - - if (ifm->ifm_type == RTM_IFINFO) { - struct if_msghdr *if2m = (struct if_msghdr *)ifm; - struct sockaddr_dl *sdl = (struct sockaddr_dl *)(if2m + 1); - char ifc_name[32]; - - strncpy(ifc_name, sdl->sdl_data, sdl->sdl_nlen); - ifc_name[sdl->sdl_nlen] = 0; - // XXX: ignore usbus interfaces: - // http://lists.freebsd.org/pipermail/freebsd-current/ - // 2011-October/028752.html - // 'ifconfig -a' doesn't show them, nor do we. - if (strncmp(ifc_name, "usbus", 5) == 0) - continue; - - py_ifc_info = Py_BuildValue("(kkkkkkki)", - if2m->ifm_data.ifi_obytes, - if2m->ifm_data.ifi_ibytes, - if2m->ifm_data.ifi_opackets, - if2m->ifm_data.ifi_ipackets, - if2m->ifm_data.ifi_ierrors, - if2m->ifm_data.ifi_oerrors, - if2m->ifm_data.ifi_iqdrops, -#ifdef _IFI_OQDROPS - if2m->ifm_data.ifi_oqdrops -#else - 0 -#endif - ); - if (!py_ifc_info) - goto error; - if (PyDict_SetItemString(py_retdict, ifc_name, py_ifc_info)) - goto error; - Py_CLEAR(py_ifc_info); - } - else { - continue; - } - } - - free(buf); - return py_retdict; - -error: - Py_XDECREF(py_ifc_info); - Py_DECREF(py_retdict); - if (buf != NULL) - free(buf); - return NULL; -} - - -/* - * Return currently connected users as a list of tuples. - */ -static PyObject * -psutil_users(PyObject *self, PyObject *args) { - PyObject *py_retlist = PyList_New(0); - PyObject *py_username = NULL; - PyObject *py_tty = NULL; - PyObject *py_hostname = NULL; - PyObject *py_tuple = NULL; - - if (py_retlist == NULL) - return NULL; - -#if (defined(__FreeBSD_version) && (__FreeBSD_version < 900000)) || PSUTIL_OPENBSD - struct utmp ut; - FILE *fp; - - Py_BEGIN_ALLOW_THREADS - fp = fopen(_PATH_UTMP, "r"); - Py_END_ALLOW_THREADS - if (fp == NULL) { - PyErr_SetFromErrnoWithFilename(PyExc_OSError, _PATH_UTMP); - goto error; - } - - while (fread(&ut, sizeof(ut), 1, fp) == 1) { - if (*ut.ut_name == '\0') - continue; - py_username = PyUnicode_DecodeFSDefault(ut.ut_name); - if (! py_username) - goto error; - py_tty = PyUnicode_DecodeFSDefault(ut.ut_line); - if (! py_tty) - goto error; - py_hostname = PyUnicode_DecodeFSDefault(ut.ut_host); - if (! py_hostname) - goto error; - py_tuple = Py_BuildValue( - "(OOOfi)", - py_username, // username - py_tty, // tty - py_hostname, // hostname - (float)ut.ut_time, // start time -#ifdef PSUTIL_OPENBSD - -1 // process id (set to None later) -#else - ut.ut_pid // process id -#endif - ); - if (!py_tuple) { - fclose(fp); - goto error; - } - if (PyList_Append(py_retlist, py_tuple)) { - fclose(fp); - goto error; - } - Py_CLEAR(py_username); - Py_CLEAR(py_tty); - Py_CLEAR(py_hostname); - Py_CLEAR(py_tuple); - } - - fclose(fp); -#else - struct utmpx *utx; - setutxent(); - while ((utx = getutxent()) != NULL) { - if (utx->ut_type != USER_PROCESS) - continue; - py_username = PyUnicode_DecodeFSDefault(utx->ut_user); - if (! py_username) - goto error; - py_tty = PyUnicode_DecodeFSDefault(utx->ut_line); - if (! py_tty) - goto error; - py_hostname = PyUnicode_DecodeFSDefault(utx->ut_host); - if (! py_hostname) - goto error; - py_tuple = Py_BuildValue( - "(OOOfi)", - py_username, // username - py_tty, // tty - py_hostname, // hostname - (float)utx->ut_tv.tv_sec, // start time -#ifdef PSUTIL_OPENBSD - -1 // process id (set to None later) -#else - utx->ut_pid // process id -#endif - ); - - if (!py_tuple) { - endutxent(); - goto error; - } - if (PyList_Append(py_retlist, py_tuple)) { - endutxent(); - goto error; - } - Py_CLEAR(py_username); - Py_CLEAR(py_tty); - Py_CLEAR(py_hostname); - Py_CLEAR(py_tuple); - } - - endutxent(); -#endif - return py_retlist; - -error: - Py_XDECREF(py_username); - Py_XDECREF(py_tty); - Py_XDECREF(py_hostname); - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - return NULL; -} - - -/* - * define the psutil C module methods and initialize the module. - */ -static PyMethodDef mod_methods[] = { - // --- per-process functions - - {"proc_oneshot_info", psutil_proc_oneshot_info, METH_VARARGS, - "Return multiple info about a process"}, - {"proc_name", psutil_proc_name, METH_VARARGS, - "Return process name"}, - {"proc_cmdline", psutil_proc_cmdline, METH_VARARGS, - "Return process cmdline as a list of cmdline arguments"}, - {"proc_threads", psutil_proc_threads, METH_VARARGS, - "Return process threads"}, -#if defined(PSUTIL_FREEBSD) || defined(PSUTIL_OPENBSD) - {"proc_connections", psutil_proc_connections, METH_VARARGS, - "Return connections opened by process"}, -#endif - {"proc_cwd", psutil_proc_cwd, METH_VARARGS, - "Return process current working directory."}, -#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000 || PSUTIL_OPENBSD || defined(PSUTIL_NETBSD) - {"proc_num_fds", psutil_proc_num_fds, METH_VARARGS, - "Return the number of file descriptors opened by this process"}, - {"proc_open_files", psutil_proc_open_files, METH_VARARGS, - "Return files opened by process as a list of (path, fd) tuples"}, -#endif -#if defined(PSUTIL_FREEBSD) || defined(PSUTIL_NETBSD) - {"proc_num_threads", psutil_proc_num_threads, METH_VARARGS, - "Return number of threads used by process"}, -#endif -#if defined(PSUTIL_FREEBSD) - {"proc_exe", psutil_proc_exe, METH_VARARGS, - "Return process pathname executable"}, - {"proc_memory_maps", psutil_proc_memory_maps, METH_VARARGS, - "Return a list of tuples for every process's memory map"}, - {"proc_cpu_affinity_get", psutil_proc_cpu_affinity_get, METH_VARARGS, - "Return process CPU affinity."}, - {"proc_cpu_affinity_set", psutil_proc_cpu_affinity_set, METH_VARARGS, - "Set process CPU affinity."}, - {"cpu_count_phys", psutil_cpu_count_phys, METH_VARARGS, - "Return an XML string to determine the number physical CPUs."}, -#endif - - // --- system-related functions - - {"pids", psutil_pids, METH_VARARGS, - "Returns a list of PIDs currently running on the system"}, - {"cpu_count_logical", psutil_cpu_count_logical, METH_VARARGS, - "Return number of logical CPUs on the system"}, - {"virtual_mem", psutil_virtual_mem, METH_VARARGS, - "Return system virtual memory usage statistics"}, - {"swap_mem", psutil_swap_mem, METH_VARARGS, - "Return swap mem stats"}, - {"cpu_times", psutil_cpu_times, METH_VARARGS, - "Return system cpu times as a tuple (user, system, nice, idle, irc)"}, - {"per_cpu_times", psutil_per_cpu_times, METH_VARARGS, - "Return system per-cpu times as a list of tuples"}, - {"boot_time", psutil_boot_time, METH_VARARGS, - "Return the system boot time expressed in seconds since the epoch."}, - {"disk_partitions", psutil_disk_partitions, METH_VARARGS, - "Return a list of tuples including device, mount point and " - "fs type for all partitions mounted on the system."}, - {"net_io_counters", psutil_net_io_counters, METH_VARARGS, - "Return dict of tuples of networks I/O information."}, - {"disk_io_counters", psutil_disk_io_counters, METH_VARARGS, - "Return a Python dict of tuples for disk I/O information"}, - {"users", psutil_users, METH_VARARGS, - "Return currently connected users as a list of tuples"}, - {"cpu_stats", psutil_cpu_stats, METH_VARARGS, - "Return CPU statistics"}, -#if defined(PSUTIL_FREEBSD) || defined(PSUTIL_NETBSD) - {"net_connections", psutil_net_connections, METH_VARARGS, - "Return system-wide open connections."}, -#endif -#if defined(PSUTIL_FREEBSD) - {"sensors_battery", psutil_sensors_battery, METH_VARARGS, - "Return battery information."}, - {"sensors_cpu_temperature", psutil_sensors_cpu_temperature, METH_VARARGS, - "Return temperature information for a given CPU core number."}, - {"cpu_frequency", psutil_cpu_freq, METH_VARARGS, - "Return frequency of a given CPU"}, -#endif - - // --- others - {"set_testing", psutil_set_testing, METH_NOARGS, - "Set psutil in testing mode"}, - - {NULL, NULL, 0, NULL} -}; - -#if PY_MAJOR_VERSION >= 3 - #define INITERR return NULL - - static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, - "_psutil_bsd", - NULL, - -1, - mod_methods, - NULL, - NULL, - NULL, - NULL - }; - - PyObject *PyInit__psutil_bsd(void) -#else /* PY_MAJOR_VERSION */ - #define INITERR return - - void init_psutil_bsd(void) -#endif /* PY_MAJOR_VERSION */ -{ - PyObject *v; -#if PY_MAJOR_VERSION >= 3 - PyObject *mod = PyModule_Create(&moduledef); -#else - PyObject *mod = Py_InitModule("_psutil_bsd", mod_methods); -#endif - if (mod == NULL) - INITERR; - - if (PyModule_AddIntConstant(mod, "version", PSUTIL_VERSION)) INITERR; - // process status constants - -#ifdef PSUTIL_FREEBSD - if (PyModule_AddIntConstant(mod, "SIDL", SIDL)) INITERR; - if (PyModule_AddIntConstant(mod, "SRUN", SRUN)) INITERR; - if (PyModule_AddIntConstant(mod, "SSLEEP", SSLEEP)) INITERR; - if (PyModule_AddIntConstant(mod, "SSTOP", SSTOP)) INITERR; - if (PyModule_AddIntConstant(mod, "SZOMB", SZOMB)) INITERR; - if (PyModule_AddIntConstant(mod, "SWAIT", SWAIT)) INITERR; - if (PyModule_AddIntConstant(mod, "SLOCK", SLOCK)) INITERR; -#elif PSUTIL_OPENBSD - if (PyModule_AddIntConstant(mod, "SIDL", SIDL)) INITERR; - if (PyModule_AddIntConstant(mod, "SRUN", SRUN)) INITERR; - if (PyModule_AddIntConstant(mod, "SSLEEP", SSLEEP)) INITERR; - if (PyModule_AddIntConstant(mod, "SSTOP", SSTOP)) INITERR; - if (PyModule_AddIntConstant(mod, "SZOMB", SZOMB)) INITERR; // unused - if (PyModule_AddIntConstant(mod, "SDEAD", SDEAD)) INITERR; - if (PyModule_AddIntConstant(mod, "SONPROC", SONPROC)) INITERR; -#elif defined(PSUTIL_NETBSD) - if (PyModule_AddIntConstant(mod, "SIDL", LSIDL)) INITERR; - if (PyModule_AddIntConstant(mod, "SRUN", LSRUN)) INITERR; - if (PyModule_AddIntConstant(mod, "SSLEEP", LSSLEEP)) INITERR; - if (PyModule_AddIntConstant(mod, "SSTOP", LSSTOP)) INITERR; - if (PyModule_AddIntConstant(mod, "SZOMB", LSZOMB)) INITERR; - if (PyModule_AddIntConstant(mod, "SDEAD", LSDEAD)) INITERR; - if (PyModule_AddIntConstant(mod, "SONPROC", LSONPROC)) INITERR; - // unique to NetBSD - if (PyModule_AddIntConstant(mod, "SSUSPENDED", LSSUSPENDED)) INITERR; -#endif - - // connection status constants - if (PyModule_AddIntConstant(mod, "TCPS_CLOSED", TCPS_CLOSED)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_CLOSING", TCPS_CLOSING)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_CLOSE_WAIT", TCPS_CLOSE_WAIT)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_LISTEN", TCPS_LISTEN)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_ESTABLISHED", TCPS_ESTABLISHED)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_SYN_SENT", TCPS_SYN_SENT)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_SYN_RECEIVED", TCPS_SYN_RECEIVED)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_FIN_WAIT_1", TCPS_FIN_WAIT_1)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_FIN_WAIT_2", TCPS_FIN_WAIT_2)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_LAST_ACK", TCPS_LAST_ACK)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_TIME_WAIT", TCPS_TIME_WAIT)) - INITERR; - // PSUTIL_CONN_NONE - if (PyModule_AddIntConstant(mod, "PSUTIL_CONN_NONE", 128)) INITERR; - - psutil_setup(); - - if (mod == NULL) - INITERR; -#if PY_MAJOR_VERSION >= 3 - return mod; -#endif -} diff --git a/ddtrace/vendor/psutil/_psutil_common.c b/ddtrace/vendor/psutil/_psutil_common.c deleted file mode 100644 index c6e37bc22ed..00000000000 --- a/ddtrace/vendor/psutil/_psutil_common.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - * 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 platforms. - */ - -#include -#ifdef _WIN32 -#include -#endif - -#include "_psutil_common.h" - -// Global vars. -int PSUTIL_DEBUG = 0; -int PSUTIL_TESTING = 0; - - -/* - * Backport of unicode FS APIs from Python 3. - * On Python 2 we just return a plain byte string - * which is never supposed to raise decoding errors. - * See: https://github.com/giampaolo/psutil/issues/1040 - */ -#if PY_MAJOR_VERSION < 3 -PyObject * -PyUnicode_DecodeFSDefault(char *s) { - return PyString_FromString(s); -} - - -PyObject * -PyUnicode_DecodeFSDefaultAndSize(char *s, Py_ssize_t size) { - return PyString_FromStringAndSize(s, size); -} -#endif - - -/* - * Set OSError(errno=ESRCH, strerror="No such process") Python exception. - * If msg != "" the exception message will change in accordance. - */ -PyObject * -NoSuchProcess(const char *msg) { - PyObject *exc; - exc = PyObject_CallFunction( - PyExc_OSError, "(is)", ESRCH, strlen(msg) ? msg : strerror(ESRCH)); - PyErr_SetObject(PyExc_OSError, exc); - Py_XDECREF(exc); - return NULL; -} - - -/* - * Same as PyErr_SetFromErrno(0) but adds the syscall to the exception - * message. - */ -PyObject * -PyErr_SetFromOSErrnoWithSyscall(const char *syscall) { - char fullmsg[1024]; - -#ifdef _WIN32 - sprintf(fullmsg, "(originated from %s)", syscall); - PyErr_SetFromWindowsErrWithFilename(GetLastError(), fullmsg); -#else - PyObject *exc; - sprintf(fullmsg, "%s (originated from %s)", strerror(errno), syscall); - exc = PyObject_CallFunction(PyExc_OSError, "(is)", errno, fullmsg); - PyErr_SetObject(PyExc_OSError, exc); - Py_XDECREF(exc); -#endif - return NULL; -} - - -/* - * Set OSError(errno=EACCES, strerror="Permission denied") Python exception. - * If msg != "" the exception message will change in accordance. - */ -PyObject * -AccessDenied(const char *msg) { - PyObject *exc; - exc = PyObject_CallFunction( - PyExc_OSError, "(is)", EACCES, strlen(msg) ? msg : strerror(EACCES)); - PyErr_SetObject(PyExc_OSError, exc); - Py_XDECREF(exc); - return NULL; -} - - -/* - * Enable testing mode. This has the same effect as setting PSUTIL_TESTING - * env var. This dual method exists because updating os.environ on - * Windows has no effect. Called on unit tests setup. - */ -PyObject * -psutil_set_testing(PyObject *self, PyObject *args) { - PSUTIL_TESTING = 1; - Py_INCREF(Py_None); - return Py_None; -} - - -/* - * Print a debug message on stderr. No-op if PSUTIL_DEBUG env var is not set. - */ -void -psutil_debug(const char* format, ...) { - va_list argptr; - if (PSUTIL_DEBUG) { - va_start(argptr, format); - fprintf(stderr, "psutil-debug> "); - vfprintf(stderr, format, argptr); - fprintf(stderr, "\n"); - va_end(argptr); - } -} - - -/* - * Called on module import on all platforms. - */ -int -psutil_setup(void) { - if (getenv("PSUTIL_DEBUG") != NULL) - PSUTIL_DEBUG = 1; - if (getenv("PSUTIL_TESTING") != NULL) - PSUTIL_TESTING = 1; - return 0; -} diff --git a/ddtrace/vendor/psutil/_psutil_common.h b/ddtrace/vendor/psutil/_psutil_common.h deleted file mode 100644 index 7f58ad17382..00000000000 --- a/ddtrace/vendor/psutil/_psutil_common.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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. - */ - -#ifndef PSUTIL_PSUTIL_COMMON_H -#define PSUTIL_PSUTIL_COMMON_H - -#include - -extern int PSUTIL_TESTING; -extern int PSUTIL_DEBUG; - -// a signaler for connections without an actual status -static const int PSUTIL_CONN_NONE = 128; - -#if PY_MAJOR_VERSION < 3 -PyObject* PyUnicode_DecodeFSDefault(char *s); -PyObject* PyUnicode_DecodeFSDefaultAndSize(char *s, Py_ssize_t size); -#endif - -PyObject* AccessDenied(const char *msg); -PyObject* NoSuchProcess(const char *msg); -PyObject* PyErr_SetFromOSErrnoWithSyscall(const char *syscall); - -PyObject* psutil_set_testing(PyObject *self, PyObject *args); -void psutil_debug(const char* format, ...); -int psutil_setup(void); - -#endif // PSUTIL_PSUTIL_COMMON_H diff --git a/ddtrace/vendor/psutil/_psutil_linux.c b/ddtrace/vendor/psutil/_psutil_linux.c deleted file mode 100644 index 0d16eb42761..00000000000 --- a/ddtrace/vendor/psutil/_psutil_linux.c +++ /dev/null @@ -1,668 +0,0 @@ -/* - * 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. - * - * Linux-specific functions. - */ - -#ifndef _GNU_SOURCE - #define _GNU_SOURCE 1 -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// see: https://github.com/giampaolo/psutil/issues/659 -#ifdef PSUTIL_ETHTOOL_MISSING_TYPES - #include - typedef __u64 u64; - typedef __u32 u32; - typedef __u16 u16; - typedef __u8 u8; -#endif -/* Avoid redefinition of struct sysinfo with musl libc */ -#define _LINUX_SYSINFO_H -#include - -/* The minimum number of CPUs allocated in a cpu_set_t */ -static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT; - -// Linux >= 2.6.13 -#define PSUTIL_HAVE_IOPRIO defined(__NR_ioprio_get) && defined(__NR_ioprio_set) - -// Linux >= 2.6.36 (supposedly) and glibc >= 13 -#define PSUTIL_HAVE_PRLIMIT \ - (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)) && \ - (__GLIBC__ >= 2 && __GLIBC_MINOR__ >= 13) && \ - defined(__NR_prlimit64) - -#if PSUTIL_HAVE_PRLIMIT - #define _FILE_OFFSET_BITS 64 - #include - #include -#endif - -// Should exist starting from CentOS 6 (year 2011). -#ifdef CPU_ALLOC - #define PSUTIL_HAVE_CPU_AFFINITY -#endif - -#include "_psutil_common.h" -#include "_psutil_posix.h" - -// May happen on old RedHat versions, see: -// https://github.com/giampaolo/psutil/issues/607 -#ifndef DUPLEX_UNKNOWN - #define DUPLEX_UNKNOWN 0xff -#endif - - -#if PSUTIL_HAVE_IOPRIO -enum { - IOPRIO_WHO_PROCESS = 1, -}; - -static inline int -ioprio_get(int which, int who) { - return syscall(__NR_ioprio_get, which, who); -} - -static inline int -ioprio_set(int which, int who, int ioprio) { - return syscall(__NR_ioprio_set, which, who, ioprio); -} - -#define IOPRIO_CLASS_SHIFT 13 -#define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1) - -#define IOPRIO_PRIO_CLASS(mask) ((mask) >> IOPRIO_CLASS_SHIFT) -#define IOPRIO_PRIO_DATA(mask) ((mask) & IOPRIO_PRIO_MASK) -#define IOPRIO_PRIO_VALUE(class, data) (((class) << IOPRIO_CLASS_SHIFT) | data) - - -/* - * Return a (ioclass, iodata) Python tuple representing process I/O priority. - */ -static PyObject * -psutil_proc_ioprio_get(PyObject *self, PyObject *args) { - long pid; - int ioprio, ioclass, iodata; - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - ioprio = ioprio_get(IOPRIO_WHO_PROCESS, pid); - if (ioprio == -1) - return PyErr_SetFromErrno(PyExc_OSError); - ioclass = IOPRIO_PRIO_CLASS(ioprio); - iodata = IOPRIO_PRIO_DATA(ioprio); - return Py_BuildValue("ii", ioclass, iodata); -} - - -/* - * A wrapper around ioprio_set(); sets process I/O priority. - * ioclass can be either IOPRIO_CLASS_RT, IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE - * or 0. iodata goes from 0 to 7 depending on ioclass specified. - */ -static PyObject * -psutil_proc_ioprio_set(PyObject *self, PyObject *args) { - long pid; - int ioprio, ioclass, iodata; - int retval; - - if (! PyArg_ParseTuple(args, "lii", &pid, &ioclass, &iodata)) - return NULL; - ioprio = IOPRIO_PRIO_VALUE(ioclass, iodata); - retval = ioprio_set(IOPRIO_WHO_PROCESS, pid, ioprio); - if (retval == -1) - return PyErr_SetFromErrno(PyExc_OSError); - Py_RETURN_NONE; -} -#endif - - -#if PSUTIL_HAVE_PRLIMIT -/* - * A wrapper around prlimit(2); sets process resource limits. - * This can be used for both get and set, in which case extra - * 'soft' and 'hard' args must be provided. - */ -static PyObject * -psutil_linux_prlimit(PyObject *self, PyObject *args) { - long pid; - int ret, resource; - struct rlimit old, new; - struct rlimit *newp = NULL; - PyObject *py_soft = NULL; - PyObject *py_hard = NULL; - - if (! PyArg_ParseTuple(args, "li|OO", &pid, &resource, &py_soft, &py_hard)) - return NULL; - - // get - if (py_soft == NULL && py_hard == NULL) { - ret = prlimit(pid, resource, NULL, &old); - if (ret == -1) - return PyErr_SetFromErrno(PyExc_OSError); -#if defined(PSUTIL_HAVE_LONG_LONG) - if (sizeof(old.rlim_cur) > sizeof(long)) { - return Py_BuildValue("LL", - (PY_LONG_LONG)old.rlim_cur, - (PY_LONG_LONG)old.rlim_max); - } -#endif - return Py_BuildValue("ll", (long)old.rlim_cur, (long)old.rlim_max); - } - - // set - else { -#if defined(PSUTIL_HAVE_LARGEFILE_SUPPORT) - new.rlim_cur = PyLong_AsLongLong(py_soft); - if (new.rlim_cur == (rlim_t) - 1 && PyErr_Occurred()) - return NULL; - new.rlim_max = PyLong_AsLongLong(py_hard); - if (new.rlim_max == (rlim_t) - 1 && PyErr_Occurred()) - return NULL; -#else - new.rlim_cur = PyLong_AsLong(py_soft); - if (new.rlim_cur == (rlim_t) - 1 && PyErr_Occurred()) - return NULL; - new.rlim_max = PyLong_AsLong(py_hard); - if (new.rlim_max == (rlim_t) - 1 && PyErr_Occurred()) - return NULL; -#endif - newp = &new; - ret = prlimit(pid, resource, newp, &old); - if (ret == -1) - return PyErr_SetFromErrno(PyExc_OSError); - Py_RETURN_NONE; - } -} -#endif - - -/* - * Return disk mounted partitions as a list of tuples including device, - * mount point and filesystem type - */ -static PyObject * -psutil_disk_partitions(PyObject *self, PyObject *args) { - FILE *file = NULL; - struct mntent *entry; - const char *mtab_path; - PyObject *py_dev = NULL; - PyObject *py_mountp = NULL; - PyObject *py_tuple = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - - if (!PyArg_ParseTuple(args, "s", &mtab_path)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - file = setmntent(mtab_path, "r"); - Py_END_ALLOW_THREADS - if ((file == 0) || (file == NULL)) { - psutil_debug("setmntent() failed"); - PyErr_SetFromErrnoWithFilename(PyExc_OSError, mtab_path); - goto error; - } - - while ((entry = getmntent(file))) { - if (entry == NULL) { - PyErr_Format(PyExc_RuntimeError, "getmntent() syscall failed"); - goto error; - } - py_dev = PyUnicode_DecodeFSDefault(entry->mnt_fsname); - if (! py_dev) - goto error; - py_mountp = PyUnicode_DecodeFSDefault(entry->mnt_dir); - if (! py_mountp) - goto error; - py_tuple = Py_BuildValue("(OOss)", - py_dev, // device - py_mountp, // mount point - entry->mnt_type, // fs type - entry->mnt_opts); // options - if (! py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_dev); - Py_CLEAR(py_mountp); - Py_CLEAR(py_tuple); - } - endmntent(file); - return py_retlist; - -error: - if (file != NULL) - endmntent(file); - Py_XDECREF(py_dev); - Py_XDECREF(py_mountp); - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - return NULL; -} - - -/* - * A wrapper around sysinfo(), return system memory usage statistics. - */ -static PyObject * -psutil_linux_sysinfo(PyObject *self, PyObject *args) { - struct sysinfo info; - - if (sysinfo(&info) != 0) - return PyErr_SetFromErrno(PyExc_OSError); - // note: boot time might also be determined from here - return Py_BuildValue( - "(kkkkkkI)", - info.totalram, // total - info.freeram, // free - info.bufferram, // buffer - info.sharedram, // shared - info.totalswap, // swap tot - info.freeswap, // swap free - info.mem_unit // multiplier - ); -} - - -/* - * Return process CPU affinity as a Python list - */ -#ifdef PSUTIL_HAVE_CPU_AFFINITY - -static PyObject * -psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args) { - int cpu, ncpus, count, cpucount_s; - long pid; - size_t setsize; - cpu_set_t *mask = NULL; - PyObject *py_list = NULL; - - if (!PyArg_ParseTuple(args, "l", &pid)) - return NULL; - ncpus = NCPUS_START; - while (1) { - setsize = CPU_ALLOC_SIZE(ncpus); - mask = CPU_ALLOC(ncpus); - if (mask == NULL) { - psutil_debug("CPU_ALLOC() failed"); - return PyErr_NoMemory(); - } - if (sched_getaffinity(pid, setsize, mask) == 0) - break; - CPU_FREE(mask); - if (errno != EINVAL) - return PyErr_SetFromErrno(PyExc_OSError); - if (ncpus > INT_MAX / 2) { - PyErr_SetString(PyExc_OverflowError, "could not allocate " - "a large enough CPU set"); - return NULL; - } - ncpus = ncpus * 2; - } - - py_list = PyList_New(0); - if (py_list == NULL) - goto error; - - cpucount_s = CPU_COUNT_S(setsize, mask); - for (cpu = 0, count = cpucount_s; count; cpu++) { - if (CPU_ISSET_S(cpu, setsize, mask)) { -#if PY_MAJOR_VERSION >= 3 - PyObject *cpu_num = PyLong_FromLong(cpu); -#else - PyObject *cpu_num = PyInt_FromLong(cpu); -#endif - if (cpu_num == NULL) - goto error; - if (PyList_Append(py_list, cpu_num)) { - Py_DECREF(cpu_num); - goto error; - } - Py_DECREF(cpu_num); - --count; - } - } - CPU_FREE(mask); - return py_list; - -error: - if (mask) - CPU_FREE(mask); - Py_XDECREF(py_list); - return NULL; -} - - -/* - * Set process CPU affinity; expects a bitmask - */ -static PyObject * -psutil_proc_cpu_affinity_set(PyObject *self, PyObject *args) { - cpu_set_t cpu_set; - size_t len; - long pid; - int i, seq_len; - PyObject *py_cpu_set; - PyObject *py_cpu_seq = NULL; - - if (!PyArg_ParseTuple(args, "lO", &pid, &py_cpu_set)) - return NULL; - - if (!PySequence_Check(py_cpu_set)) { - PyErr_Format(PyExc_TypeError, "sequence argument expected, got %s", - Py_TYPE(py_cpu_set)->tp_name); - goto error; - } - - py_cpu_seq = PySequence_Fast(py_cpu_set, "expected a sequence or integer"); - if (!py_cpu_seq) - goto error; - seq_len = PySequence_Fast_GET_SIZE(py_cpu_seq); - CPU_ZERO(&cpu_set); - for (i = 0; i < seq_len; i++) { - PyObject *item = PySequence_Fast_GET_ITEM(py_cpu_seq, i); -#if PY_MAJOR_VERSION >= 3 - long value = PyLong_AsLong(item); -#else - long value = PyInt_AsLong(item); -#endif - if ((value == -1) || PyErr_Occurred()) { - if (!PyErr_Occurred()) - PyErr_SetString(PyExc_ValueError, "invalid CPU value"); - goto error; - } - CPU_SET(value, &cpu_set); - } - - len = sizeof(cpu_set); - if (sched_setaffinity(pid, len, &cpu_set)) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - Py_DECREF(py_cpu_seq); - Py_RETURN_NONE; - -error: - if (py_cpu_seq != NULL) - Py_DECREF(py_cpu_seq); - return NULL; -} -#endif /* PSUTIL_HAVE_CPU_AFFINITY */ - - -/* - * Return currently connected users as a list of tuples. - */ -static PyObject * -psutil_users(PyObject *self, PyObject *args) { - struct utmp *ut; - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - PyObject *py_username = NULL; - PyObject *py_tty = NULL; - PyObject *py_hostname = NULL; - PyObject *py_user_proc = NULL; - - if (py_retlist == NULL) - return NULL; - setutent(); - while (NULL != (ut = getutent())) { - py_tuple = NULL; - py_user_proc = NULL; - if (ut->ut_type == USER_PROCESS) - py_user_proc = Py_True; - else - py_user_proc = Py_False; - py_username = PyUnicode_DecodeFSDefault(ut->ut_user); - if (! py_username) - goto error; - py_tty = PyUnicode_DecodeFSDefault(ut->ut_line); - if (! py_tty) - goto error; - py_hostname = PyUnicode_DecodeFSDefault(ut->ut_host); - if (! py_hostname) - goto error; - py_tuple = Py_BuildValue( - "(OOOfOi)", - py_username, // username - py_tty, // tty - py_hostname, // hostname - (float)ut->ut_tv.tv_sec, // tstamp - py_user_proc, // (bool) user process - ut->ut_pid // process id - ); - if (! py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_username); - Py_CLEAR(py_tty); - Py_CLEAR(py_hostname); - Py_CLEAR(py_tuple); - } - endutent(); - return py_retlist; - -error: - Py_XDECREF(py_username); - Py_XDECREF(py_tty); - Py_XDECREF(py_hostname); - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - endutent(); - return NULL; -} - - -/* - * Return stats about a particular network - * interface. References: - * https://github.com/dpaleino/wicd/blob/master/wicd/backends/be-ioctl.py - * http://www.i-scream.org/libstatgrab/ - */ -static PyObject* -psutil_net_if_duplex_speed(PyObject* self, PyObject* args) { - char *nic_name; - int sock = 0; - int ret; - int duplex; - int speed; - struct ifreq ifr; - struct ethtool_cmd ethcmd; - PyObject *py_retlist = NULL; - - if (! PyArg_ParseTuple(args, "s", &nic_name)) - return NULL; - - sock = socket(AF_INET, SOCK_DGRAM, 0); - if (sock == -1) - return PyErr_SetFromOSErrnoWithSyscall("socket()"); - strncpy(ifr.ifr_name, nic_name, sizeof(ifr.ifr_name)); - - // duplex and speed - memset(ðcmd, 0, sizeof ethcmd); - ethcmd.cmd = ETHTOOL_GSET; - ifr.ifr_data = (void *)ðcmd; - ret = ioctl(sock, SIOCETHTOOL, &ifr); - - if (ret != -1) { - duplex = ethcmd.duplex; - speed = ethcmd.speed; - } - else { - if ((errno == EOPNOTSUPP) || (errno == EINVAL)) { - // EOPNOTSUPP may occur in case of wi-fi cards. - // For EINVAL see: - // https://github.com/giampaolo/psutil/issues/797 - // #issuecomment-202999532 - duplex = DUPLEX_UNKNOWN; - speed = 0; - } - else { - PyErr_SetFromOSErrnoWithSyscall("ioctl(SIOCETHTOOL)"); - goto error; - } - } - - py_retlist = Py_BuildValue("[ii]", duplex, speed); - if (!py_retlist) - goto error; - close(sock); - return py_retlist; - -error: - if (sock != -1) - close(sock); - return NULL; -} - - -/* - * Module init. - */ - -static PyMethodDef mod_methods[] = { - // --- per-process functions - -#ifdef PSUTIL_HAVE_IOPRIO - {"proc_ioprio_get", psutil_proc_ioprio_get, METH_VARARGS, - "Get process I/O priority"}, - {"proc_ioprio_set", psutil_proc_ioprio_set, METH_VARARGS, - "Set process I/O priority"}, -#endif -#ifdef PSUTIL_HAVE_CPU_AFFINITY - {"proc_cpu_affinity_get", psutil_proc_cpu_affinity_get, METH_VARARGS, - "Return process CPU affinity as a Python long (the bitmask)."}, - {"proc_cpu_affinity_set", psutil_proc_cpu_affinity_set, METH_VARARGS, - "Set process CPU affinity; expects a bitmask."}, -#endif - - // --- system related functions - - {"disk_partitions", psutil_disk_partitions, METH_VARARGS, - "Return disk mounted partitions as a list of tuples including " - "device, mount point and filesystem type"}, - {"users", psutil_users, METH_VARARGS, - "Return currently connected users as a list of tuples"}, - {"net_if_duplex_speed", psutil_net_if_duplex_speed, METH_VARARGS, - "Return duplex and speed info about a NIC"}, - - // --- linux specific - - {"linux_sysinfo", psutil_linux_sysinfo, METH_VARARGS, - "A wrapper around sysinfo(), return system memory usage statistics"}, -#if PSUTIL_HAVE_PRLIMIT - {"linux_prlimit", psutil_linux_prlimit, METH_VARARGS, - "Get or set process resource limits."}, -#endif - // --- others - {"set_testing", psutil_set_testing, METH_NOARGS, - "Set psutil in testing mode"}, - - {NULL, NULL, 0, NULL} -}; - - -#if PY_MAJOR_VERSION >= 3 - #define INITERR return NULL - - static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, - "_psutil_linux", - NULL, - -1, - mod_methods, - NULL, - NULL, - NULL, - NULL - }; - - PyObject *PyInit__psutil_linux(void) -#else /* PY_MAJOR_VERSION */ - #define INITERR return - - void init_psutil_linux(void) -#endif /* PY_MAJOR_VERSION */ -{ - PyObject *v; -#if PY_MAJOR_VERSION >= 3 - PyObject *mod = PyModule_Create(&moduledef); -#else - PyObject *mod = Py_InitModule("_psutil_linux", mod_methods); -#endif - if (mod == NULL) - INITERR; - - if (PyModule_AddIntConstant(mod, "version", PSUTIL_VERSION)) INITERR; -#if PSUTIL_HAVE_PRLIMIT - if (PyModule_AddIntConstant(mod, "RLIMIT_AS", RLIMIT_AS)) INITERR; - if (PyModule_AddIntConstant(mod, "RLIMIT_CORE", RLIMIT_CORE)) INITERR; - if (PyModule_AddIntConstant(mod, "RLIMIT_CPU", RLIMIT_CPU)) INITERR; - if (PyModule_AddIntConstant(mod, "RLIMIT_DATA", RLIMIT_DATA)) INITERR; - if (PyModule_AddIntConstant(mod, "RLIMIT_FSIZE", RLIMIT_FSIZE)) INITERR; - if (PyModule_AddIntConstant(mod, "RLIMIT_LOCKS", RLIMIT_LOCKS)) INITERR; - if (PyModule_AddIntConstant(mod, "RLIMIT_MEMLOCK", RLIMIT_MEMLOCK)) INITERR; - if (PyModule_AddIntConstant(mod, "RLIMIT_NOFILE", RLIMIT_NOFILE)) INITERR; - if (PyModule_AddIntConstant(mod, "RLIMIT_NPROC", RLIMIT_NPROC)) INITERR; - if (PyModule_AddIntConstant(mod, "RLIMIT_RSS", RLIMIT_RSS)) INITERR; - if (PyModule_AddIntConstant(mod, "RLIMIT_STACK", RLIMIT_STACK)) INITERR; - -#if defined(HAVE_LONG_LONG) - if (sizeof(RLIM_INFINITY) > sizeof(long)) { - v = PyLong_FromLongLong((PY_LONG_LONG) RLIM_INFINITY); - } else -#endif - { - v = PyLong_FromLong((long) RLIM_INFINITY); - } - if (v) { - PyModule_AddObject(mod, "RLIM_INFINITY", v); - } - -#ifdef RLIMIT_MSGQUEUE - if (PyModule_AddIntConstant(mod, "RLIMIT_MSGQUEUE", RLIMIT_MSGQUEUE)) INITERR; -#endif -#ifdef RLIMIT_NICE - if (PyModule_AddIntConstant(mod, "RLIMIT_NICE", RLIMIT_NICE)) INITERR; -#endif -#ifdef RLIMIT_RTPRIO - if (PyModule_AddIntConstant(mod, "RLIMIT_RTPRIO", RLIMIT_RTPRIO)) INITERR; -#endif -#ifdef RLIMIT_RTTIME - if (PyModule_AddIntConstant(mod, "RLIMIT_RTTIME", RLIMIT_RTTIME)) INITERR; -#endif -#ifdef RLIMIT_SIGPENDING - if (PyModule_AddIntConstant(mod, "RLIMIT_SIGPENDING", RLIMIT_SIGPENDING)) - INITERR; -#endif -#endif - if (PyModule_AddIntConstant(mod, "DUPLEX_HALF", DUPLEX_HALF)) INITERR; - if (PyModule_AddIntConstant(mod, "DUPLEX_FULL", DUPLEX_FULL)) INITERR; - if (PyModule_AddIntConstant(mod, "DUPLEX_UNKNOWN", DUPLEX_UNKNOWN)) INITERR; - - if (mod == NULL) - INITERR; -#if PY_MAJOR_VERSION >= 3 - return mod; -#endif -} diff --git a/ddtrace/vendor/psutil/_psutil_osx.c b/ddtrace/vendor/psutil/_psutil_osx.c deleted file mode 100644 index 67b7e122c5a..00000000000 --- a/ddtrace/vendor/psutil/_psutil_osx.c +++ /dev/null @@ -1,1905 +0,0 @@ -/* - * 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. - * - * macOS platform-specific module methods. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "_psutil_common.h" -#include "_psutil_posix.h" -#include "arch/osx/process_info.h" - - -#define PSUTIL_TV2DOUBLE(t) ((t).tv_sec + (t).tv_usec / 1000000.0) - -static PyObject *ZombieProcessError; - - -/* - * A wrapper around host_statistics() invoked with HOST_VM_INFO. - */ -int -psutil_sys_vminfo(vm_statistics_data_t *vmstat) { - kern_return_t ret; - mach_msg_type_number_t count = sizeof(*vmstat) / sizeof(integer_t); - mach_port_t mport = mach_host_self(); - - ret = host_statistics(mport, HOST_VM_INFO, (host_info_t)vmstat, &count); - if (ret != KERN_SUCCESS) { - PyErr_Format( - PyExc_RuntimeError, - "host_statistics(HOST_VM_INFO) syscall failed: %s", - mach_error_string(ret)); - return 0; - } - mach_port_deallocate(mach_task_self(), mport); - return 1; -} - - -/* - * A wrapper around task_for_pid() which sucks big time: - * - it's not documented - * - errno is set only sometimes - * - sometimes errno is ENOENT (?!?) - * - for PIDs != getpid() or PIDs which are not members of the procmod - * it requires root - * As such we can only guess what the heck went wrong and fail either - * with NoSuchProcess, ZombieProcessError or giveup with AccessDenied. - * Here's some history: - * https://github.com/giampaolo/psutil/issues/1181 - * https://github.com/giampaolo/psutil/issues/1209 - * https://github.com/giampaolo/psutil/issues/1291#issuecomment-396062519 - */ -int -psutil_task_for_pid(long pid, mach_port_t *task) -{ - // See: https://github.com/giampaolo/psutil/issues/1181 - kern_return_t err = KERN_SUCCESS; - - err = task_for_pid(mach_task_self(), (pid_t)pid, task); - if (err != KERN_SUCCESS) { - if (psutil_pid_exists(pid) == 0) - NoSuchProcess("task_for_pid() failed"); - else if (psutil_is_zombie(pid) == 1) - PyErr_SetString(ZombieProcessError, "task_for_pid() failed"); - else { - psutil_debug( - "task_for_pid() failed (pid=%ld, err=%i, errno=%i, msg='%s'); " - "setting AccessDenied()", - pid, err, errno, mach_error_string(err)); - AccessDenied("task_for_pid() failed"); - } - return 1; - } - return 0; -} - - -/* - * Return a Python list of all the PIDs running on the system. - */ -static PyObject * -psutil_pids(PyObject *self, PyObject *args) { - kinfo_proc *proclist = NULL; - kinfo_proc *orig_address = NULL; - size_t num_processes; - size_t idx; - PyObject *py_pid = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - - if (psutil_get_proc_list(&proclist, &num_processes) != 0) - goto error; - - // save the address of proclist so we can free it later - orig_address = proclist; - for (idx = 0; idx < num_processes; idx++) { - py_pid = Py_BuildValue("i", proclist->kp_proc.p_pid); - if (! py_pid) - goto error; - if (PyList_Append(py_retlist, py_pid)) - goto error; - Py_CLEAR(py_pid); - proclist++; - } - free(orig_address); - - return py_retlist; - -error: - Py_XDECREF(py_pid); - Py_DECREF(py_retlist); - if (orig_address != NULL) - free(orig_address); - return NULL; -} - - -/* - * Return multiple process info as a Python tuple in one shot by - * using sysctl() and filling up a kinfo_proc struct. - * It should be possible to do this for all processes without - * incurring into permission (EPERM) errors. - * This will also succeed for zombie processes returning correct - * information. - */ -static PyObject * -psutil_proc_kinfo_oneshot(PyObject *self, PyObject *args) { - long pid; - struct kinfo_proc kp; - PyObject *py_name; - PyObject *py_retlist; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (psutil_get_kinfo_proc(pid, &kp) == -1) - return NULL; - - py_name = PyUnicode_DecodeFSDefault(kp.kp_proc.p_comm); - if (! py_name) { - // Likely a decoding error. We don't want to fail the whole - // operation. The python module may retry with proc_name(). - PyErr_Clear(); - py_name = Py_None; - } - - py_retlist = Py_BuildValue( - "lllllllidiO", - (long)kp.kp_eproc.e_ppid, // (long) ppid - (long)kp.kp_eproc.e_pcred.p_ruid, // (long) real uid - (long)kp.kp_eproc.e_ucred.cr_uid, // (long) effective uid - (long)kp.kp_eproc.e_pcred.p_svuid, // (long) saved uid - (long)kp.kp_eproc.e_pcred.p_rgid, // (long) real gid - (long)kp.kp_eproc.e_ucred.cr_groups[0], // (long) effective gid - (long)kp.kp_eproc.e_pcred.p_svgid, // (long) saved gid - kp.kp_eproc.e_tdev, // (int) tty nr - PSUTIL_TV2DOUBLE(kp.kp_proc.p_starttime), // (double) create time - (int)kp.kp_proc.p_stat, // (int) status - py_name // (pystr) name - ); - - if (py_retlist != NULL) { - // XXX shall we decref() also in case of Py_BuildValue() error? - Py_DECREF(py_name); - } - return py_retlist; -} - - -/* - * Return multiple process info as a Python tuple in one shot by - * using proc_pidinfo(PROC_PIDTASKINFO) and filling a proc_taskinfo - * struct. - * Contrarily from proc_kinfo above this function will fail with - * EACCES for PIDs owned by another user and with ESRCH for zombie - * processes. - */ -static PyObject * -psutil_proc_pidtaskinfo_oneshot(PyObject *self, PyObject *args) { - long pid; - struct proc_taskinfo pti; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (psutil_proc_pidinfo(pid, PROC_PIDTASKINFO, 0, &pti, sizeof(pti)) <= 0) - return NULL; - - return Py_BuildValue( - "(ddKKkkkk)", - (float)pti.pti_total_user / 1000000000.0, // (float) cpu user time - (float)pti.pti_total_system / 1000000000.0, // (float) cpu sys time - // Note about memory: determining other mem stats on macOS is a mess: - // http://www.opensource.apple.com/source/top/top-67/libtop.c?txt - // I just give up. - // struct proc_regioninfo pri; - // psutil_proc_pidinfo(pid, PROC_PIDREGIONINFO, 0, &pri, sizeof(pri)) - pti.pti_resident_size, // (uns long long) rss - pti.pti_virtual_size, // (uns long long) vms - pti.pti_faults, // (uns long) number of page faults (pages) - pti.pti_pageins, // (uns long) number of actual pageins (pages) - pti.pti_threadnum, // (uns long) num threads - // Unvoluntary value seems not to be available; - // pti.pti_csw probably refers to the sum of the two; - // getrusage() numbers seems to confirm this theory. - pti.pti_csw // (uns long) voluntary ctx switches - ); -} - - -/* - * Return process name from kinfo_proc as a Python string. - */ -static PyObject * -psutil_proc_name(PyObject *self, PyObject *args) { - long pid; - struct kinfo_proc kp; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (psutil_get_kinfo_proc(pid, &kp) == -1) - return NULL; - return PyUnicode_DecodeFSDefault(kp.kp_proc.p_comm); -} - - -/* - * Return process current working directory. - * Raises NSP in case of zombie process. - */ -static PyObject * -psutil_proc_cwd(PyObject *self, PyObject *args) { - long pid; - struct proc_vnodepathinfo pathinfo; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - if (psutil_proc_pidinfo( - pid, PROC_PIDVNODEPATHINFO, 0, &pathinfo, sizeof(pathinfo)) <= 0) - { - return NULL; - } - - return PyUnicode_DecodeFSDefault(pathinfo.pvi_cdir.vip_path); -} - - -/* - * Return path of the process executable. - */ -static PyObject * -psutil_proc_exe(PyObject *self, PyObject *args) { - long pid; - char buf[PATH_MAX]; - int ret; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - errno = 0; - ret = proc_pidpath((pid_t)pid, &buf, sizeof(buf)); - if (ret == 0) { - if (pid == 0) - AccessDenied(""); - else - psutil_raise_for_pid(pid, "proc_pidpath()"); - return NULL; - } - return PyUnicode_DecodeFSDefault(buf); -} - - -/* - * Return process cmdline as a Python list of cmdline arguments. - */ -static PyObject * -psutil_proc_cmdline(PyObject *self, PyObject *args) { - long pid; - PyObject *py_retlist = NULL; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - // get the commandline, defined in arch/osx/process_info.c - py_retlist = psutil_get_cmdline(pid); - return py_retlist; -} - - -/* - * Return process environment as a Python string. - */ -static PyObject * -psutil_proc_environ(PyObject *self, PyObject *args) { - long pid; - PyObject *py_retdict = NULL; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - // get the environment block, defined in arch/osx/process_info.c - py_retdict = psutil_get_environ(pid); - return py_retdict; -} - - -/* - * Return the number of logical CPUs in the system. - * XXX this could be shared with BSD. - */ -static PyObject * -psutil_cpu_count_logical(PyObject *self, PyObject *args) { - /* - int mib[2]; - int ncpu; - size_t len; - mib[0] = CTL_HW; - mib[1] = HW_NCPU; - len = sizeof(ncpu); - - if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1) - Py_RETURN_NONE; // mimic os.cpu_count() - else - return Py_BuildValue("i", ncpu); - */ - int num; - size_t size = sizeof(int); - - if (sysctlbyname("hw.logicalcpu", &num, &size, NULL, 2)) - Py_RETURN_NONE; // mimic os.cpu_count() - else - return Py_BuildValue("i", num); -} - - -/* - * Return the number of physical CPUs in the system. - */ -static PyObject * -psutil_cpu_count_phys(PyObject *self, PyObject *args) { - int num; - size_t size = sizeof(int); - - if (sysctlbyname("hw.physicalcpu", &num, &size, NULL, 0)) - Py_RETURN_NONE; // mimic os.cpu_count() - else - return Py_BuildValue("i", num); -} - - -/* - * Indicates if the given virtual address on the given architecture is in the - * shared VM region. - */ -static bool -psutil_in_shared_region(mach_vm_address_t addr, cpu_type_t type) { - mach_vm_address_t base; - mach_vm_address_t size; - - switch (type) { - case CPU_TYPE_ARM: - base = SHARED_REGION_BASE_ARM; - size = SHARED_REGION_SIZE_ARM; - break; - case CPU_TYPE_I386: - base = SHARED_REGION_BASE_I386; - size = SHARED_REGION_SIZE_I386; - break; - case CPU_TYPE_X86_64: - base = SHARED_REGION_BASE_X86_64; - size = SHARED_REGION_SIZE_X86_64; - break; - default: - return false; - } - - return base <= addr && addr < (base + size); -} - - -/* - * Returns the USS (unique set size) of the process. Reference: - * https://dxr.mozilla.org/mozilla-central/source/xpcom/base/ - * nsMemoryReporterManager.cpp - */ -static PyObject * -psutil_proc_memory_uss(PyObject *self, PyObject *args) { - long pid; - size_t len; - cpu_type_t cpu_type; - size_t private_pages = 0; - mach_vm_size_t size = 0; - mach_msg_type_number_t info_count = VM_REGION_TOP_INFO_COUNT; - kern_return_t kr; - vm_size_t page_size; - mach_vm_address_t addr = MACH_VM_MIN_ADDRESS; - mach_port_t task = MACH_PORT_NULL; - vm_region_top_info_data_t info; - mach_port_t object_name; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - if (psutil_task_for_pid(pid, &task) != 0) - return NULL; - - len = sizeof(cpu_type); - if (sysctlbyname("sysctl.proc_cputype", &cpu_type, &len, NULL, 0) != 0) { - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('sysctl.proc_cputype')"); - } - - // Roughly based on libtop_update_vm_regions in - // http://www.opensource.apple.com/source/top/top-100.1.2/libtop.c - for (addr = 0; ; addr += size) { - kr = mach_vm_region( - task, &addr, &size, VM_REGION_TOP_INFO, (vm_region_info_t)&info, - &info_count, &object_name); - if (kr == KERN_INVALID_ADDRESS) { - // Done iterating VM regions. - break; - } - else if (kr != KERN_SUCCESS) { - PyErr_Format( - PyExc_RuntimeError, - "mach_vm_region(VM_REGION_TOP_INFO) syscall failed"); - return NULL; - } - - if (psutil_in_shared_region(addr, cpu_type) && - info.share_mode != SM_PRIVATE) { - continue; - } - - switch (info.share_mode) { -#ifdef SM_LARGE_PAGE - case SM_LARGE_PAGE: - // NB: Large pages are not shareable and always resident. -#endif - case SM_PRIVATE: - private_pages += info.private_pages_resident; - private_pages += info.shared_pages_resident; - break; - case SM_COW: - private_pages += info.private_pages_resident; - if (info.ref_count == 1) { - // Treat copy-on-write pages as private if they only - // have one reference. - private_pages += info.shared_pages_resident; - } - break; - case SM_SHARED: - default: - break; - } - } - - mach_port_deallocate(mach_task_self(), task); - - if (host_page_size(mach_host_self(), &page_size) != KERN_SUCCESS) - page_size = PAGE_SIZE; - - return Py_BuildValue("K", private_pages * page_size); -} - - -/* - * Return system virtual memory stats. - * See: - * https://opensource.apple.com/source/system_cmds/system_cmds-790/ - * vm_stat.tproj/vm_stat.c.auto.html - */ -static PyObject * -psutil_virtual_mem(PyObject *self, PyObject *args) { - int mib[2]; - uint64_t total; - size_t len = sizeof(total); - vm_statistics_data_t vm; - int pagesize = PAGE_SIZE; - // physical mem - mib[0] = CTL_HW; - mib[1] = HW_MEMSIZE; - - // This is also available as sysctlbyname("hw.memsize"). - if (sysctl(mib, 2, &total, &len, NULL, 0)) { - if (errno != 0) - PyErr_SetFromErrno(PyExc_OSError); - else - PyErr_Format( - PyExc_RuntimeError, "sysctl(HW_MEMSIZE) syscall failed"); - return NULL; - } - - // vm - if (!psutil_sys_vminfo(&vm)) - return NULL; - - return Py_BuildValue( - "KKKKKK", - total, - (unsigned long long) vm.active_count * pagesize, // active - (unsigned long long) vm.inactive_count * pagesize, // inactive - (unsigned long long) vm.wire_count * pagesize, // wired - (unsigned long long) vm.free_count * pagesize, // free - (unsigned long long) vm.speculative_count * pagesize // speculative - ); -} - - -/* - * Return stats about swap memory. - */ -static PyObject * -psutil_swap_mem(PyObject *self, PyObject *args) { - int mib[2]; - size_t size; - struct xsw_usage totals; - vm_statistics_data_t vmstat; - int pagesize = PAGE_SIZE; - - mib[0] = CTL_VM; - mib[1] = VM_SWAPUSAGE; - size = sizeof(totals); - if (sysctl(mib, 2, &totals, &size, NULL, 0) == -1) { - if (errno != 0) - PyErr_SetFromErrno(PyExc_OSError); - else - PyErr_Format( - PyExc_RuntimeError, "sysctl(VM_SWAPUSAGE) syscall failed"); - return NULL; - } - if (!psutil_sys_vminfo(&vmstat)) - return NULL; - - return Py_BuildValue( - "LLLKK", - totals.xsu_total, - totals.xsu_used, - totals.xsu_avail, - (unsigned long long)vmstat.pageins * pagesize, - (unsigned long long)vmstat.pageouts * pagesize); -} - - -/* - * Return a Python tuple representing user, kernel and idle CPU times - */ -static PyObject * -psutil_cpu_times(PyObject *self, PyObject *args) { - mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT; - kern_return_t error; - host_cpu_load_info_data_t r_load; - - mach_port_t host_port = mach_host_self(); - error = host_statistics(host_port, HOST_CPU_LOAD_INFO, - (host_info_t)&r_load, &count); - if (error != KERN_SUCCESS) { - return PyErr_Format( - PyExc_RuntimeError, - "host_statistics(HOST_CPU_LOAD_INFO) syscall failed: %s", - mach_error_string(error)); - } - mach_port_deallocate(mach_task_self(), host_port); - - return Py_BuildValue( - "(dddd)", - (double)r_load.cpu_ticks[CPU_STATE_USER] / CLK_TCK, - (double)r_load.cpu_ticks[CPU_STATE_NICE] / CLK_TCK, - (double)r_load.cpu_ticks[CPU_STATE_SYSTEM] / CLK_TCK, - (double)r_load.cpu_ticks[CPU_STATE_IDLE] / CLK_TCK - ); -} - - -/* - * Return a Python list of tuple representing per-cpu times - */ -static PyObject * -psutil_per_cpu_times(PyObject *self, PyObject *args) { - natural_t cpu_count; - natural_t i; - processor_info_array_t info_array; - mach_msg_type_number_t info_count; - kern_return_t error; - processor_cpu_load_info_data_t *cpu_load_info = NULL; - int ret; - PyObject *py_retlist = PyList_New(0); - PyObject *py_cputime = NULL; - - if (py_retlist == NULL) - return NULL; - - mach_port_t host_port = mach_host_self(); - error = host_processor_info(host_port, PROCESSOR_CPU_LOAD_INFO, - &cpu_count, &info_array, &info_count); - if (error != KERN_SUCCESS) { - PyErr_Format( - PyExc_RuntimeError, - "host_processor_info(PROCESSOR_CPU_LOAD_INFO) syscall failed: %s", - mach_error_string(error)); - goto error; - } - mach_port_deallocate(mach_task_self(), host_port); - - cpu_load_info = (processor_cpu_load_info_data_t *) info_array; - - for (i = 0; i < cpu_count; i++) { - py_cputime = Py_BuildValue( - "(dddd)", - (double)cpu_load_info[i].cpu_ticks[CPU_STATE_USER] / CLK_TCK, - (double)cpu_load_info[i].cpu_ticks[CPU_STATE_NICE] / CLK_TCK, - (double)cpu_load_info[i].cpu_ticks[CPU_STATE_SYSTEM] / CLK_TCK, - (double)cpu_load_info[i].cpu_ticks[CPU_STATE_IDLE] / CLK_TCK - ); - if (!py_cputime) - goto error; - if (PyList_Append(py_retlist, py_cputime)) - goto error; - Py_CLEAR(py_cputime); - } - - ret = vm_deallocate(mach_task_self(), (vm_address_t)info_array, - info_count * sizeof(int)); - if (ret != KERN_SUCCESS) - PyErr_WarnEx(PyExc_RuntimeWarning, "vm_deallocate() failed", 2); - return py_retlist; - -error: - Py_XDECREF(py_cputime); - Py_DECREF(py_retlist); - if (cpu_load_info != NULL) { - ret = vm_deallocate(mach_task_self(), (vm_address_t)info_array, - info_count * sizeof(int)); - if (ret != KERN_SUCCESS) - PyErr_WarnEx(PyExc_RuntimeWarning, "vm_deallocate() failed", 2); - } - return NULL; -} - - -/* - * Retrieve CPU frequency. - */ -static PyObject * -psutil_cpu_freq(PyObject *self, PyObject *args) { - int64_t curr; - int64_t min; - int64_t max; - size_t size = sizeof(int64_t); - - if (sysctlbyname("hw.cpufrequency", &curr, &size, NULL, 0)) { - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('hw.cpufrequency')"); - } - if (sysctlbyname("hw.cpufrequency_min", &min, &size, NULL, 0)) { - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('hw.cpufrequency_min')"); - } - if (sysctlbyname("hw.cpufrequency_max", &max, &size, NULL, 0)) { - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('hw.cpufrequency_max')"); - } - - return Py_BuildValue( - "KKK", - curr / 1000 / 1000, - min / 1000 / 1000, - max / 1000 / 1000); -} - - -/* - * Return a Python float indicating the system boot time expressed in - * seconds since the epoch. - */ -static PyObject * -psutil_boot_time(PyObject *self, PyObject *args) { - // fetch sysctl "kern.boottime" - static int request[2] = { CTL_KERN, KERN_BOOTTIME }; - struct timeval result; - size_t result_len = sizeof result; - time_t boot_time = 0; - - if (sysctl(request, 2, &result, &result_len, NULL, 0) == -1) - return PyErr_SetFromErrno(PyExc_OSError); - boot_time = result.tv_sec; - return Py_BuildValue("f", (float)boot_time); -} - - -/* - * Return a list of tuples including device, mount point and fs type - * for all partitions mounted on the system. - */ -static PyObject * -psutil_disk_partitions(PyObject *self, PyObject *args) { - int num; - int i; - int len; - uint64_t flags; - char opts[400]; - struct statfs *fs = NULL; - PyObject *py_dev = NULL; - PyObject *py_mountp = NULL; - PyObject *py_tuple = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - - // get the number of mount points - Py_BEGIN_ALLOW_THREADS - num = getfsstat(NULL, 0, MNT_NOWAIT); - Py_END_ALLOW_THREADS - if (num == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - len = sizeof(*fs) * num; - fs = malloc(len); - if (fs == NULL) { - PyErr_NoMemory(); - goto error; - } - - Py_BEGIN_ALLOW_THREADS - num = getfsstat(fs, len, MNT_NOWAIT); - Py_END_ALLOW_THREADS - if (num == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (i = 0; i < num; i++) { - opts[0] = 0; - flags = fs[i].f_flags; - - // see sys/mount.h - if (flags & MNT_RDONLY) - strlcat(opts, "ro", sizeof(opts)); - else - strlcat(opts, "rw", sizeof(opts)); - if (flags & MNT_SYNCHRONOUS) - strlcat(opts, ",sync", sizeof(opts)); - if (flags & MNT_NOEXEC) - strlcat(opts, ",noexec", sizeof(opts)); - if (flags & MNT_NOSUID) - strlcat(opts, ",nosuid", sizeof(opts)); - if (flags & MNT_UNION) - strlcat(opts, ",union", sizeof(opts)); - if (flags & MNT_ASYNC) - strlcat(opts, ",async", sizeof(opts)); - if (flags & MNT_EXPORTED) - strlcat(opts, ",exported", sizeof(opts)); - if (flags & MNT_QUARANTINE) - strlcat(opts, ",quarantine", sizeof(opts)); - if (flags & MNT_LOCAL) - strlcat(opts, ",local", sizeof(opts)); - if (flags & MNT_QUOTA) - strlcat(opts, ",quota", sizeof(opts)); - if (flags & MNT_ROOTFS) - strlcat(opts, ",rootfs", sizeof(opts)); - if (flags & MNT_DOVOLFS) - strlcat(opts, ",dovolfs", sizeof(opts)); - if (flags & MNT_DONTBROWSE) - strlcat(opts, ",dontbrowse", sizeof(opts)); - if (flags & MNT_IGNORE_OWNERSHIP) - strlcat(opts, ",ignore-ownership", sizeof(opts)); - if (flags & MNT_AUTOMOUNTED) - strlcat(opts, ",automounted", sizeof(opts)); - if (flags & MNT_JOURNALED) - strlcat(opts, ",journaled", sizeof(opts)); - if (flags & MNT_NOUSERXATTR) - strlcat(opts, ",nouserxattr", sizeof(opts)); - if (flags & MNT_DEFWRITE) - strlcat(opts, ",defwrite", sizeof(opts)); - if (flags & MNT_MULTILABEL) - strlcat(opts, ",multilabel", sizeof(opts)); - if (flags & MNT_NOATIME) - strlcat(opts, ",noatime", sizeof(opts)); - if (flags & MNT_UPDATE) - strlcat(opts, ",update", sizeof(opts)); - if (flags & MNT_RELOAD) - strlcat(opts, ",reload", sizeof(opts)); - if (flags & MNT_FORCE) - strlcat(opts, ",force", sizeof(opts)); - if (flags & MNT_CMDFLAGS) - strlcat(opts, ",cmdflags", sizeof(opts)); - - py_dev = PyUnicode_DecodeFSDefault(fs[i].f_mntfromname); - if (! py_dev) - goto error; - py_mountp = PyUnicode_DecodeFSDefault(fs[i].f_mntonname); - if (! py_mountp) - goto error; - py_tuple = Py_BuildValue( - "(OOss)", - py_dev, // device - py_mountp, // mount point - fs[i].f_fstypename, // fs type - opts); // options - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_dev); - Py_CLEAR(py_mountp); - Py_CLEAR(py_tuple); - } - - free(fs); - return py_retlist; - -error: - Py_XDECREF(py_dev); - Py_XDECREF(py_mountp); - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (fs != NULL) - free(fs); - return NULL; -} - - -/* - * Return process threads - */ -static PyObject * -psutil_proc_threads(PyObject *self, PyObject *args) { - long pid; - int err, ret; - kern_return_t kr; - unsigned int info_count = TASK_BASIC_INFO_COUNT; - mach_port_t task = MACH_PORT_NULL; - struct task_basic_info tasks_info; - thread_act_port_array_t thread_list = NULL; - thread_info_data_t thinfo_basic; - thread_basic_info_t basic_info_th; - mach_msg_type_number_t thread_count, thread_info_count, j; - - PyObject *py_tuple = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - - if (! PyArg_ParseTuple(args, "l", &pid)) - goto error; - - if (psutil_task_for_pid(pid, &task) != 0) - goto error; - - info_count = TASK_BASIC_INFO_COUNT; - err = task_info(task, TASK_BASIC_INFO, (task_info_t)&tasks_info, - &info_count); - if (err != KERN_SUCCESS) { - // errcode 4 is "invalid argument" (access denied) - if (err == 4) { - AccessDenied(""); - } - else { - // otherwise throw a runtime error with appropriate error code - PyErr_Format(PyExc_RuntimeError, - "task_info(TASK_BASIC_INFO) syscall failed"); - } - goto error; - } - - err = task_threads(task, &thread_list, &thread_count); - if (err != KERN_SUCCESS) { - PyErr_Format(PyExc_RuntimeError, "task_threads() syscall failed"); - goto error; - } - - for (j = 0; j < thread_count; j++) { - thread_info_count = THREAD_INFO_MAX; - kr = thread_info(thread_list[j], THREAD_BASIC_INFO, - (thread_info_t)thinfo_basic, &thread_info_count); - if (kr != KERN_SUCCESS) { - PyErr_Format(PyExc_RuntimeError, - "thread_info(THREAD_BASIC_INFO) syscall failed"); - goto error; - } - - basic_info_th = (thread_basic_info_t)thinfo_basic; - py_tuple = Py_BuildValue( - "Iff", - j + 1, - basic_info_th->user_time.seconds + \ - (float)basic_info_th->user_time.microseconds / 1000000.0, - basic_info_th->system_time.seconds + \ - (float)basic_info_th->system_time.microseconds / 1000000.0 - ); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_tuple); - } - - ret = vm_deallocate(task, (vm_address_t)thread_list, - thread_count * sizeof(int)); - if (ret != KERN_SUCCESS) - PyErr_WarnEx(PyExc_RuntimeWarning, "vm_deallocate() failed", 2); - - mach_port_deallocate(mach_task_self(), task); - - return py_retlist; - -error: - if (task != MACH_PORT_NULL) - mach_port_deallocate(mach_task_self(), task); - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (thread_list != NULL) { - ret = vm_deallocate(task, (vm_address_t)thread_list, - thread_count * sizeof(int)); - if (ret != KERN_SUCCESS) - PyErr_WarnEx(PyExc_RuntimeWarning, "vm_deallocate() failed", 2); - } - return NULL; -} - - -/* - * Return process open files as a Python tuple. - * References: - * - lsof source code: http://goo.gl/SYW79 and http://goo.gl/m78fd - * - /usr/include/sys/proc_info.h - */ -static PyObject * -psutil_proc_open_files(PyObject *self, PyObject *args) { - long pid; - int pidinfo_result; - int iterations; - int i; - unsigned long nb; - - struct proc_fdinfo *fds_pointer = NULL; - struct proc_fdinfo *fdp_pointer; - struct vnode_fdinfowithpath vi; - - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - PyObject *py_path = NULL; - - if (py_retlist == NULL) - return NULL; - - if (! PyArg_ParseTuple(args, "l", &pid)) - goto error; - - pidinfo_result = psutil_proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0); - if (pidinfo_result <= 0) - goto error; - - fds_pointer = malloc(pidinfo_result); - if (fds_pointer == NULL) { - PyErr_NoMemory(); - goto error; - } - pidinfo_result = psutil_proc_pidinfo( - pid, PROC_PIDLISTFDS, 0, fds_pointer, pidinfo_result); - if (pidinfo_result <= 0) - goto error; - - iterations = (pidinfo_result / PROC_PIDLISTFD_SIZE); - - for (i = 0; i < iterations; i++) { - fdp_pointer = &fds_pointer[i]; - - if (fdp_pointer->proc_fdtype == PROX_FDTYPE_VNODE) { - errno = 0; - nb = proc_pidfdinfo((pid_t)pid, - fdp_pointer->proc_fd, - PROC_PIDFDVNODEPATHINFO, - &vi, - sizeof(vi)); - - // --- errors checking - if ((nb <= 0) || nb < sizeof(vi)) { - if ((errno == ENOENT) || (errno == EBADF)) { - // no such file or directory or bad file descriptor; - // let's assume the file has been closed or removed - continue; - } - else { - psutil_raise_for_pid( - pid, "proc_pidinfo(PROC_PIDFDVNODEPATHINFO)"); - goto error; - } - } - // --- /errors checking - - // --- construct python list - py_path = PyUnicode_DecodeFSDefault(vi.pvip.vip_path); - if (! py_path) - goto error; - py_tuple = Py_BuildValue( - "(Oi)", - py_path, - (int)fdp_pointer->proc_fd); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_tuple); - Py_CLEAR(py_path); - // --- /construct python list - } - } - - free(fds_pointer); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_XDECREF(py_path); - Py_DECREF(py_retlist); - if (fds_pointer != NULL) - free(fds_pointer); - return NULL; // exception has already been set earlier -} - - -/* - * Return process TCP and UDP connections as a list of tuples. - * Raises NSP in case of zombie process. - * References: - * - lsof source code: http://goo.gl/SYW79 and http://goo.gl/wNrC0 - * - /usr/include/sys/proc_info.h - */ -static PyObject * -psutil_proc_connections(PyObject *self, PyObject *args) { - long pid; - int pidinfo_result; - int iterations; - int i; - unsigned long nb; - - struct proc_fdinfo *fds_pointer = NULL; - struct proc_fdinfo *fdp_pointer; - struct socket_fdinfo si; - - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - PyObject *py_laddr = NULL; - PyObject *py_raddr = NULL; - PyObject *py_af_filter = NULL; - PyObject *py_type_filter = NULL; - - if (py_retlist == NULL) - return NULL; - - if (! PyArg_ParseTuple(args, "lOO", &pid, &py_af_filter, &py_type_filter)) - goto error; - - if (!PySequence_Check(py_af_filter) || !PySequence_Check(py_type_filter)) { - PyErr_SetString(PyExc_TypeError, "arg 2 or 3 is not a sequence"); - goto error; - } - - if (pid == 0) - return py_retlist; - pidinfo_result = psutil_proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0); - if (pidinfo_result <= 0) - goto error; - - fds_pointer = malloc(pidinfo_result); - if (fds_pointer == NULL) { - PyErr_NoMemory(); - goto error; - } - - pidinfo_result = psutil_proc_pidinfo( - pid, PROC_PIDLISTFDS, 0, fds_pointer, pidinfo_result); - if (pidinfo_result <= 0) - goto error; - - iterations = (pidinfo_result / PROC_PIDLISTFD_SIZE); - for (i = 0; i < iterations; i++) { - py_tuple = NULL; - py_laddr = NULL; - py_raddr = NULL; - fdp_pointer = &fds_pointer[i]; - - if (fdp_pointer->proc_fdtype == PROX_FDTYPE_SOCKET) { - errno = 0; - nb = proc_pidfdinfo((pid_t)pid, fdp_pointer->proc_fd, - PROC_PIDFDSOCKETINFO, &si, sizeof(si)); - - // --- errors checking - if ((nb <= 0) || (nb < sizeof(si))) { - if (errno == EBADF) { - // let's assume socket has been closed - continue; - } - else { - psutil_raise_for_pid( - pid, "proc_pidinfo(PROC_PIDFDSOCKETINFO)"); - goto error; - } - } - // --- /errors checking - - // - int fd, family, type, lport, rport, state; - char lip[200], rip[200]; - int inseq; - PyObject *py_family; - PyObject *py_type; - - fd = (int)fdp_pointer->proc_fd; - family = si.psi.soi_family; - type = si.psi.soi_type; - - // apply filters - py_family = PyLong_FromLong((long)family); - inseq = PySequence_Contains(py_af_filter, py_family); - Py_DECREF(py_family); - if (inseq == 0) - continue; - py_type = PyLong_FromLong((long)type); - inseq = PySequence_Contains(py_type_filter, py_type); - Py_DECREF(py_type); - if (inseq == 0) - continue; - - if (errno != 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - if ((family == AF_INET) || (family == AF_INET6)) { - if (family == AF_INET) { - inet_ntop(AF_INET, - &si.psi.soi_proto.pri_tcp.tcpsi_ini. \ - insi_laddr.ina_46.i46a_addr4, - lip, - sizeof(lip)); - inet_ntop(AF_INET, - &si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_faddr. \ - ina_46.i46a_addr4, - rip, - sizeof(rip)); - } - else { - inet_ntop(AF_INET6, - &si.psi.soi_proto.pri_tcp.tcpsi_ini. \ - insi_laddr.ina_6, - lip, sizeof(lip)); - inet_ntop(AF_INET6, - &si.psi.soi_proto.pri_tcp.tcpsi_ini. \ - insi_faddr.ina_6, - rip, sizeof(rip)); - } - - // check for inet_ntop failures - if (errno != 0) { - PyErr_SetFromOSErrnoWithSyscall("inet_ntop()"); - goto error; - } - - lport = ntohs(si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_lport); - rport = ntohs(si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_fport); - if (type == SOCK_STREAM) - state = (int)si.psi.soi_proto.pri_tcp.tcpsi_state; - else - state = PSUTIL_CONN_NONE; - - py_laddr = Py_BuildValue("(si)", lip, lport); - if (!py_laddr) - goto error; - if (rport != 0) - py_raddr = Py_BuildValue("(si)", rip, rport); - else - py_raddr = Py_BuildValue("()"); - if (!py_raddr) - goto error; - - // construct the python list - py_tuple = Py_BuildValue( - "(iiiNNi)", fd, family, type, py_laddr, py_raddr, state); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_tuple); - } - else if (family == AF_UNIX) { - py_laddr = PyUnicode_DecodeFSDefault( - si.psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_path); - if (!py_laddr) - goto error; - py_raddr = PyUnicode_DecodeFSDefault( - si.psi.soi_proto.pri_un.unsi_caddr.ua_sun.sun_path); - if (!py_raddr) - goto error; - // construct the python list - py_tuple = Py_BuildValue( - "(iiiOOi)", - fd, family, type, - py_laddr, - py_raddr, - PSUTIL_CONN_NONE); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_tuple); - Py_CLEAR(py_laddr); - Py_CLEAR(py_raddr); - } - } - } - - free(fds_pointer); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_XDECREF(py_laddr); - Py_XDECREF(py_raddr); - Py_DECREF(py_retlist); - if (fds_pointer != NULL) - free(fds_pointer); - return NULL; -} - - -/* - * Return number of file descriptors opened by process. - * Raises NSP in case of zombie process. - */ -static PyObject * -psutil_proc_num_fds(PyObject *self, PyObject *args) { - long pid; - int pidinfo_result; - int num; - struct proc_fdinfo *fds_pointer; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - pidinfo_result = proc_pidinfo((pid_t)pid, PROC_PIDLISTFDS, 0, NULL, 0); - if (pidinfo_result <= 0) - return PyErr_SetFromErrno(PyExc_OSError); - - fds_pointer = malloc(pidinfo_result); - if (fds_pointer == NULL) - return PyErr_NoMemory(); - pidinfo_result = proc_pidinfo((pid_t)pid, PROC_PIDLISTFDS, 0, fds_pointer, - pidinfo_result); - if (pidinfo_result <= 0) { - free(fds_pointer); - return PyErr_SetFromErrno(PyExc_OSError); - } - - num = (pidinfo_result / PROC_PIDLISTFD_SIZE); - free(fds_pointer); - return Py_BuildValue("i", num); -} - - -/* - * Return a Python list of named tuples with overall network I/O information - */ -static PyObject * -psutil_net_io_counters(PyObject *self, PyObject *args) { - char *buf = NULL, *lim, *next; - struct if_msghdr *ifm; - int mib[6]; - mib[0] = CTL_NET; // networking subsystem - mib[1] = PF_ROUTE; // type of information - mib[2] = 0; // protocol (IPPROTO_xxx) - mib[3] = 0; // address family - mib[4] = NET_RT_IFLIST2; // operation - mib[5] = 0; - size_t len; - PyObject *py_ifc_info = NULL; - PyObject *py_retdict = PyDict_New(); - - if (py_retdict == NULL) - return NULL; - - if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - buf = malloc(len); - if (buf == NULL) { - PyErr_NoMemory(); - goto error; - } - - if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - lim = buf + len; - - for (next = buf; next < lim; ) { - ifm = (struct if_msghdr *)next; - next += ifm->ifm_msglen; - - if (ifm->ifm_type == RTM_IFINFO2) { - py_ifc_info = NULL; - struct if_msghdr2 *if2m = (struct if_msghdr2 *)ifm; - struct sockaddr_dl *sdl = (struct sockaddr_dl *)(if2m + 1); - char ifc_name[32]; - - strncpy(ifc_name, sdl->sdl_data, sdl->sdl_nlen); - ifc_name[sdl->sdl_nlen] = 0; - - py_ifc_info = Py_BuildValue( - "(KKKKKKKi)", - if2m->ifm_data.ifi_obytes, - if2m->ifm_data.ifi_ibytes, - if2m->ifm_data.ifi_opackets, - if2m->ifm_data.ifi_ipackets, - if2m->ifm_data.ifi_ierrors, - if2m->ifm_data.ifi_oerrors, - if2m->ifm_data.ifi_iqdrops, - 0); // dropout not supported - - if (!py_ifc_info) - goto error; - if (PyDict_SetItemString(py_retdict, ifc_name, py_ifc_info)) - goto error; - Py_CLEAR(py_ifc_info); - } - else { - continue; - } - } - - free(buf); - return py_retdict; - -error: - Py_XDECREF(py_ifc_info); - Py_DECREF(py_retdict); - if (buf != NULL) - free(buf); - return NULL; -} - - -/* - * Return a Python dict of tuples for disk I/O information - */ -static PyObject * -psutil_disk_io_counters(PyObject *self, PyObject *args) { - CFDictionaryRef parent_dict; - CFDictionaryRef props_dict; - CFDictionaryRef stats_dict; - io_registry_entry_t parent; - io_registry_entry_t disk; - io_iterator_t disk_list; - PyObject *py_disk_info = NULL; - PyObject *py_retdict = PyDict_New(); - - if (py_retdict == NULL) - return NULL; - - // Get list of disks - if (IOServiceGetMatchingServices(kIOMasterPortDefault, - IOServiceMatching(kIOMediaClass), - &disk_list) != kIOReturnSuccess) { - PyErr_SetString( - PyExc_RuntimeError, "unable to get the list of disks."); - goto error; - } - - // Iterate over disks - while ((disk = IOIteratorNext(disk_list)) != 0) { - py_disk_info = NULL; - parent_dict = NULL; - props_dict = NULL; - stats_dict = NULL; - - if (IORegistryEntryGetParentEntry(disk, kIOServicePlane, &parent) - != kIOReturnSuccess) { - PyErr_SetString(PyExc_RuntimeError, - "unable to get the disk's parent."); - IOObjectRelease(disk); - goto error; - } - - if (IOObjectConformsTo(parent, "IOBlockStorageDriver")) { - if (IORegistryEntryCreateCFProperties( - disk, - (CFMutableDictionaryRef *) &parent_dict, - kCFAllocatorDefault, - kNilOptions - ) != kIOReturnSuccess) - { - PyErr_SetString(PyExc_RuntimeError, - "unable to get the parent's properties."); - IOObjectRelease(disk); - IOObjectRelease(parent); - goto error; - } - - if (IORegistryEntryCreateCFProperties( - parent, - (CFMutableDictionaryRef *) &props_dict, - kCFAllocatorDefault, - kNilOptions - ) != kIOReturnSuccess) - { - PyErr_SetString(PyExc_RuntimeError, - "unable to get the disk properties."); - CFRelease(props_dict); - IOObjectRelease(disk); - IOObjectRelease(parent); - goto error; - } - - const int kMaxDiskNameSize = 64; - CFStringRef disk_name_ref = (CFStringRef)CFDictionaryGetValue( - parent_dict, CFSTR(kIOBSDNameKey)); - char disk_name[kMaxDiskNameSize]; - - CFStringGetCString(disk_name_ref, - disk_name, - kMaxDiskNameSize, - CFStringGetSystemEncoding()); - - stats_dict = (CFDictionaryRef)CFDictionaryGetValue( - props_dict, CFSTR(kIOBlockStorageDriverStatisticsKey)); - - if (stats_dict == NULL) { - PyErr_SetString(PyExc_RuntimeError, - "Unable to get disk stats."); - goto error; - } - - CFNumberRef number; - int64_t reads = 0; - int64_t writes = 0; - int64_t read_bytes = 0; - int64_t write_bytes = 0; - int64_t read_time = 0; - int64_t write_time = 0; - - // Get disk reads/writes - if ((number = (CFNumberRef)CFDictionaryGetValue( - stats_dict, - CFSTR(kIOBlockStorageDriverStatisticsReadsKey)))) - { - CFNumberGetValue(number, kCFNumberSInt64Type, &reads); - } - if ((number = (CFNumberRef)CFDictionaryGetValue( - stats_dict, - CFSTR(kIOBlockStorageDriverStatisticsWritesKey)))) - { - CFNumberGetValue(number, kCFNumberSInt64Type, &writes); - } - - // Get disk bytes read/written - if ((number = (CFNumberRef)CFDictionaryGetValue( - stats_dict, - CFSTR(kIOBlockStorageDriverStatisticsBytesReadKey)))) - { - CFNumberGetValue(number, kCFNumberSInt64Type, &read_bytes); - } - if ((number = (CFNumberRef)CFDictionaryGetValue( - stats_dict, - CFSTR(kIOBlockStorageDriverStatisticsBytesWrittenKey)))) - { - CFNumberGetValue(number, kCFNumberSInt64Type, &write_bytes); - } - - // Get disk time spent reading/writing (nanoseconds) - if ((number = (CFNumberRef)CFDictionaryGetValue( - stats_dict, - CFSTR(kIOBlockStorageDriverStatisticsTotalReadTimeKey)))) - { - CFNumberGetValue(number, kCFNumberSInt64Type, &read_time); - } - if ((number = (CFNumberRef)CFDictionaryGetValue( - stats_dict, - CFSTR(kIOBlockStorageDriverStatisticsTotalWriteTimeKey)))) - { - CFNumberGetValue(number, kCFNumberSInt64Type, &write_time); - } - - // Read/Write time on macOS comes back in nanoseconds and in psutil - // we've standardized on milliseconds so do the conversion. - py_disk_info = Py_BuildValue( - "(KKKKKK)", - reads, - writes, - read_bytes, - write_bytes, - read_time / 1000 / 1000, - write_time / 1000 / 1000); - if (!py_disk_info) - goto error; - if (PyDict_SetItemString(py_retdict, disk_name, py_disk_info)) - goto error; - Py_CLEAR(py_disk_info); - - CFRelease(parent_dict); - IOObjectRelease(parent); - CFRelease(props_dict); - IOObjectRelease(disk); - } - } - - IOObjectRelease (disk_list); - - return py_retdict; - -error: - Py_XDECREF(py_disk_info); - Py_DECREF(py_retdict); - return NULL; -} - - -/* - * Return currently connected users as a list of tuples. - */ -static PyObject * -psutil_users(PyObject *self, PyObject *args) { - struct utmpx *utx; - PyObject *py_username = NULL; - PyObject *py_tty = NULL; - PyObject *py_hostname = NULL; - PyObject *py_tuple = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - while ((utx = getutxent()) != NULL) { - if (utx->ut_type != USER_PROCESS) - continue; - py_username = PyUnicode_DecodeFSDefault(utx->ut_user); - if (! py_username) - goto error; - py_tty = PyUnicode_DecodeFSDefault(utx->ut_line); - if (! py_tty) - goto error; - py_hostname = PyUnicode_DecodeFSDefault(utx->ut_host); - if (! py_hostname) - goto error; - py_tuple = Py_BuildValue( - "(OOOfi)", - py_username, // username - py_tty, // tty - py_hostname, // hostname - (float)utx->ut_tv.tv_sec, // start time - utx->ut_pid // process id - ); - if (!py_tuple) { - endutxent(); - goto error; - } - if (PyList_Append(py_retlist, py_tuple)) { - endutxent(); - goto error; - } - Py_CLEAR(py_username); - Py_CLEAR(py_tty); - Py_CLEAR(py_hostname); - Py_CLEAR(py_tuple); - } - - endutxent(); - return py_retlist; - -error: - Py_XDECREF(py_username); - Py_XDECREF(py_tty); - Py_XDECREF(py_hostname); - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - return NULL; -} - - -/* - * Return CPU statistics. - */ -static PyObject * -psutil_cpu_stats(PyObject *self, PyObject *args) { - struct vmmeter vmstat; - kern_return_t ret; - mach_msg_type_number_t count = sizeof(vmstat) / sizeof(integer_t); - mach_port_t mport = mach_host_self(); - - ret = host_statistics(mport, HOST_VM_INFO, (host_info_t)&vmstat, &count); - if (ret != KERN_SUCCESS) { - PyErr_Format( - PyExc_RuntimeError, - "host_statistics(HOST_VM_INFO) failed: %s", - mach_error_string(ret)); - return NULL; - } - mach_port_deallocate(mach_task_self(), mport); - - return Py_BuildValue( - "IIIII", - vmstat.v_swtch, // ctx switches - vmstat.v_intr, // interrupts - vmstat.v_soft, // software interrupts - vmstat.v_syscall, // syscalls - vmstat.v_trap // traps - ); -} - - -/* - * Return battery information. - */ -static PyObject * -psutil_sensors_battery(PyObject *self, PyObject *args) { - PyObject *py_tuple = NULL; - CFTypeRef power_info = NULL; - CFArrayRef power_sources_list = NULL; - CFDictionaryRef power_sources_information = NULL; - CFNumberRef capacity_ref = NULL; - CFNumberRef time_to_empty_ref = NULL; - CFStringRef ps_state_ref = NULL; - uint32_t capacity; /* units are percent */ - int time_to_empty; /* units are minutes */ - int is_power_plugged; - - power_info = IOPSCopyPowerSourcesInfo(); - - if (!power_info) { - PyErr_SetString(PyExc_RuntimeError, - "IOPSCopyPowerSourcesInfo() syscall failed"); - goto error; - } - - power_sources_list = IOPSCopyPowerSourcesList(power_info); - if (!power_sources_list) { - PyErr_SetString(PyExc_RuntimeError, - "IOPSCopyPowerSourcesList() syscall failed"); - goto error; - } - - /* Should only get one source. But in practice, check for > 0 sources */ - if (!CFArrayGetCount(power_sources_list)) { - PyErr_SetString(PyExc_NotImplementedError, "no battery"); - goto error; - } - - power_sources_information = IOPSGetPowerSourceDescription( - power_info, CFArrayGetValueAtIndex(power_sources_list, 0)); - - capacity_ref = (CFNumberRef) CFDictionaryGetValue( - power_sources_information, CFSTR(kIOPSCurrentCapacityKey)); - if (!CFNumberGetValue(capacity_ref, kCFNumberSInt32Type, &capacity)) { - PyErr_SetString(PyExc_RuntimeError, - "No battery capacity infomration in power sources info"); - goto error; - } - - ps_state_ref = (CFStringRef) CFDictionaryGetValue( - power_sources_information, CFSTR(kIOPSPowerSourceStateKey)); - is_power_plugged = CFStringCompare( - ps_state_ref, CFSTR(kIOPSACPowerValue), 0) - == kCFCompareEqualTo; - - time_to_empty_ref = (CFNumberRef) CFDictionaryGetValue( - power_sources_information, CFSTR(kIOPSTimeToEmptyKey)); - if (!CFNumberGetValue(time_to_empty_ref, - kCFNumberIntType, &time_to_empty)) { - /* This value is recommended for non-Apple power sources, so it's not - * an error if it doesn't exist. We'll return -1 for "unknown" */ - /* A value of -1 indicates "Still Calculating the Time" also for - * apple power source */ - time_to_empty = -1; - } - - py_tuple = Py_BuildValue("Iii", - capacity, time_to_empty, is_power_plugged); - if (!py_tuple) { - goto error; - } - - CFRelease(power_info); - CFRelease(power_sources_list); - /* Caller should NOT release power_sources_information */ - - return py_tuple; - -error: - if (power_info) - CFRelease(power_info); - if (power_sources_list) - CFRelease(power_sources_list); - Py_XDECREF(py_tuple); - return NULL; -} - - -/* - * define the psutil C module methods and initialize the module. - */ -static PyMethodDef mod_methods[] = { - // --- per-process functions - - {"proc_kinfo_oneshot", psutil_proc_kinfo_oneshot, METH_VARARGS, - "Return multiple process info."}, - {"proc_pidtaskinfo_oneshot", psutil_proc_pidtaskinfo_oneshot, METH_VARARGS, - "Return multiple process info."}, - {"proc_name", psutil_proc_name, METH_VARARGS, - "Return process name"}, - {"proc_cmdline", psutil_proc_cmdline, METH_VARARGS, - "Return process cmdline as a list of cmdline arguments"}, - {"proc_environ", psutil_proc_environ, METH_VARARGS, - "Return process environment data"}, - {"proc_exe", psutil_proc_exe, METH_VARARGS, - "Return path of the process executable"}, - {"proc_cwd", psutil_proc_cwd, METH_VARARGS, - "Return process current working directory."}, - {"proc_memory_uss", psutil_proc_memory_uss, METH_VARARGS, - "Return process USS memory"}, - {"proc_threads", psutil_proc_threads, METH_VARARGS, - "Return process threads as a list of tuples"}, - {"proc_open_files", psutil_proc_open_files, METH_VARARGS, - "Return files opened by process as a list of tuples"}, - {"proc_num_fds", psutil_proc_num_fds, METH_VARARGS, - "Return the number of fds opened by process."}, - {"proc_connections", psutil_proc_connections, METH_VARARGS, - "Get process TCP and UDP connections as a list of tuples"}, - - // --- system-related functions - - {"pids", psutil_pids, METH_VARARGS, - "Returns a list of PIDs currently running on the system"}, - {"cpu_count_logical", psutil_cpu_count_logical, METH_VARARGS, - "Return number of logical CPUs on the system"}, - {"cpu_count_phys", psutil_cpu_count_phys, METH_VARARGS, - "Return number of physical CPUs on the system"}, - {"virtual_mem", psutil_virtual_mem, METH_VARARGS, - "Return system virtual memory stats"}, - {"swap_mem", psutil_swap_mem, METH_VARARGS, - "Return stats about swap memory, in bytes"}, - {"cpu_times", psutil_cpu_times, METH_VARARGS, - "Return system cpu times as a tuple (user, system, nice, idle, irc)"}, - {"per_cpu_times", psutil_per_cpu_times, METH_VARARGS, - "Return system per-cpu times as a list of tuples"}, - {"cpu_freq", psutil_cpu_freq, METH_VARARGS, - "Return cpu current frequency"}, - {"boot_time", psutil_boot_time, METH_VARARGS, - "Return the system boot time expressed in seconds since the epoch."}, - {"disk_partitions", psutil_disk_partitions, METH_VARARGS, - "Return a list of tuples including device, mount point and " - "fs type for all partitions mounted on the system."}, - {"net_io_counters", psutil_net_io_counters, METH_VARARGS, - "Return dict of tuples of networks I/O information."}, - {"disk_io_counters", psutil_disk_io_counters, METH_VARARGS, - "Return dict of tuples of disks I/O information."}, - {"users", psutil_users, METH_VARARGS, - "Return currently connected users as a list of tuples"}, - {"cpu_stats", psutil_cpu_stats, METH_VARARGS, - "Return CPU statistics"}, - {"sensors_battery", psutil_sensors_battery, METH_VARARGS, - "Return battery information."}, - - // --- others - {"set_testing", psutil_set_testing, METH_NOARGS, - "Set psutil in testing mode"}, - - {NULL, NULL, 0, NULL} -}; - - -#if PY_MAJOR_VERSION >= 3 - #define INITERR return NULL - - static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, - "_psutil_osx", - NULL, - -1, - mod_methods, - NULL, - NULL, - NULL, - NULL - }; - - PyObject *PyInit__psutil_osx(void) -#else /* PY_MAJOR_VERSION */ - #define INITERR return - - void init_psutil_osx(void) -#endif /* PY_MAJOR_VERSION */ -{ - PyObject *v; -#if PY_MAJOR_VERSION >= 3 - PyObject *mod = PyModule_Create(&moduledef); -#else - PyObject *mod = Py_InitModule("_psutil_osx", mod_methods); -#endif - if (mod == NULL) - INITERR; - - if (psutil_setup() != 0) - INITERR; - - if (PyModule_AddIntConstant(mod, "version", PSUTIL_VERSION)) - INITERR; - // process status constants, defined in: - // http://fxr.watson.org/fxr/source/bsd/sys/proc.h?v=xnu-792.6.70#L149 - if (PyModule_AddIntConstant(mod, "SIDL", SIDL)) - INITERR; - if (PyModule_AddIntConstant(mod, "SRUN", SRUN)) - INITERR; - if (PyModule_AddIntConstant(mod, "SSLEEP", SSLEEP)) - INITERR; - if (PyModule_AddIntConstant(mod, "SSTOP", SSTOP)) - INITERR; - if (PyModule_AddIntConstant(mod, "SZOMB", SZOMB)) - INITERR; - // connection status constants - if (PyModule_AddIntConstant(mod, "TCPS_CLOSED", TCPS_CLOSED)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_CLOSING", TCPS_CLOSING)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_CLOSE_WAIT", TCPS_CLOSE_WAIT)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_LISTEN", TCPS_LISTEN)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_ESTABLISHED", TCPS_ESTABLISHED)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_SYN_SENT", TCPS_SYN_SENT)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_SYN_RECEIVED", TCPS_SYN_RECEIVED)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_FIN_WAIT_1", TCPS_FIN_WAIT_1)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_FIN_WAIT_2", TCPS_FIN_WAIT_2)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_LAST_ACK", TCPS_LAST_ACK)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_TIME_WAIT", TCPS_TIME_WAIT)) - INITERR; - if (PyModule_AddIntConstant(mod, "PSUTIL_CONN_NONE", PSUTIL_CONN_NONE)) - INITERR; - - // Exception. - ZombieProcessError = PyErr_NewException( - "_psutil_osx.ZombieProcessError", NULL, NULL); - if (ZombieProcessError == NULL) - INITERR; - Py_INCREF(ZombieProcessError); - if (PyModule_AddObject(mod, "ZombieProcessError", ZombieProcessError)) { - Py_DECREF(ZombieProcessError); - INITERR; - } - - if (mod == NULL) - INITERR; -#if PY_MAJOR_VERSION >= 3 - return mod; -#endif -} diff --git a/ddtrace/vendor/psutil/_psutil_posix.c b/ddtrace/vendor/psutil/_psutil_posix.c deleted file mode 100644 index aa600849176..00000000000 --- a/ddtrace/vendor/psutil/_psutil_posix.c +++ /dev/null @@ -1,691 +0,0 @@ -/* - * 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. - * - * Functions specific to all POSIX compliant platforms. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef PSUTIL_SUNOS10 - #include "arch/solaris/v10/ifaddrs.h" -#elif PSUTIL_AIX - #include "arch/aix/ifaddrs.h" -#else - #include -#endif - -#if defined(PSUTIL_LINUX) - #include - #include - #include -#elif defined(PSUTIL_BSD) || defined(PSUTIL_OSX) - #include - #include - #include - #include - #include - #include -#elif defined(PSUTIL_SUNOS) - #include - #include -#elif defined(PSUTIL_AIX) - #include -#endif - -#include "_psutil_common.h" - -/* - * Check if PID exists. Return values: - * 1: exists - * 0: does not exist - * -1: error (Python exception is set) - */ -int -psutil_pid_exists(long pid) { - int ret; - - // No negative PID exists, plus -1 is an alias for sending signal - // too all processes except system ones. Not what we want. - if (pid < 0) - return 0; - - // As per "man 2 kill" PID 0 is an alias for sending the signal to - // every process in the process group of the calling process. - // Not what we want. Some platforms have PID 0, some do not. - // We decide that at runtime. - if (pid == 0) { -#if defined(PSUTIL_LINUX) || defined(PSUTIL_FREEBSD) - return 0; -#else - return 1; -#endif - } - -#if defined(PSUTIL_OSX) - ret = kill((pid_t)pid , 0); -#else - ret = kill(pid , 0); -#endif - - if (ret == 0) - return 1; - else { - if (errno == ESRCH) { - // ESRCH == No such process - return 0; - } - else if (errno == EPERM) { - // EPERM clearly indicates there's a process to deny - // access to. - return 1; - } - 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. - PyErr_SetFromErrno(PyExc_OSError); - return -1; - } - } -} - - -/* - * Utility used for those syscalls which do not return a meaningful - * error that we can translate into an exception which makes sense. - * As such, we'll have to guess. - * On UNIX, if errno is set, we return that one (OSError). - * Else, if PID does not exist we assume the syscall failed because - * of that so we raise NoSuchProcess. - * If none of this is true we giveup and raise RuntimeError(msg). - * This will always set a Python exception and return NULL. - */ -int -psutil_raise_for_pid(long pid, char *syscall_name) { - // Set exception to AccessDenied if pid exists else NoSuchProcess. - if (errno != 0) { - // Unlikely we get here. - PyErr_SetFromErrno(PyExc_OSError); - return 0; - } - else if (psutil_pid_exists(pid) == 0) { - psutil_debug("%s syscall failed and PID %i no longer exists; " - "assume NoSuchProcess", syscall_name, pid); - NoSuchProcess(""); - } - else { - PyErr_Format(PyExc_RuntimeError, "%s syscall failed", syscall_name); - } - return 0; -} - - -/* - * Given a PID return process priority as a Python integer. - */ -static PyObject * -psutil_posix_getpriority(PyObject *self, PyObject *args) { - long pid; - int priority; - errno = 0; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - -#ifdef PSUTIL_OSX - priority = getpriority(PRIO_PROCESS, (id_t)pid); -#else - priority = getpriority(PRIO_PROCESS, pid); -#endif - if (errno != 0) - return PyErr_SetFromErrno(PyExc_OSError); - return Py_BuildValue("i", priority); -} - - -/* - * Given a PID and a value change process priority. - */ -static PyObject * -psutil_posix_setpriority(PyObject *self, PyObject *args) { - long pid; - int priority; - int retval; - - if (! PyArg_ParseTuple(args, "li", &pid, &priority)) - return NULL; - -#ifdef PSUTIL_OSX - retval = setpriority(PRIO_PROCESS, (id_t)pid, priority); -#else - retval = setpriority(PRIO_PROCESS, pid, priority); -#endif - if (retval == -1) - return PyErr_SetFromErrno(PyExc_OSError); - Py_RETURN_NONE; -} - - -/* - * Translate a sockaddr struct into a Python string. - * Return None if address family is not AF_INET* or AF_PACKET. - */ -static PyObject * -psutil_convert_ipaddr(struct sockaddr *addr, int family) { - char buf[NI_MAXHOST]; - int err; - int addrlen; - size_t n; - size_t len; - const char *data; - char *ptr; - - if (addr == NULL) { - Py_INCREF(Py_None); - return Py_None; - } - else if (family == AF_INET || family == AF_INET6) { - if (family == AF_INET) - addrlen = sizeof(struct sockaddr_in); - else - addrlen = sizeof(struct sockaddr_in6); - err = getnameinfo(addr, addrlen, buf, sizeof(buf), NULL, 0, - NI_NUMERICHOST); - if (err != 0) { - // XXX we get here on FreeBSD when processing 'lo' / AF_INET6 - // broadcast. Not sure what to do other than returning None. - // ifconfig does not show anything BTW. - //PyErr_Format(PyExc_RuntimeError, gai_strerror(err)); - //return NULL; - Py_INCREF(Py_None); - return Py_None; - } - else { - return Py_BuildValue("s", buf); - } - } -#ifdef PSUTIL_LINUX - else if (family == AF_PACKET) { - struct sockaddr_ll *lladdr = (struct sockaddr_ll *)addr; - len = lladdr->sll_halen; - data = (const char *)lladdr->sll_addr; - } -#elif defined(PSUTIL_BSD) || defined(PSUTIL_OSX) - else if (addr->sa_family == AF_LINK) { - // Note: prior to Python 3.4 socket module does not expose - // AF_LINK so we'll do. - struct sockaddr_dl *dladdr = (struct sockaddr_dl *)addr; - len = dladdr->sdl_alen; - data = LLADDR(dladdr); - } -#endif - else { - // unknown family - Py_INCREF(Py_None); - return Py_None; - } - - // AF_PACKET or AF_LINK - if (len > 0) { - ptr = buf; - for (n = 0; n < len; ++n) { - sprintf(ptr, "%02x:", data[n] & 0xff); - ptr += 3; - } - *--ptr = '\0'; - return Py_BuildValue("s", buf); - } - else { - Py_INCREF(Py_None); - return Py_None; - } -} - - -/* - * Return NICs information a-la ifconfig as a list of tuples. - * TODO: on Solaris we won't get any MAC address. - */ -static PyObject* -psutil_net_if_addrs(PyObject* self, PyObject* args) { - struct ifaddrs *ifaddr, *ifa; - int family; - - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - PyObject *py_address = NULL; - PyObject *py_netmask = NULL; - PyObject *py_broadcast = NULL; - PyObject *py_ptp = NULL; - - if (py_retlist == NULL) - return NULL; - if (getifaddrs(&ifaddr) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { - if (!ifa->ifa_addr) - continue; - family = ifa->ifa_addr->sa_family; - py_address = psutil_convert_ipaddr(ifa->ifa_addr, family); - // If the primary address can't be determined just skip it. - // I've never seen this happen on Linux but I did on FreeBSD. - if (py_address == Py_None) - continue; - if (py_address == NULL) - goto error; - py_netmask = psutil_convert_ipaddr(ifa->ifa_netmask, family); - if (py_netmask == NULL) - goto error; - - if (ifa->ifa_flags & IFF_BROADCAST) { - py_broadcast = psutil_convert_ipaddr(ifa->ifa_broadaddr, family); - Py_INCREF(Py_None); - py_ptp = Py_None; - } - else if (ifa->ifa_flags & IFF_POINTOPOINT) { - py_ptp = psutil_convert_ipaddr(ifa->ifa_dstaddr, family); - Py_INCREF(Py_None); - py_broadcast = Py_None; - } - else { - Py_INCREF(Py_None); - Py_INCREF(Py_None); - py_broadcast = Py_None; - py_ptp = Py_None; - } - - if ((py_broadcast == NULL) || (py_ptp == NULL)) - goto error; - py_tuple = Py_BuildValue( - "(siOOOO)", - ifa->ifa_name, - family, - py_address, - py_netmask, - py_broadcast, - py_ptp - ); - - if (! py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_tuple); - Py_CLEAR(py_address); - Py_CLEAR(py_netmask); - Py_CLEAR(py_broadcast); - Py_CLEAR(py_ptp); - } - - freeifaddrs(ifaddr); - return py_retlist; - -error: - if (ifaddr != NULL) - freeifaddrs(ifaddr); - Py_DECREF(py_retlist); - Py_XDECREF(py_tuple); - Py_XDECREF(py_address); - Py_XDECREF(py_netmask); - Py_XDECREF(py_broadcast); - Py_XDECREF(py_ptp); - return NULL; -} - - -/* - * Return NIC MTU. References: - * http://www.i-scream.org/libstatgrab/ - */ -static PyObject * -psutil_net_if_mtu(PyObject *self, PyObject *args) { - char *nic_name; - int sock = -1; - int ret; -#ifdef PSUTIL_SUNOS10 - struct lifreq lifr; -#else - struct ifreq ifr; -#endif - - if (! PyArg_ParseTuple(args, "s", &nic_name)) - return NULL; - - sock = socket(AF_INET, SOCK_DGRAM, 0); - if (sock == -1) - goto error; - -#ifdef PSUTIL_SUNOS10 - strncpy(lifr.lifr_name, nic_name, sizeof(lifr.lifr_name)); - ret = ioctl(sock, SIOCGIFMTU, &lifr); -#else - strncpy(ifr.ifr_name, nic_name, sizeof(ifr.ifr_name)); - ret = ioctl(sock, SIOCGIFMTU, &ifr); -#endif - if (ret == -1) - goto error; - close(sock); - -#ifdef PSUTIL_SUNOS10 - return Py_BuildValue("i", lifr.lifr_mtu); -#else - return Py_BuildValue("i", ifr.ifr_mtu); -#endif - -error: - if (sock != -1) - close(sock); - return PyErr_SetFromErrno(PyExc_OSError); -} - - -/* - * Inspect NIC flags, returns a bool indicating whether the NIC is - * running. References: - * http://www.i-scream.org/libstatgrab/ - */ -static PyObject * -psutil_net_if_flags(PyObject *self, PyObject *args) { - char *nic_name; - int sock = -1; - int ret; - struct ifreq ifr; - - if (! PyArg_ParseTuple(args, "s", &nic_name)) - return NULL; - - sock = socket(AF_INET, SOCK_DGRAM, 0); - if (sock == -1) - goto error; - - strncpy(ifr.ifr_name, nic_name, sizeof(ifr.ifr_name)); - ret = ioctl(sock, SIOCGIFFLAGS, &ifr); - if (ret == -1) - goto error; - - close(sock); - if ((ifr.ifr_flags & IFF_UP) != 0) - return Py_BuildValue("O", Py_True); - else - return Py_BuildValue("O", Py_False); - -error: - if (sock != -1) - close(sock); - return PyErr_SetFromErrno(PyExc_OSError); -} - - -/* - * net_if_stats() macOS/BSD implementation. - */ -#if defined(PSUTIL_BSD) || defined(PSUTIL_OSX) - -int psutil_get_nic_speed(int ifm_active) { - // Determine NIC speed. Taken from: - // http://www.i-scream.org/libstatgrab/ - // Assuming only ETHER devices - switch(IFM_TYPE(ifm_active)) { - case IFM_ETHER: - switch(IFM_SUBTYPE(ifm_active)) { -#if defined(IFM_HPNA_1) && ((!defined(IFM_10G_LR)) \ - || (IFM_10G_LR != IFM_HPNA_1)) - // HomePNA 1.0 (1Mb/s) - case(IFM_HPNA_1): - return 1; -#endif - // 10 Mbit - case(IFM_10_T): // 10BaseT - RJ45 - case(IFM_10_2): // 10Base2 - Thinnet - case(IFM_10_5): // 10Base5 - AUI - case(IFM_10_STP): // 10BaseT over shielded TP - case(IFM_10_FL): // 10baseFL - Fiber - return 10; - // 100 Mbit - case(IFM_100_TX): // 100BaseTX - RJ45 - case(IFM_100_FX): // 100BaseFX - Fiber - case(IFM_100_T4): // 100BaseT4 - 4 pair cat 3 - case(IFM_100_VG): // 100VG-AnyLAN - case(IFM_100_T2): // 100BaseT2 - return 100; - // 1000 Mbit - case(IFM_1000_SX): // 1000BaseSX - multi-mode fiber - case(IFM_1000_LX): // 1000baseLX - single-mode fiber - case(IFM_1000_CX): // 1000baseCX - 150ohm STP -#if defined(IFM_1000_TX) && !defined(PSUTIL_OPENBSD) - // FreeBSD 4 and others (but NOT OpenBSD) -> #define IFM_1000_T in net/if_media.h - case(IFM_1000_TX): -#endif -#ifdef IFM_1000_FX - case(IFM_1000_FX): -#endif -#ifdef IFM_1000_T - case(IFM_1000_T): -#endif - return 1000; -#if defined(IFM_10G_SR) || defined(IFM_10G_LR) || defined(IFM_10G_CX4) \ - || defined(IFM_10G_T) -#ifdef IFM_10G_SR - case(IFM_10G_SR): -#endif -#ifdef IFM_10G_LR - case(IFM_10G_LR): -#endif -#ifdef IFM_10G_CX4 - case(IFM_10G_CX4): -#endif -#ifdef IFM_10G_TWINAX - case(IFM_10G_TWINAX): -#endif -#ifdef IFM_10G_TWINAX_LONG - case(IFM_10G_TWINAX_LONG): -#endif -#ifdef IFM_10G_T - case(IFM_10G_T): -#endif - return 10000; -#endif -#if defined(IFM_2500_SX) -#ifdef IFM_2500_SX - case(IFM_2500_SX): -#endif - return 2500; -#endif // any 2.5GBit stuff... - // We don't know what it is - default: - return 0; - } - break; - -#ifdef IFM_TOKEN - case IFM_TOKEN: - switch(IFM_SUBTYPE(ifm_active)) { - case IFM_TOK_STP4: // Shielded twisted pair 4m - DB9 - case IFM_TOK_UTP4: // Unshielded twisted pair 4m - RJ45 - return 4; - case IFM_TOK_STP16: // Shielded twisted pair 16m - DB9 - case IFM_TOK_UTP16: // Unshielded twisted pair 16m - RJ45 - return 16; -#if defined(IFM_TOK_STP100) || defined(IFM_TOK_UTP100) -#ifdef IFM_TOK_STP100 - case IFM_TOK_STP100: // Shielded twisted pair 100m - DB9 -#endif -#ifdef IFM_TOK_UTP100 - case IFM_TOK_UTP100: // Unshielded twisted pair 100m - RJ45 -#endif - return 100; -#endif - // We don't know what it is - default: - return 0; - } - break; -#endif - -#ifdef IFM_FDDI - case IFM_FDDI: - switch(IFM_SUBTYPE(ifm_active)) { - // We don't know what it is - default: - return 0; - } - break; -#endif - case IFM_IEEE80211: - switch(IFM_SUBTYPE(ifm_active)) { - case IFM_IEEE80211_FH1: // Frequency Hopping 1Mbps - case IFM_IEEE80211_DS1: // Direct Sequence 1Mbps - return 1; - case IFM_IEEE80211_FH2: // Frequency Hopping 2Mbps - case IFM_IEEE80211_DS2: // Direct Sequence 2Mbps - return 2; - case IFM_IEEE80211_DS5: // Direct Sequence 5Mbps - return 5; - case IFM_IEEE80211_DS11: // Direct Sequence 11Mbps - return 11; - case IFM_IEEE80211_DS22: // Direct Sequence 22Mbps - return 22; - // We don't know what it is - default: - return 0; - } - break; - - default: - return 0; - } -} - - -/* - * Return stats about a particular network interface. - * References: - * http://www.i-scream.org/libstatgrab/ - */ -static PyObject * -psutil_net_if_duplex_speed(PyObject *self, PyObject *args) { - char *nic_name; - int sock = -1; - int ret; - int duplex; - int speed; - struct ifreq ifr; - struct ifmediareq ifmed; - - if (! PyArg_ParseTuple(args, "s", &nic_name)) - return NULL; - - sock = socket(AF_INET, SOCK_DGRAM, 0); - if (sock == -1) - return PyErr_SetFromErrno(PyExc_OSError); - strncpy(ifr.ifr_name, nic_name, sizeof(ifr.ifr_name)); - - // speed / duplex - memset(&ifmed, 0, sizeof(struct ifmediareq)); - strlcpy(ifmed.ifm_name, nic_name, sizeof(ifmed.ifm_name)); - ret = ioctl(sock, SIOCGIFMEDIA, (caddr_t)&ifmed); - if (ret == -1) { - speed = 0; - duplex = 0; - } - else { - speed = psutil_get_nic_speed(ifmed.ifm_active); - if ((ifmed.ifm_active | IFM_FDX) == ifmed.ifm_active) - duplex = 2; - else if ((ifmed.ifm_active | IFM_HDX) == ifmed.ifm_active) - duplex = 1; - else - duplex = 0; - } - - close(sock); - return Py_BuildValue("[ii]", duplex, speed); -} -#endif // net_if_stats() macOS/BSD implementation - - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * define the psutil C module methods and initialize the module. - */ -static PyMethodDef mod_methods[] = { - {"getpriority", psutil_posix_getpriority, METH_VARARGS, - "Return process priority"}, - {"setpriority", psutil_posix_setpriority, METH_VARARGS, - "Set process priority"}, - {"net_if_addrs", psutil_net_if_addrs, METH_VARARGS, - "Retrieve NICs information"}, - {"net_if_mtu", psutil_net_if_mtu, METH_VARARGS, - "Retrieve NIC MTU"}, - {"net_if_flags", psutil_net_if_flags, METH_VARARGS, - "Retrieve NIC flags"}, -#if defined(PSUTIL_BSD) || defined(PSUTIL_OSX) - {"net_if_duplex_speed", psutil_net_if_duplex_speed, METH_VARARGS, - "Return NIC stats."}, -#endif - {NULL, NULL, 0, NULL} -}; - - -#if PY_MAJOR_VERSION >= 3 - #define INITERR return NULL - - static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, - "_psutil_posix", - NULL, - -1, - mod_methods, - NULL, - NULL, - NULL, - NULL - }; - - PyObject *PyInit__psutil_posix(void) -#else /* PY_MAJOR_VERSION */ - #define INITERR return - - void init_psutil_posix(void) -#endif /* PY_MAJOR_VERSION */ -{ -#if PY_MAJOR_VERSION >= 3 - PyObject *mod = PyModule_Create(&moduledef); -#else - PyObject *mod = Py_InitModule("_psutil_posix", mod_methods); -#endif - if (mod == NULL) - INITERR; - -#if defined(PSUTIL_BSD) || defined(PSUTIL_OSX) || defined(PSUTIL_SUNOS) || defined(PSUTIL_AIX) - if (PyModule_AddIntConstant(mod, "AF_LINK", AF_LINK)) INITERR; -#endif - - if (mod == NULL) - INITERR; -#if PY_MAJOR_VERSION >= 3 - return mod; -#endif -} - -#ifdef __cplusplus -} -#endif diff --git a/ddtrace/vendor/psutil/_psutil_posix.h b/ddtrace/vendor/psutil/_psutil_posix.h deleted file mode 100644 index fe25b366950..00000000000 --- a/ddtrace/vendor/psutil/_psutil_posix.h +++ /dev/null @@ -1,8 +0,0 @@ -/* - * 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. - */ - -int psutil_pid_exists(long pid); -void psutil_raise_for_pid(long pid, char *msg); diff --git a/ddtrace/vendor/psutil/_psutil_sunos.c b/ddtrace/vendor/psutil/_psutil_sunos.c deleted file mode 100644 index 31d6f364fbc..00000000000 --- a/ddtrace/vendor/psutil/_psutil_sunos.c +++ /dev/null @@ -1,1776 +0,0 @@ -/* - * 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. - * - * Functions specific to Sun OS Solaris platforms. - * - * Thanks to Justin Venus who originally wrote a consistent part of - * this in Cython which I later on translated in C. - */ - -/* fix compilation issue on SunOS 5.10, see: - * https://github.com/giampaolo/psutil/issues/421 - * https://github.com/giampaolo/psutil/issues/1077 - * http://us-east.manta.joyent.com/jmc/public/opensolaris/ARChive/PSARC/2010/111/materials/s10ceval.txt - * - * Because LEGACY_MIB_SIZE defined in the same file there is no way to make autoconfiguration =\ -*/ - -#define NEW_MIB_COMPLIANT 1 -#define _STRUCTURED_PROC 1 - -#include - -#if !defined(_LP64) && _FILE_OFFSET_BITS == 64 -# undef _FILE_OFFSET_BITS -# undef _LARGEFILE64_SOURCE -#endif - -#include -#include -#include -#include -#include -#include // for MNTTAB -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include // fabs() - -#include "_psutil_common.h" -#include "_psutil_posix.h" - -#include "arch/solaris/environ.h" - -#define PSUTIL_TV2DOUBLE(t) (((t).tv_nsec * 0.000000001) + (t).tv_sec) - - -/* - * Read a file content and fills a C structure with it. - */ -static int -psutil_file_to_struct(char *path, void *fstruct, size_t size) { - int fd; - ssize_t nbytes; - fd = open(path, O_RDONLY); - if (fd == -1) { - PyErr_SetFromErrnoWithFilename(PyExc_OSError, path); - return 0; - } - nbytes = read(fd, fstruct, size); - if (nbytes == -1) { - close(fd); - PyErr_SetFromErrno(PyExc_OSError); - return 0; - } - if (nbytes != (ssize_t) size) { - close(fd); - PyErr_SetString( - PyExc_RuntimeError, "read() file structure size mismatch"); - return 0; - } - close(fd); - return nbytes; -} - - -/* - * Return process ppid, rss, vms, ctime, nice, nthreads, status and tty - * as a Python tuple. - */ -static PyObject * -psutil_proc_basic_info(PyObject *self, PyObject *args) { - int pid; - char path[1000]; - psinfo_t info; - const char *procfs_path; - - if (! PyArg_ParseTuple(args, "is", &pid, &procfs_path)) - return NULL; - - sprintf(path, "%s/%i/psinfo", procfs_path, pid); - if (! psutil_file_to_struct(path, (void *)&info, sizeof(info))) - return NULL; - return Py_BuildValue( - "ikkdiiikiiii", - info.pr_ppid, // parent pid - info.pr_rssize, // rss - info.pr_size, // vms - PSUTIL_TV2DOUBLE(info.pr_start), // create time - info.pr_lwp.pr_nice, // nice - info.pr_nlwp, // no. of threads - info.pr_lwp.pr_state, // status code - info.pr_ttydev, // tty nr - (int)info.pr_uid, // real user id - (int)info.pr_euid, // effective user id - (int)info.pr_gid, // real group id - (int)info.pr_egid // effective group id - ); -} - -/* - * Join array of C strings to C string with delemiter dm. - * Omit empty records. - */ -static int -cstrings_array_to_string(char **joined, char ** array, size_t count, char dm) { - int i; - size_t total_length = 0; - size_t item_length = 0; - char *result = NULL; - char *last = NULL; - - if (!array || !joined) - return 0; - - for (i=0; i 0) { - py_args = PyUnicode_DecodeFSDefault(argv_plain); - free(argv_plain); - } else if (joined < 0) { - goto error; - } - - psutil_free_cstrings_array(argv, argc); - } - } - - /* If we can't read process memory or can't decode the result - * then return args from /proc. */ - if (!py_args) { - PyErr_Clear(); - py_args = PyUnicode_DecodeFSDefault(info.pr_psargs); - } - - /* Both methods has been failed. */ - if (!py_args) - goto error; - - py_retlist = Py_BuildValue("OO", py_name, py_args); - if (!py_retlist) - goto error; - - Py_DECREF(py_name); - Py_DECREF(py_args); - return py_retlist; - -error: - Py_XDECREF(py_name); - Py_XDECREF(py_args); - Py_XDECREF(py_retlist); - return NULL; -} - - -/* - * Return process environ block. - */ -static PyObject * -psutil_proc_environ(PyObject *self, PyObject *args) { - int pid; - char path[1000]; - psinfo_t info; - const char *procfs_path; - char **env = NULL; - ssize_t env_count = -1; - char *dm; - int i = 0; - PyObject *py_envname = NULL; - PyObject *py_envval = NULL; - PyObject *py_retdict = PyDict_New(); - - if (! py_retdict) - return PyErr_NoMemory(); - - if (! PyArg_ParseTuple(args, "is", &pid, &procfs_path)) - return NULL; - - sprintf(path, "%s/%i/psinfo", procfs_path, pid); - if (! psutil_file_to_struct(path, (void *)&info, sizeof(info))) - goto error; - - if (! info.pr_envp) { - AccessDenied(""); - goto error; - } - - env = psutil_read_raw_env(info, procfs_path, &env_count); - if (! env && env_count != 0) - goto error; - - for (i=0; i= 0) - psutil_free_cstrings_array(env, env_count); - - Py_XDECREF(py_envname); - Py_XDECREF(py_envval); - Py_XDECREF(py_retdict); - return NULL; -} - - -/* - * Return process user and system CPU times as a Python tuple. - */ -static PyObject * -psutil_proc_cpu_times(PyObject *self, PyObject *args) { - int pid; - char path[1000]; - pstatus_t info; - const char *procfs_path; - - if (! PyArg_ParseTuple(args, "is", &pid, &procfs_path)) - return NULL; - sprintf(path, "%s/%i/status", procfs_path, pid); - if (! psutil_file_to_struct(path, (void *)&info, sizeof(info))) - return NULL; - // results are more precise than os.times() - return Py_BuildValue( - "(dddd)", - PSUTIL_TV2DOUBLE(info.pr_utime), - PSUTIL_TV2DOUBLE(info.pr_stime), - PSUTIL_TV2DOUBLE(info.pr_cutime), - PSUTIL_TV2DOUBLE(info.pr_cstime) - ); -} - - -/* - * Return what CPU the process is running on. - */ -static PyObject * -psutil_proc_cpu_num(PyObject *self, PyObject *args) { - int fd = NULL; - int pid; - char path[1000]; - struct prheader header; - struct lwpsinfo *lwp = NULL; - int nent; - int size; - int proc_num; - ssize_t nbytes; - const char *procfs_path; - - if (! PyArg_ParseTuple(args, "is", &pid, &procfs_path)) - return NULL; - - sprintf(path, "%s/%i/lpsinfo", procfs_path, pid); - fd = open(path, O_RDONLY); - if (fd == -1) { - PyErr_SetFromErrnoWithFilename(PyExc_OSError, path); - return NULL; - } - - // read header - nbytes = pread(fd, &header, sizeof(header), 0); - if (nbytes == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - if (nbytes != sizeof(header)) { - PyErr_SetString( - PyExc_RuntimeError, "read() file structure size mismatch"); - goto error; - } - - // malloc - nent = header.pr_nent; - size = header.pr_entsize * nent; - lwp = malloc(size); - if (lwp == NULL) { - PyErr_NoMemory(); - goto error; - } - - // read the rest - nbytes = pread(fd, lwp, size, sizeof(header)); - if (nbytes == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - if (nbytes != size) { - PyErr_SetString( - PyExc_RuntimeError, "read() file structure size mismatch"); - goto error; - } - - // done - proc_num = lwp->pr_onpro; - close(fd); - free(lwp); - return Py_BuildValue("i", proc_num); - -error: - if (fd != -1) - close(fd); - free(lwp); - return NULL; -} - - -/* - * Return process uids/gids as a Python tuple. - */ -static PyObject * -psutil_proc_cred(PyObject *self, PyObject *args) { - int pid; - char path[1000]; - prcred_t info; - const char *procfs_path; - - if (! PyArg_ParseTuple(args, "is", &pid, &procfs_path)) - return NULL; - sprintf(path, "%s/%i/cred", procfs_path, pid); - if (! psutil_file_to_struct(path, (void *)&info, sizeof(info))) - return NULL; - return Py_BuildValue("iiiiii", - info.pr_ruid, info.pr_euid, info.pr_suid, - info.pr_rgid, info.pr_egid, info.pr_sgid); -} - - -/* - * Return process voluntary and involuntary context switches as a Python tuple. - */ -static PyObject * -psutil_proc_num_ctx_switches(PyObject *self, PyObject *args) { - int pid; - char path[1000]; - prusage_t info; - const char *procfs_path; - - if (! PyArg_ParseTuple(args, "is", &pid, &procfs_path)) - return NULL; - sprintf(path, "%s/%i/usage", procfs_path, pid); - if (! psutil_file_to_struct(path, (void *)&info, sizeof(info))) - return NULL; - return Py_BuildValue("kk", info.pr_vctx, info.pr_ictx); -} - - -/* - * Process IO counters. - * - * Commented out and left here as a reminder. Apparently we cannot - * retrieve process IO stats because: - * - 'pr_ioch' is a sum of chars read and written, with no distinction - * - 'pr_inblk' and 'pr_oublk', which should be the number of bytes - * read and written, hardly increase and according to: - * http://www.brendangregg.com/Solaris/paper_diskubyp1.pdf - * ...they should be meaningless anyway. - * -static PyObject* -proc_io_counters(PyObject* self, PyObject* args) { - int pid; - char path[1000]; - prusage_t info; - const char *procfs_path; - - if (! PyArg_ParseTuple(args, "is", &pid, &procfs_path)) - return NULL; - sprintf(path, "%s/%i/usage", procfs_path, pid); - if (! psutil_file_to_struct(path, (void *)&info, sizeof(info))) - return NULL; - - // On Solaris we only have 'pr_ioch' which accounts for bytes read - // *and* written. - // 'pr_inblk' and 'pr_oublk' should be expressed in blocks of - // 8KB according to: - // http://www.brendangregg.com/Solaris/paper_diskubyp1.pdf (pag. 8) - return Py_BuildValue("kkkk", - info.pr_ioch, - info.pr_ioch, - info.pr_inblk, - info.pr_oublk); -} - */ - - -/* - * Return information about a given process thread. - */ -static PyObject * -psutil_proc_query_thread(PyObject *self, PyObject *args) { - int pid, tid; - char path[1000]; - lwpstatus_t info; - const char *procfs_path; - - if (! PyArg_ParseTuple(args, "iis", &pid, &tid, &procfs_path)) - return NULL; - sprintf(path, "%s/%i/lwp/%i/lwpstatus", procfs_path, pid, tid); - if (! psutil_file_to_struct(path, (void *)&info, sizeof(info))) - return NULL; - return Py_BuildValue("dd", - PSUTIL_TV2DOUBLE(info.pr_utime), - PSUTIL_TV2DOUBLE(info.pr_stime)); -} - - -/* - * Return information about system virtual memory. - */ -static PyObject * -psutil_swap_mem(PyObject *self, PyObject *args) { -// XXX (arghhh!) -// total/free swap mem: commented out as for some reason I can't -// manage to get the same results shown by "swap -l", despite the -// code below is exactly the same as: -// http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/ -// cmd/swap/swap.c -// We're going to parse "swap -l" output from Python (sigh!) - -/* - struct swaptable *st; - struct swapent *swapent; - int i; - struct stat64 statbuf; - char *path; - char fullpath[MAXPATHLEN+1]; - int num; - - if ((num = swapctl(SC_GETNSWP, NULL)) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - if (num == 0) { - PyErr_SetString(PyExc_RuntimeError, "no swap devices configured"); - return NULL; - } - if ((st = malloc(num * sizeof(swapent_t) + sizeof (int))) == NULL) { - PyErr_SetString(PyExc_RuntimeError, "malloc failed"); - return NULL; - } - if ((path = malloc(num * MAXPATHLEN)) == NULL) { - PyErr_SetString(PyExc_RuntimeError, "malloc failed"); - return NULL; - } - swapent = st->swt_ent; - for (i = 0; i < num; i++, swapent++) { - swapent->ste_path = path; - path += MAXPATHLEN; - } - st->swt_n = num; - if ((num = swapctl(SC_LIST, st)) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - swapent = st->swt_ent; - long t = 0, f = 0; - for (i = 0; i < num; i++, swapent++) { - int diskblks_per_page =(int)(sysconf(_SC_PAGESIZE) >> DEV_BSHIFT); - t += (long)swapent->ste_pages; - f += (long)swapent->ste_free; - } - - free(st); - return Py_BuildValue("(kk)", t, f); -*/ - - kstat_ctl_t *kc; - kstat_t *k; - cpu_stat_t *cpu; - int cpu_count = 0; - int flag = 0; - uint_t sin = 0; - uint_t sout = 0; - - kc = kstat_open(); - if (kc == NULL) - return PyErr_SetFromErrno(PyExc_OSError);; - - k = kc->kc_chain; - while (k != NULL) { - if ((strncmp(k->ks_name, "cpu_stat", 8) == 0) && \ - (kstat_read(kc, k, NULL) != -1) ) - { - flag = 1; - cpu = (cpu_stat_t *) k->ks_data; - sin += cpu->cpu_vminfo.pgswapin; // num pages swapped in - sout += cpu->cpu_vminfo.pgswapout; // num pages swapped out - } - cpu_count += 1; - k = k->ks_next; - } - kstat_close(kc); - if (!flag) { - PyErr_SetString(PyExc_RuntimeError, "no swap device was found"); - return NULL; - } - return Py_BuildValue("(II)", sin, sout); -} - - -/* - * Return users currently connected on the system. - */ -static PyObject * -psutil_users(PyObject *self, PyObject *args) { - struct utmpx *ut; - PyObject *py_tuple = NULL; - PyObject *py_username = NULL; - PyObject *py_tty = NULL; - PyObject *py_hostname = NULL; - PyObject *py_user_proc = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - - setutxent(); - while (NULL != (ut = getutxent())) { - if (ut->ut_type == USER_PROCESS) - py_user_proc = Py_True; - else - py_user_proc = Py_False; - py_username = PyUnicode_DecodeFSDefault(ut->ut_user); - if (! py_username) - goto error; - py_tty = PyUnicode_DecodeFSDefault(ut->ut_line); - if (! py_tty) - goto error; - py_hostname = PyUnicode_DecodeFSDefault(ut->ut_host); - if (! py_hostname) - goto error; - py_tuple = Py_BuildValue( - "(OOOfOi)", - py_username, // username - py_tty, // tty - py_hostname, // hostname - (float)ut->ut_tv.tv_sec, // tstamp - py_user_proc, // (bool) user process - ut->ut_pid // process id - ); - if (py_tuple == NULL) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_username); - Py_CLEAR(py_tty); - Py_CLEAR(py_hostname); - Py_CLEAR(py_tuple); - } - endutxent(); - - return py_retlist; - -error: - Py_XDECREF(py_username); - Py_XDECREF(py_tty); - Py_XDECREF(py_hostname); - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - endutxent(); - return NULL; -} - - -/* - * Return disk mounted partitions as a list of tuples including device, - * mount point and filesystem type. - */ -static PyObject * -psutil_disk_partitions(PyObject *self, PyObject *args) { - FILE *file; - struct mnttab mt; - PyObject *py_dev = NULL; - PyObject *py_mountp = NULL; - PyObject *py_tuple = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - - file = fopen(MNTTAB, "rb"); - if (file == NULL) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - while (getmntent(file, &mt) == 0) { - py_dev = PyUnicode_DecodeFSDefault(mt.mnt_special); - if (! py_dev) - goto error; - py_mountp = PyUnicode_DecodeFSDefault(mt.mnt_mountp); - if (! py_mountp) - goto error; - py_tuple = Py_BuildValue( - "(OOss)", - py_dev, // device - py_mountp, // mount point - mt.mnt_fstype, // fs type - mt.mnt_mntopts); // options - if (py_tuple == NULL) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_dev); - Py_CLEAR(py_mountp); - Py_CLEAR(py_tuple); - } - fclose(file); - return py_retlist; - -error: - Py_XDECREF(py_dev); - Py_XDECREF(py_mountp); - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (file != NULL) - fclose(file); - return NULL; -} - - -/* - * Return system-wide CPU times. - */ -static PyObject * -psutil_per_cpu_times(PyObject *self, PyObject *args) { - kstat_ctl_t *kc; - kstat_t *ksp; - cpu_stat_t cs; - PyObject *py_retlist = PyList_New(0); - PyObject *py_cputime = NULL; - - if (py_retlist == NULL) - return NULL; - - kc = kstat_open(); - if (kc == NULL) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (ksp = kc->kc_chain; ksp != NULL; ksp = ksp->ks_next) { - if (strcmp(ksp->ks_module, "cpu_stat") == 0) { - if (kstat_read(kc, ksp, &cs) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - py_cputime = Py_BuildValue("ffff", - (float)cs.cpu_sysinfo.cpu[CPU_USER], - (float)cs.cpu_sysinfo.cpu[CPU_KERNEL], - (float)cs.cpu_sysinfo.cpu[CPU_IDLE], - (float)cs.cpu_sysinfo.cpu[CPU_WAIT]); - if (py_cputime == NULL) - goto error; - if (PyList_Append(py_retlist, py_cputime)) - goto error; - Py_CLEAR(py_cputime); - } - } - - kstat_close(kc); - return py_retlist; - -error: - Py_XDECREF(py_cputime); - Py_DECREF(py_retlist); - if (kc != NULL) - kstat_close(kc); - return NULL; -} - - -/* - * Return disk IO statistics. - */ -static PyObject * -psutil_disk_io_counters(PyObject *self, PyObject *args) { - kstat_ctl_t *kc; - kstat_t *ksp; - kstat_io_t kio; - PyObject *py_retdict = PyDict_New(); - PyObject *py_disk_info = NULL; - - if (py_retdict == NULL) - return NULL; - kc = kstat_open(); - if (kc == NULL) { - PyErr_SetFromErrno(PyExc_OSError);; - goto error; - } - ksp = kc->kc_chain; - while (ksp != NULL) { - if (ksp->ks_type == KSTAT_TYPE_IO) { - if (strcmp(ksp->ks_class, "disk") == 0) { - if (kstat_read(kc, ksp, &kio) == -1) { - kstat_close(kc); - return PyErr_SetFromErrno(PyExc_OSError);; - } - py_disk_info = Py_BuildValue( - "(IIKKLL)", - kio.reads, - kio.writes, - kio.nread, - kio.nwritten, - kio.rtime / 1000 / 1000, // from nano to milli secs - kio.wtime / 1000 / 1000 // from nano to milli secs - ); - if (!py_disk_info) - goto error; - if (PyDict_SetItemString(py_retdict, ksp->ks_name, - py_disk_info)) - goto error; - Py_CLEAR(py_disk_info); - } - } - ksp = ksp->ks_next; - } - kstat_close(kc); - - return py_retdict; - -error: - Py_XDECREF(py_disk_info); - Py_DECREF(py_retdict); - if (kc != NULL) - kstat_close(kc); - return NULL; -} - - -/* - * Return process memory mappings. - */ -static PyObject * -psutil_proc_memory_maps(PyObject *self, PyObject *args) { - int pid; - int fd = -1; - char path[1000]; - char perms[10]; - const char *name; - struct stat st; - pstatus_t status; - - prxmap_t *xmap = NULL, *p; - off_t size; - size_t nread; - int nmap; - uintptr_t pr_addr_sz; - uintptr_t stk_base_sz, brk_base_sz; - const char *procfs_path; - - PyObject *py_tuple = NULL; - PyObject *py_path = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - if (! PyArg_ParseTuple(args, "is", &pid, &procfs_path)) - goto error; - - sprintf(path, "%s/%i/status", procfs_path, pid); - if (! psutil_file_to_struct(path, (void *)&status, sizeof(status))) - goto error; - - sprintf(path, "%s/%i/xmap", procfs_path, pid); - if (stat(path, &st) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - size = st.st_size; - - fd = open(path, O_RDONLY); - if (fd == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - xmap = (prxmap_t *)malloc(size); - if (xmap == NULL) { - PyErr_NoMemory(); - goto error; - } - - nread = pread(fd, xmap, size, 0); - nmap = nread / sizeof(prxmap_t); - p = xmap; - - while (nmap) { - nmap -= 1; - if (p == NULL) { - p += 1; - continue; - } - - perms[0] = '\0'; - pr_addr_sz = p->pr_vaddr + p->pr_size; - - // perms - sprintf(perms, "%c%c%c%c", p->pr_mflags & MA_READ ? 'r' : '-', - p->pr_mflags & MA_WRITE ? 'w' : '-', - p->pr_mflags & MA_EXEC ? 'x' : '-', - p->pr_mflags & MA_SHARED ? 's' : '-'); - - // name - if (strlen(p->pr_mapname) > 0) { - name = p->pr_mapname; - } - else { - if ((p->pr_mflags & MA_ISM) || (p->pr_mflags & MA_SHM)) { - name = "[shmid]"; - } - else { - stk_base_sz = status.pr_stkbase + status.pr_stksize; - brk_base_sz = status.pr_brkbase + status.pr_brksize; - - if ((pr_addr_sz > status.pr_stkbase) && - (p->pr_vaddr < stk_base_sz)) { - name = "[stack]"; - } - else if ((p->pr_mflags & MA_ANON) && \ - (pr_addr_sz > status.pr_brkbase) && \ - (p->pr_vaddr < brk_base_sz)) { - name = "[heap]"; - } - else { - name = "[anon]"; - } - } - } - - py_path = PyUnicode_DecodeFSDefault(name); - if (! py_path) - goto error; - py_tuple = Py_BuildValue( - "kksOkkk", - (unsigned long)p->pr_vaddr, - (unsigned long)pr_addr_sz, - perms, - py_path, - (unsigned long)p->pr_rss * p->pr_pagesize, - (unsigned long)p->pr_anon * p->pr_pagesize, - (unsigned long)p->pr_locked * p->pr_pagesize); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_path); - Py_CLEAR(py_tuple); - - // increment pointer - p += 1; - } - - close(fd); - free(xmap); - return py_retlist; - -error: - if (fd != -1) - close(fd); - Py_XDECREF(py_tuple); - Py_XDECREF(py_path); - Py_DECREF(py_retlist); - if (xmap != NULL) - free(xmap); - return NULL; -} - - -/* - * Return a list of tuples for network I/O statistics. - */ -static PyObject * -psutil_net_io_counters(PyObject *self, PyObject *args) { - kstat_ctl_t *kc = NULL; - kstat_t *ksp; - kstat_named_t *rbytes, *wbytes, *rpkts, *wpkts, *ierrs, *oerrs; - int ret; - int sock = -1; - struct lifreq ifr; - - PyObject *py_retdict = PyDict_New(); - PyObject *py_ifc_info = NULL; - - if (py_retdict == NULL) - return NULL; - kc = kstat_open(); - if (kc == NULL) - goto error; - - sock = socket(AF_INET, SOCK_DGRAM, 0); - if (sock == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - ksp = kc->kc_chain; - while (ksp != NULL) { - if (ksp->ks_type != KSTAT_TYPE_NAMED) - goto next; - if (strcmp(ksp->ks_class, "net") != 0) - goto next; - // skip 'lo' (localhost) because it doesn't have the statistics we need - // and it makes kstat_data_lookup() fail - if (strcmp(ksp->ks_module, "lo") == 0) - goto next; - - // check if this is a network interface by sending a ioctl - strncpy(ifr.lifr_name, ksp->ks_name, sizeof(ifr.lifr_name)); - ret = ioctl(sock, SIOCGLIFFLAGS, &ifr); - if (ret == -1) - goto next; - - if (kstat_read(kc, ksp, NULL) == -1) { - errno = 0; - goto next; - } - - rbytes = (kstat_named_t *)kstat_data_lookup(ksp, "rbytes"); - wbytes = (kstat_named_t *)kstat_data_lookup(ksp, "obytes"); - rpkts = (kstat_named_t *)kstat_data_lookup(ksp, "ipackets"); - wpkts = (kstat_named_t *)kstat_data_lookup(ksp, "opackets"); - ierrs = (kstat_named_t *)kstat_data_lookup(ksp, "ierrors"); - oerrs = (kstat_named_t *)kstat_data_lookup(ksp, "oerrors"); - - if ((rbytes == NULL) || (wbytes == NULL) || (rpkts == NULL) || - (wpkts == NULL) || (ierrs == NULL) || (oerrs == NULL)) - { - PyErr_SetString(PyExc_RuntimeError, "kstat_data_lookup() failed"); - goto error; - } - - if (rbytes->data_type == KSTAT_DATA_UINT64) - { - py_ifc_info = Py_BuildValue("(KKKKIIii)", - wbytes->value.ui64, - rbytes->value.ui64, - wpkts->value.ui64, - rpkts->value.ui64, - ierrs->value.ui32, - oerrs->value.ui32, - 0, // dropin not supported - 0 // dropout not supported - ); - } - else - { - py_ifc_info = Py_BuildValue("(IIIIIIii)", - wbytes->value.ui32, - rbytes->value.ui32, - wpkts->value.ui32, - rpkts->value.ui32, - ierrs->value.ui32, - oerrs->value.ui32, - 0, // dropin not supported - 0 // dropout not supported - ); - } - if (!py_ifc_info) - goto error; - if (PyDict_SetItemString(py_retdict, ksp->ks_name, py_ifc_info)) - goto error; - Py_CLEAR(py_ifc_info); - goto next; - -next: - ksp = ksp->ks_next; - } - - kstat_close(kc); - close(sock); - return py_retdict; - -error: - Py_XDECREF(py_ifc_info); - Py_DECREF(py_retdict); - if (kc != NULL) - kstat_close(kc); - if (sock != -1) { - close(sock); - } - return NULL; -} - - -/* - * Return TCP and UDP connections opened by process. - * UNIX sockets are excluded. - * - * Thanks to: - * https://github.com/DavidGriffith/finx/blob/master/ - * nxsensor-3.5.0-1/src/sysdeps/solaris.c - * ...and: - * https://hg.java.net/hg/solaris~on-src/file/tip/usr/src/cmd/ - * cmd-inet/usr.bin/netstat/netstat.c - */ -static PyObject * -psutil_net_connections(PyObject *self, PyObject *args) { - long pid; - int sd = 0; - mib2_tcpConnEntry_t tp; - mib2_udpEntry_t ude; -#if defined(AF_INET6) - mib2_tcp6ConnEntry_t tp6; - mib2_udp6Entry_t ude6; -#endif - char buf[512]; - int i, flags, getcode, num_ent, state, ret; - char lip[INET6_ADDRSTRLEN], rip[INET6_ADDRSTRLEN]; - int lport, rport; - int processed_pid; - int databuf_init = 0; - struct strbuf ctlbuf, databuf; - struct T_optmgmt_req tor = {0}; - struct T_optmgmt_ack toa = {0}; - struct T_error_ack tea = {0}; - struct opthdr mibhdr = {0}; - - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - PyObject *py_laddr = NULL; - PyObject *py_raddr = NULL; - - if (py_retlist == NULL) - return NULL; - if (! PyArg_ParseTuple(args, "l", &pid)) - goto error; - - sd = open("/dev/arp", O_RDWR); - if (sd == -1) { - PyErr_SetFromErrnoWithFilename(PyExc_OSError, "/dev/arp"); - goto error; - } - - ret = ioctl(sd, I_PUSH, "tcp"); - if (ret == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - ret = ioctl(sd, I_PUSH, "udp"); - if (ret == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - // - // OK, this mess is basically copied and pasted from nxsensor project - // which copied and pasted it from netstat source code, mibget() - // function. Also see: - // http://stackoverflow.com/questions/8723598/ - tor.PRIM_type = T_SVR4_OPTMGMT_REQ; - tor.OPT_offset = sizeof (struct T_optmgmt_req); - tor.OPT_length = sizeof (struct opthdr); - tor.MGMT_flags = T_CURRENT; - mibhdr.level = MIB2_IP; - mibhdr.name = 0; - -#ifdef NEW_MIB_COMPLIANT - mibhdr.len = 1; -#else - mibhdr.len = 0; -#endif - memcpy(buf, &tor, sizeof tor); - memcpy(buf + tor.OPT_offset, &mibhdr, sizeof mibhdr); - - ctlbuf.buf = buf; - ctlbuf.len = tor.OPT_offset + tor.OPT_length; - flags = 0; // request to be sent in non-priority - - if (putmsg(sd, &ctlbuf, (struct strbuf *)0, flags) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - ctlbuf.maxlen = sizeof (buf); - for (;;) { - flags = 0; - getcode = getmsg(sd, &ctlbuf, (struct strbuf *)0, &flags); - memcpy(&toa, buf, sizeof toa); - memcpy(&tea, buf, sizeof tea); - - if (getcode != MOREDATA || - ctlbuf.len < (int)sizeof (struct T_optmgmt_ack) || - toa.PRIM_type != T_OPTMGMT_ACK || - toa.MGMT_flags != T_SUCCESS) - { - break; - } - if (ctlbuf.len >= (int)sizeof (struct T_error_ack) && - tea.PRIM_type == T_ERROR_ACK) - { - PyErr_SetString(PyExc_RuntimeError, "ERROR_ACK"); - goto error; - } - if (getcode == 0 && - ctlbuf.len >= (int)sizeof (struct T_optmgmt_ack) && - toa.PRIM_type == T_OPTMGMT_ACK && - toa.MGMT_flags == T_SUCCESS) - { - PyErr_SetString(PyExc_RuntimeError, "ERROR_T_OPTMGMT_ACK"); - goto error; - } - - memset(&mibhdr, 0x0, sizeof(mibhdr)); - memcpy(&mibhdr, buf + toa.OPT_offset, toa.OPT_length); - - databuf.maxlen = mibhdr.len; - databuf.len = 0; - databuf.buf = (char *)malloc((int)mibhdr.len); - if (!databuf.buf) { - PyErr_NoMemory(); - goto error; - } - databuf_init = 1; - - flags = 0; - getcode = getmsg(sd, (struct strbuf *)0, &databuf, &flags); - if (getcode < 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - // TCPv4 - if (mibhdr.level == MIB2_TCP && mibhdr.name == MIB2_TCP_13) { - num_ent = mibhdr.len / sizeof(mib2_tcpConnEntry_t); - for (i = 0; i < num_ent; i++) { - memcpy(&tp, databuf.buf + i * sizeof tp, sizeof tp); -#ifdef NEW_MIB_COMPLIANT - processed_pid = tp.tcpConnCreationProcess; -#else - processed_pid = 0; -#endif - if (pid != -1 && processed_pid != pid) - continue; - // construct local/remote addresses - inet_ntop(AF_INET, &tp.tcpConnLocalAddress, lip, sizeof(lip)); - inet_ntop(AF_INET, &tp.tcpConnRemAddress, rip, sizeof(rip)); - lport = tp.tcpConnLocalPort; - rport = tp.tcpConnRemPort; - - // contruct python tuple/list - py_laddr = Py_BuildValue("(si)", lip, lport); - if (!py_laddr) - goto error; - if (rport != 0) - py_raddr = Py_BuildValue("(si)", rip, rport); - else { - py_raddr = Py_BuildValue("()"); - } - if (!py_raddr) - goto error; - state = tp.tcpConnEntryInfo.ce_state; - - // add item - py_tuple = Py_BuildValue("(iiiNNiI)", -1, AF_INET, SOCK_STREAM, - py_laddr, py_raddr, state, - processed_pid); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_tuple); - } - } -#if defined(AF_INET6) - // TCPv6 - else if (mibhdr.level == MIB2_TCP6 && mibhdr.name == MIB2_TCP6_CONN) - { - num_ent = mibhdr.len / sizeof(mib2_tcp6ConnEntry_t); - - for (i = 0; i < num_ent; i++) { - memcpy(&tp6, databuf.buf + i * sizeof tp6, sizeof tp6); -#ifdef NEW_MIB_COMPLIANT - processed_pid = tp6.tcp6ConnCreationProcess; -#else - processed_pid = 0; -#endif - if (pid != -1 && processed_pid != pid) - continue; - // construct local/remote addresses - inet_ntop(AF_INET6, &tp6.tcp6ConnLocalAddress, lip, sizeof(lip)); - inet_ntop(AF_INET6, &tp6.tcp6ConnRemAddress, rip, sizeof(rip)); - lport = tp6.tcp6ConnLocalPort; - rport = tp6.tcp6ConnRemPort; - - // contruct python tuple/list - py_laddr = Py_BuildValue("(si)", lip, lport); - if (!py_laddr) - goto error; - if (rport != 0) - py_raddr = Py_BuildValue("(si)", rip, rport); - else - py_raddr = Py_BuildValue("()"); - if (!py_raddr) - goto error; - state = tp6.tcp6ConnEntryInfo.ce_state; - - // add item - py_tuple = Py_BuildValue("(iiiNNiI)", -1, AF_INET6, SOCK_STREAM, - py_laddr, py_raddr, state, processed_pid); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_tuple); - } - } -#endif - // UDPv4 - else if (mibhdr.level == MIB2_UDP || mibhdr.level == MIB2_UDP_ENTRY) { - num_ent = mibhdr.len / sizeof(mib2_udpEntry_t); - assert(num_ent * sizeof(mib2_udpEntry_t) == mibhdr.len); - for (i = 0; i < num_ent; i++) { - memcpy(&ude, databuf.buf + i * sizeof ude, sizeof ude); -#ifdef NEW_MIB_COMPLIANT - processed_pid = ude.udpCreationProcess; -#else - processed_pid = 0; -#endif - if (pid != -1 && processed_pid != pid) - continue; - // XXX Very ugly hack! It seems we get here only the first - // time we bump into a UDPv4 socket. PID is a very high - // number (clearly impossible) and the address does not - // belong to any valid interface. Not sure what else - // to do other than skipping. - if (processed_pid > 131072) - continue; - inet_ntop(AF_INET, &ude.udpLocalAddress, lip, sizeof(lip)); - lport = ude.udpLocalPort; - py_laddr = Py_BuildValue("(si)", lip, lport); - if (!py_laddr) - goto error; - py_raddr = Py_BuildValue("()"); - if (!py_raddr) - goto error; - py_tuple = Py_BuildValue("(iiiNNiI)", -1, AF_INET, SOCK_DGRAM, - py_laddr, py_raddr, PSUTIL_CONN_NONE, - processed_pid); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_tuple); - } - } -#if defined(AF_INET6) - // UDPv6 - else if (mibhdr.level == MIB2_UDP6 || - mibhdr.level == MIB2_UDP6_ENTRY) - { - num_ent = mibhdr.len / sizeof(mib2_udp6Entry_t); - for (i = 0; i < num_ent; i++) { - memcpy(&ude6, databuf.buf + i * sizeof ude6, sizeof ude6); -#ifdef NEW_MIB_COMPLIANT - processed_pid = ude6.udp6CreationProcess; -#else - processed_pid = 0; -#endif - if (pid != -1 && processed_pid != pid) - continue; - inet_ntop(AF_INET6, &ude6.udp6LocalAddress, lip, sizeof(lip)); - lport = ude6.udp6LocalPort; - py_laddr = Py_BuildValue("(si)", lip, lport); - if (!py_laddr) - goto error; - py_raddr = Py_BuildValue("()"); - if (!py_raddr) - goto error; - py_tuple = Py_BuildValue("(iiiNNiI)", -1, AF_INET6, SOCK_DGRAM, - py_laddr, py_raddr, PSUTIL_CONN_NONE, - processed_pid); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_tuple); - } - } -#endif - free(databuf.buf); - } - - close(sd); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_XDECREF(py_laddr); - Py_XDECREF(py_raddr); - Py_DECREF(py_retlist); - if (databuf_init == 1) - free(databuf.buf); - if (sd != 0) - close(sd); - return NULL; -} - - -static PyObject * -psutil_boot_time(PyObject *self, PyObject *args) { - float boot_time = 0.0; - struct utmpx *ut; - - setutxent(); - while (NULL != (ut = getutxent())) { - if (ut->ut_type == BOOT_TIME) { - boot_time = (float)ut->ut_tv.tv_sec; - break; - } - } - endutxent(); - if (fabs(boot_time) < 0.000001) { - /* could not find BOOT_TIME in getutxent loop */ - PyErr_SetString(PyExc_RuntimeError, "can't determine boot time"); - return NULL; - } - return Py_BuildValue("f", boot_time); -} - - -/* - * Return the number of physical CPU cores on the system. - */ -static PyObject * -psutil_cpu_count_phys(PyObject *self, PyObject *args) { - kstat_ctl_t *kc; - kstat_t *ksp; - int ncpus = 0; - - kc = kstat_open(); - if (kc == NULL) - goto error; - ksp = kstat_lookup(kc, "cpu_info", -1, NULL); - if (ksp == NULL) - goto error; - - for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { - if (strcmp(ksp->ks_module, "cpu_info") != 0) - continue; - if (kstat_read(kc, ksp, NULL) == -1) - goto error; - ncpus += 1; - } - - kstat_close(kc); - if (ncpus > 0) - return Py_BuildValue("i", ncpus); - else - goto error; - -error: - // mimic os.cpu_count() - if (kc != NULL) - kstat_close(kc); - Py_RETURN_NONE; -} - - -/* - * Return stats about a particular network - * interface. References: - * https://github.com/dpaleino/wicd/blob/master/wicd/backends/be-ioctl.py - * http://www.i-scream.org/libstatgrab/ - */ -static PyObject* -psutil_net_if_stats(PyObject* self, PyObject* args) { - kstat_ctl_t *kc = NULL; - kstat_t *ksp; - kstat_named_t *knp; - int ret; - int sock = -1; - int duplex; - int speed; - - PyObject *py_retdict = PyDict_New(); - PyObject *py_ifc_info = NULL; - PyObject *py_is_up = NULL; - - if (py_retdict == NULL) - return NULL; - kc = kstat_open(); - if (kc == NULL) - goto error; - sock = socket(AF_INET, SOCK_DGRAM, 0); - if (sock == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { - if (strcmp(ksp->ks_class, "net") == 0) { - struct lifreq ifr; - - kstat_read(kc, ksp, NULL); - if (ksp->ks_type != KSTAT_TYPE_NAMED) - continue; - if (strcmp(ksp->ks_class, "net") != 0) - continue; - - strncpy(ifr.lifr_name, ksp->ks_name, sizeof(ifr.lifr_name)); - ret = ioctl(sock, SIOCGLIFFLAGS, &ifr); - if (ret == -1) - continue; // not a network interface - - // is up? - if ((ifr.lifr_flags & IFF_UP) != 0) { - if ((knp = kstat_data_lookup(ksp, "link_up")) != NULL) { - if (knp->value.ui32 != 0u) - py_is_up = Py_True; - else - py_is_up = Py_False; - } - else { - py_is_up = Py_True; - } - } - else { - py_is_up = Py_False; - } - Py_INCREF(py_is_up); - - // duplex - duplex = 0; // unknown - if ((knp = kstat_data_lookup(ksp, "link_duplex")) != NULL) { - if (knp->value.ui32 == 1) - duplex = 1; // half - else if (knp->value.ui32 == 2) - duplex = 2; // full - } - - // speed - if ((knp = kstat_data_lookup(ksp, "ifspeed")) != NULL) - // expressed in bits per sec, we want mega bits per sec - speed = (int)knp->value.ui64 / 1000000; - else - speed = 0; - - // mtu - ret = ioctl(sock, SIOCGLIFMTU, &ifr); - if (ret == -1) - goto error; - - py_ifc_info = Py_BuildValue("(Oiii)", py_is_up, duplex, speed, - ifr.lifr_mtu); - if (!py_ifc_info) - goto error; - if (PyDict_SetItemString(py_retdict, ksp->ks_name, py_ifc_info)) - goto error; - Py_CLEAR(py_ifc_info); - } - } - - close(sock); - kstat_close(kc); - return py_retdict; - -error: - Py_XDECREF(py_is_up); - Py_XDECREF(py_ifc_info); - Py_DECREF(py_retdict); - if (sock != -1) - close(sock); - if (kc != NULL) - kstat_close(kc); - PyErr_SetFromErrno(PyExc_OSError); - return NULL; -} - - -/* - * Return CPU statistics. - */ -static PyObject * -psutil_cpu_stats(PyObject *self, PyObject *args) { - kstat_ctl_t *kc; - kstat_t *ksp; - cpu_stat_t cs; - unsigned int ctx_switches = 0; - unsigned int interrupts = 0; - unsigned int traps = 0; - unsigned int syscalls = 0; - - kc = kstat_open(); - if (kc == NULL) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (ksp = kc->kc_chain; ksp != NULL; ksp = ksp->ks_next) { - if (strcmp(ksp->ks_module, "cpu_stat") == 0) { - if (kstat_read(kc, ksp, &cs) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - // voluntary + involuntary - ctx_switches += cs.cpu_sysinfo.pswitch + cs.cpu_sysinfo.inv_swtch; - interrupts += cs.cpu_sysinfo.intr; - traps += cs.cpu_sysinfo.trap; - syscalls += cs.cpu_sysinfo.syscall; - } - } - - kstat_close(kc); - return Py_BuildValue( - "IIII", ctx_switches, interrupts, syscalls, traps); - -error: - if (kc != NULL) - kstat_close(kc); - return NULL; -} - - -/* - * define the psutil C module methods and initialize the module. - */ -static PyMethodDef -PsutilMethods[] = { - // --- process-related functions - {"proc_basic_info", psutil_proc_basic_info, METH_VARARGS, - "Return process ppid, rss, vms, ctime, nice, nthreads, status and tty"}, - {"proc_name_and_args", psutil_proc_name_and_args, METH_VARARGS, - "Return process name and args."}, - {"proc_environ", psutil_proc_environ, METH_VARARGS, - "Return process environment."}, - {"proc_cpu_times", psutil_proc_cpu_times, METH_VARARGS, - "Return process user and system CPU times."}, - {"proc_cred", psutil_proc_cred, METH_VARARGS, - "Return process uids/gids."}, - {"query_process_thread", psutil_proc_query_thread, METH_VARARGS, - "Return info about a process thread"}, - {"proc_memory_maps", psutil_proc_memory_maps, METH_VARARGS, - "Return process memory mappings"}, - {"proc_num_ctx_switches", psutil_proc_num_ctx_switches, METH_VARARGS, - "Return the number of context switches performed by process"}, - {"proc_cpu_num", psutil_proc_cpu_num, METH_VARARGS, - "Return what CPU the process is on"}, - - // --- system-related functions - {"swap_mem", psutil_swap_mem, METH_VARARGS, - "Return information about system swap memory."}, - {"users", psutil_users, METH_VARARGS, - "Return currently connected users."}, - {"disk_partitions", psutil_disk_partitions, METH_VARARGS, - "Return disk partitions."}, - {"per_cpu_times", psutil_per_cpu_times, METH_VARARGS, - "Return system per-CPU times."}, - {"disk_io_counters", psutil_disk_io_counters, METH_VARARGS, - "Return a Python dict of tuples for disk I/O statistics."}, - {"net_io_counters", psutil_net_io_counters, METH_VARARGS, - "Return a Python dict of tuples for network I/O statistics."}, - {"boot_time", psutil_boot_time, METH_VARARGS, - "Return system boot time in seconds since the EPOCH."}, - {"cpu_count_phys", psutil_cpu_count_phys, METH_VARARGS, - "Return the number of physical CPUs on the system."}, - {"net_connections", psutil_net_connections, METH_VARARGS, - "Return TCP and UDP syste-wide open connections."}, - {"net_if_stats", psutil_net_if_stats, METH_VARARGS, - "Return NIC stats (isup, duplex, speed, mtu)"}, - {"cpu_stats", psutil_cpu_stats, METH_VARARGS, - "Return CPU statistics"}, - - // --- others - {"set_testing", psutil_set_testing, METH_NOARGS, - "Set psutil in testing mode"}, - - {NULL, NULL, 0, NULL} -}; - - -struct module_state { - PyObject *error; -}; - -#if PY_MAJOR_VERSION >= 3 -#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) -#else -#define GETSTATE(m) (&_state) -#endif - -#if PY_MAJOR_VERSION >= 3 - -static int -psutil_sunos_traverse(PyObject *m, visitproc visit, void *arg) { - Py_VISIT(GETSTATE(m)->error); - return 0; -} - -static int -psutil_sunos_clear(PyObject *m) { - Py_CLEAR(GETSTATE(m)->error); - return 0; -} - -static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, - "psutil_sunos", - NULL, - sizeof(struct module_state), - PsutilMethods, - NULL, - psutil_sunos_traverse, - psutil_sunos_clear, - NULL -}; - -#define INITERROR return NULL - -PyMODINIT_FUNC PyInit__psutil_sunos(void) - -#else -#define INITERROR return - -void init_psutil_sunos(void) -#endif -{ -#if PY_MAJOR_VERSION >= 3 - PyObject *module = PyModule_Create(&moduledef); -#else - PyObject *module = Py_InitModule("_psutil_sunos", PsutilMethods); -#endif - if (module == NULL) - INITERROR; - - if (psutil_setup() != 0) - INITERROR; - - PyModule_AddIntConstant(module, "version", PSUTIL_VERSION); - - PyModule_AddIntConstant(module, "SSLEEP", SSLEEP); - PyModule_AddIntConstant(module, "SRUN", SRUN); - PyModule_AddIntConstant(module, "SZOMB", SZOMB); - PyModule_AddIntConstant(module, "SSTOP", SSTOP); - PyModule_AddIntConstant(module, "SIDL", SIDL); - PyModule_AddIntConstant(module, "SONPROC", SONPROC); - PyModule_AddIntConstant(module, "SWAIT", SWAIT); - - PyModule_AddIntConstant(module, "PRNODEV", PRNODEV); // for process tty - - PyModule_AddIntConstant(module, "TCPS_CLOSED", TCPS_CLOSED); - PyModule_AddIntConstant(module, "TCPS_CLOSING", TCPS_CLOSING); - PyModule_AddIntConstant(module, "TCPS_CLOSE_WAIT", TCPS_CLOSE_WAIT); - PyModule_AddIntConstant(module, "TCPS_LISTEN", TCPS_LISTEN); - PyModule_AddIntConstant(module, "TCPS_ESTABLISHED", TCPS_ESTABLISHED); - PyModule_AddIntConstant(module, "TCPS_SYN_SENT", TCPS_SYN_SENT); - PyModule_AddIntConstant(module, "TCPS_SYN_RCVD", TCPS_SYN_RCVD); - PyModule_AddIntConstant(module, "TCPS_FIN_WAIT_1", TCPS_FIN_WAIT_1); - PyModule_AddIntConstant(module, "TCPS_FIN_WAIT_2", TCPS_FIN_WAIT_2); - PyModule_AddIntConstant(module, "TCPS_LAST_ACK", TCPS_LAST_ACK); - PyModule_AddIntConstant(module, "TCPS_TIME_WAIT", TCPS_TIME_WAIT); - // sunos specific - PyModule_AddIntConstant(module, "TCPS_IDLE", TCPS_IDLE); - // sunos specific - PyModule_AddIntConstant(module, "TCPS_BOUND", TCPS_BOUND); - PyModule_AddIntConstant(module, "PSUTIL_CONN_NONE", PSUTIL_CONN_NONE); - - if (module == NULL) - INITERROR; -#if PY_MAJOR_VERSION >= 3 - return module; -#endif -} diff --git a/ddtrace/vendor/psutil/_psutil_windows.c b/ddtrace/vendor/psutil/_psutil_windows.c deleted file mode 100644 index f35d0076d29..00000000000 --- a/ddtrace/vendor/psutil/_psutil_windows.c +++ /dev/null @@ -1,3723 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, 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. - * - * Windows platform-specific module methods for _psutil_windows. - * - * List of undocumented Windows NT APIs which are used in here and in - * other modules: - * - NtQuerySystemInformation - * - NtQueryInformationProcess - * - NtQueryObject - * - NtSuspendProcess - * - NtResumeProcess - */ - -// Fixes clash between winsock2.h and windows.h -#define WIN32_LEAN_AND_MEAN - -#include -#include -#include -#include -#include // disk_io_counters() -#include -#include -#include // users() -#include // cpu_freq() -#if (_WIN32_WINNT >= 0x0600) // Windows >= Vista -#include // net_connections() -#endif - -// Link with Iphlpapi.lib -#pragma comment(lib, "IPHLPAPI.lib") - -#include "arch/windows/ntextapi.h" -#include "arch/windows/global.h" -#include "arch/windows/security.h" -#include "arch/windows/process_info.h" -#include "arch/windows/process_handles.h" -#include "arch/windows/inet_ntop.h" -#include "arch/windows/services.h" -#include "arch/windows/wmi.h" -#include "_psutil_common.h" - - -/* - * ============================================================================ - * Utilities - * ============================================================================ - */ - -#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) -#define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) -#define LO_T 1e-7 -#define HI_T 429.4967296 -#define BYTESWAP_USHORT(x) ((((USHORT)(x) << 8) | ((USHORT)(x) >> 8)) & 0xffff) -#ifndef AF_INET6 -#define AF_INET6 23 -#endif - - -PIP_ADAPTER_ADDRESSES -psutil_get_nic_addresses() { - // allocate a 15 KB buffer to start with - int outBufLen = 15000; - DWORD dwRetVal = 0; - ULONG attempts = 0; - PIP_ADAPTER_ADDRESSES pAddresses = NULL; - - do { - pAddresses = (IP_ADAPTER_ADDRESSES *) malloc(outBufLen); - if (pAddresses == NULL) { - PyErr_NoMemory(); - return NULL; - } - - dwRetVal = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, pAddresses, - &outBufLen); - if (dwRetVal == ERROR_BUFFER_OVERFLOW) { - free(pAddresses); - pAddresses = NULL; - } - else { - break; - } - - attempts++; - } while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (attempts < 3)); - - if (dwRetVal != NO_ERROR) { - PyErr_SetString( - PyExc_RuntimeError, "GetAdaptersAddresses() syscall failed."); - return NULL; - } - - return pAddresses; -} - - -/* - * Return the number of logical, active CPUs. Return 0 if undetermined. - * See discussion at: https://bugs.python.org/issue33166#msg314631 - */ -unsigned int -psutil_get_num_cpus(int fail_on_err) { - unsigned int ncpus = 0; - - // Minimum requirement: Windows 7 - if (psutil_GetActiveProcessorCount != NULL) { - ncpus = psutil_GetActiveProcessorCount(ALL_PROCESSOR_GROUPS); - if ((ncpus == 0) && (fail_on_err == 1)) { - PyErr_SetFromWindowsErr(0); - } - } - else { - psutil_debug("GetActiveProcessorCount() not available; " - "using GetSystemInfo()"); - ncpus = (unsigned int)PSUTIL_SYSTEM_INFO.dwNumberOfProcessors; - if ((ncpus <= 0) && (fail_on_err == 1)) { - PyErr_SetString( - PyExc_RuntimeError, - "GetSystemInfo() failed to retrieve CPU count"); - } - } - return ncpus; -} - - -/* - * ============================================================================ - * Public Python API - * ============================================================================ - */ - -// Raised by Process.wait(). -static PyObject *TimeoutExpired; -static PyObject *TimeoutAbandoned; - -/* - * Return a Python float representing the system uptime expressed in seconds - * since the epoch. - */ -static PyObject * -psutil_boot_time(PyObject *self, PyObject *args) { - ULONGLONG uptime; - time_t pt; - FILETIME fileTime; - ULONGLONG ll; - - GetSystemTimeAsFileTime(&fileTime); - /* - HUGE thanks to: - http://johnstewien.spaces.live.com/blog/cns!E6885DB5CEBABBC8!831.entry - - This function converts the FILETIME structure to the 32 bit - Unix time structure. - The time_t is a 32-bit value for the number of seconds since - January 1, 1970. A FILETIME is a 64-bit for the number of - 100-nanosecond periods since January 1, 1601. Convert by - subtracting the number of 100-nanosecond period between 01-01-1970 - and 01-01-1601, from time_t the divide by 1e+7 to get to the same - base granularity. - */ - ll = (((ULONGLONG) - (fileTime.dwHighDateTime)) << 32) + fileTime.dwLowDateTime; - pt = (time_t)((ll - 116444736000000000ull) / 10000000ull); - - if (psutil_GetTickCount64 != NULL) { - // Windows >= Vista - uptime = psutil_GetTickCount64() / 1000ull; - } - else { - // Windows XP. - // GetTickCount() time will wrap around to zero if the - // system is run continuously for 49.7 days. - uptime = (ULONGLONG)GetTickCount() / 1000ull; - } - return Py_BuildValue("K", pt - uptime); -} - - -/* - * Return 1 if PID exists in the current process list, else 0. - */ -static PyObject * -psutil_pid_exists(PyObject *self, PyObject *args) { - long pid; - int status; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - status = psutil_pid_is_running(pid); - if (-1 == status) - return NULL; // exception raised in psutil_pid_is_running() - return PyBool_FromLong(status); -} - - -/* - * Return a Python list of all the PIDs running on the system. - */ -static PyObject * -psutil_pids(PyObject *self, PyObject *args) { - DWORD *proclist = NULL; - DWORD numberOfReturnedPIDs; - DWORD i; - PyObject *py_pid = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - proclist = psutil_get_pids(&numberOfReturnedPIDs); - if (proclist == NULL) - goto error; - - for (i = 0; i < numberOfReturnedPIDs; i++) { - py_pid = Py_BuildValue("I", proclist[i]); - if (!py_pid) - goto error; - if (PyList_Append(py_retlist, py_pid)) - goto error; - Py_CLEAR(py_pid); - } - - // free C array allocated for PIDs - free(proclist); - return py_retlist; - -error: - Py_XDECREF(py_pid); - Py_DECREF(py_retlist); - if (proclist != NULL) - free(proclist); - return NULL; -} - - -/* - * Kill a process given its PID. - */ -static PyObject * -psutil_proc_kill(PyObject *self, PyObject *args) { - HANDLE hProcess; - long pid; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (pid == 0) - return AccessDenied(""); - - hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pid); - if (hProcess == NULL) { - if (GetLastError() == ERROR_INVALID_PARAMETER) { - // see https://github.com/giampaolo/psutil/issues/24 - psutil_debug("OpenProcess -> ERROR_INVALID_PARAMETER turned " - "into NoSuchProcess"); - NoSuchProcess(""); - } - else { - PyErr_SetFromWindowsErr(0); - } - return NULL; - } - - if (! TerminateProcess(hProcess, SIGTERM)) { - // ERROR_ACCESS_DENIED may happen if the process already died. See: - // https://github.com/giampaolo/psutil/issues/1099 - if (GetLastError() != ERROR_ACCESS_DENIED) { - PyErr_SetFromOSErrnoWithSyscall("TerminateProcess"); - return NULL; - } - } - - CloseHandle(hProcess); - Py_RETURN_NONE; -} - - -/* - * Wait for process to terminate and return its exit code. - */ -static PyObject * -psutil_proc_wait(PyObject *self, PyObject *args) { - HANDLE hProcess; - DWORD ExitCode; - DWORD retVal; - long pid; - long timeout; - - if (! PyArg_ParseTuple(args, "ll", &pid, &timeout)) - return NULL; - if (pid == 0) - return AccessDenied(""); - - hProcess = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION, - FALSE, pid); - if (hProcess == NULL) { - if (GetLastError() == ERROR_INVALID_PARAMETER) { - // no such process; we do not want to raise NSP but - // return None instead. - Py_RETURN_NONE; - } - else - return PyErr_SetFromWindowsErr(0); - } - - // wait until the process has terminated - Py_BEGIN_ALLOW_THREADS - retVal = WaitForSingleObject(hProcess, timeout); - Py_END_ALLOW_THREADS - - // handle return code - if (retVal == WAIT_FAILED) { - PyErr_SetFromOSErrnoWithSyscall("WaitForSingleObject"); - CloseHandle(hProcess); - return NULL; - } - if (retVal == WAIT_TIMEOUT) { - PyErr_SetString(TimeoutExpired, - "WaitForSingleObject() returned WAIT_TIMEOUT"); - CloseHandle(hProcess); - return NULL; - } - if (retVal == WAIT_ABANDONED) { - psutil_debug("WaitForSingleObject() -> WAIT_ABANDONED"); - PyErr_SetString(TimeoutAbandoned, - "WaitForSingleObject() returned WAIT_ABANDONED"); - CloseHandle(hProcess); - return NULL; - } - - // WaitForSingleObject() returned WAIT_OBJECT_0. It means the - // process is gone so we can get its process exit code. The PID - // may still stick around though but we'll handle that from Python. - if (GetExitCodeProcess(hProcess, &ExitCode) == 0) { - PyErr_SetFromOSErrnoWithSyscall("GetExitCodeProcess"); - CloseHandle(hProcess); - return NULL; - } - - CloseHandle(hProcess); - -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong((long) ExitCode); -#else - return PyInt_FromLong((long) ExitCode); -#endif -} - - -/* - * Return a Python tuple (user_time, kernel_time) - */ -static PyObject * -psutil_proc_cpu_times(PyObject *self, PyObject *args) { - long pid; - HANDLE hProcess; - FILETIME ftCreate, ftExit, ftKernel, ftUser; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - hProcess = psutil_handle_from_pid(pid, PROCESS_QUERY_LIMITED_INFORMATION); - - if (hProcess == NULL) - return NULL; - if (! GetProcessTimes(hProcess, &ftCreate, &ftExit, &ftKernel, &ftUser)) { - if (GetLastError() == ERROR_ACCESS_DENIED) { - // usually means the process has died so we throw a NoSuchProcess - // here - NoSuchProcess(""); - } - else { - PyErr_SetFromWindowsErr(0); - } - CloseHandle(hProcess); - return NULL; - } - - CloseHandle(hProcess); - - /* - * User and kernel times are represented as a FILETIME structure - * which contains a 64-bit value representing the number of - * 100-nanosecond intervals since January 1, 1601 (UTC): - * http://msdn.microsoft.com/en-us/library/ms724284(VS.85).aspx - * To convert it into a float representing the seconds that the - * process has executed in user/kernel mode I borrowed the code - * below from Python's Modules/posixmodule.c - */ - return Py_BuildValue( - "(dd)", - (double)(ftUser.dwHighDateTime * 429.4967296 + \ - ftUser.dwLowDateTime * 1e-7), - (double)(ftKernel.dwHighDateTime * 429.4967296 + \ - ftKernel.dwLowDateTime * 1e-7) - ); -} - - -/* - * Return a Python float indicating the process create time expressed in - * seconds since the epoch. - */ -static PyObject * -psutil_proc_create_time(PyObject *self, PyObject *args) { - long pid; - long long unix_time; - HANDLE hProcess; - FILETIME ftCreate, ftExit, ftKernel, ftUser; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - // special case for PIDs 0 and 4, return system boot time - if (0 == pid || 4 == pid) - return psutil_boot_time(NULL, NULL); - - hProcess = psutil_handle_from_pid(pid, PROCESS_QUERY_LIMITED_INFORMATION); - if (hProcess == NULL) - return NULL; - if (! GetProcessTimes(hProcess, &ftCreate, &ftExit, &ftKernel, &ftUser)) { - if (GetLastError() == ERROR_ACCESS_DENIED) { - // usually means the process has died so we throw a - // NoSuchProcess here - NoSuchProcess(""); - } - else { - PyErr_SetFromWindowsErr(0); - } - CloseHandle(hProcess); - return NULL; - } - - CloseHandle(hProcess); - - /* - // Make sure the process is not gone as OpenProcess alone seems to be - // unreliable in doing so (it seems a previous call to p.wait() makes - // it unreliable). - // This check is important as creation time is used to make sure the - // process is still running. - ret = GetExitCodeProcess(hProcess, &exitCode); - CloseHandle(hProcess); - if (ret != 0) { - if (exitCode != STILL_ACTIVE) - return NoSuchProcess(""); - } - else { - // Ignore access denied as it means the process is still alive. - // For all other errors, we want an exception. - if (GetLastError() != ERROR_ACCESS_DENIED) - return PyErr_SetFromWindowsErr(0); - } - */ - - // Convert the FILETIME structure to a Unix time. - // It's the best I could find by googling and borrowing code here - // and there. The time returned has a precision of 1 second. - unix_time = ((LONGLONG)ftCreate.dwHighDateTime) << 32; - unix_time += ftCreate.dwLowDateTime - 116444736000000000LL; - unix_time /= 10000000; - return Py_BuildValue("d", (double)unix_time); -} - - -/* - * Return the number of active, logical CPUs. - */ -static PyObject * -psutil_cpu_count_logical(PyObject *self, PyObject *args) { - unsigned int ncpus; - - ncpus = psutil_get_num_cpus(0); - if (ncpus != 0) - return Py_BuildValue("I", ncpus); - else - Py_RETURN_NONE; // mimick os.cpu_count() -} - - -/* - * Return the number of physical CPU cores (hyper-thread CPUs count - * is excluded). - */ -static PyObject * -psutil_cpu_count_phys(PyObject *self, PyObject *args) { - DWORD rc; - PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX buffer = NULL; - PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX ptr = NULL; - DWORD length = 0; - DWORD offset = 0; - DWORD ncpus = 0; - DWORD prev_processor_info_size = 0; - - // GetLogicalProcessorInformationEx() is available from Windows 7 - // onward. Differently from GetLogicalProcessorInformation() - // it supports process groups, meaning this is able to report more - // than 64 CPUs. See: - // https://bugs.python.org/issue33166 - if (psutil_GetLogicalProcessorInformationEx == NULL) { - psutil_debug("Win < 7; cpu_count_phys() forced to None"); - Py_RETURN_NONE; - } - - while (1) { - rc = psutil_GetLogicalProcessorInformationEx( - RelationAll, buffer, &length); - if (rc == FALSE) { - if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - if (buffer) { - free(buffer); - } - buffer = \ - (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)malloc(length); - if (NULL == buffer) { - PyErr_NoMemory(); - return NULL; - } - } - else { - psutil_debug("GetLogicalProcessorInformationEx() returned ", - GetLastError()); - goto return_none; - } - } - else { - break; - } - } - - ptr = buffer; - while (offset < length) { - // Advance ptr by the size of the previous - // SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX struct. - ptr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)\ - (((char*)ptr) + prev_processor_info_size); - - if (ptr->Relationship == RelationProcessorCore) { - ncpus += 1; - } - - // When offset == length, we've reached the last processor - // info struct in the buffer. - offset += ptr->Size; - prev_processor_info_size = ptr->Size; - } - - free(buffer); - if (ncpus != 0) { - return Py_BuildValue("I", ncpus); - } - else { - psutil_debug("GetLogicalProcessorInformationEx() count was 0"); - Py_RETURN_NONE; // mimick os.cpu_count() - } - -return_none: - if (buffer != NULL) - free(buffer); - Py_RETURN_NONE; -} - - -/* - * Return process cmdline as a Python list of cmdline arguments. - */ -static PyObject * -psutil_proc_cmdline(PyObject *self, PyObject *args, PyObject *kwdict) { - long pid; - int pid_return; - int use_peb; - PyObject *py_usepeb = Py_True; - static char *keywords[] = {"pid", "use_peb", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwdict, "i|O", - keywords, &pid, &py_usepeb)) { - return NULL; - } - if ((pid == 0) || (pid == 4)) - return Py_BuildValue("[]"); - - pid_return = psutil_pid_is_running(pid); - if (pid_return == 0) - return NoSuchProcess(""); - if (pid_return == -1) - return NULL; - - use_peb = (py_usepeb == Py_True) ? 1 : 0; - return psutil_get_cmdline(pid, use_peb); -} - - -/* - * Return process cmdline as a Python list of cmdline arguments. - */ -static PyObject * -psutil_proc_environ(PyObject *self, PyObject *args) { - long pid; - int pid_return; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if ((pid == 0) || (pid == 4)) - return Py_BuildValue("s", ""); - - pid_return = psutil_pid_is_running(pid); - if (pid_return == 0) - return NoSuchProcess(""); - if (pid_return == -1) - return NULL; - - return psutil_get_environ(pid); -} - - -/* - * Return process executable path. - */ -static PyObject * -psutil_proc_exe(PyObject *self, PyObject *args) { - long pid; - HANDLE hProcess; - wchar_t exe[MAX_PATH]; -#if (_WIN32_WINNT >= 0x0600) // >= Vista - unsigned int size = sizeof(exe); -#endif - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - hProcess = psutil_handle_from_pid(pid, PROCESS_QUERY_LIMITED_INFORMATION); - if (NULL == hProcess) - return NULL; - - // Here we differentiate between XP and Vista+ because - // QueryFullProcessImageNameW is better than GetProcessImageFileNameW - // (avoid using QueryDosDevice on the returned path), see: - // https://github.com/giampaolo/psutil/issues/1394 -#if (_WIN32_WINNT >= 0x0600) // Windows >= Vista - memset(exe, 0, MAX_PATH); - if (QueryFullProcessImageNameW(hProcess, 0, exe, &size) == 0) { - PyErr_SetFromOSErrnoWithSyscall("QueryFullProcessImageNameW"); - CloseHandle(hProcess); - return NULL; - } -#else // Windows XP - if (GetProcessImageFileNameW(hProcess, exe, MAX_PATH) == 0) { - // see: https://github.com/giampaolo/psutil/issues/1394 - if (GetLastError() == 0) - PyErr_SetFromWindowsErr(ERROR_ACCESS_DENIED); - else - PyErr_SetFromOSErrnoWithSyscall("GetProcessImageFileNameW"); - CloseHandle(hProcess); - return NULL; - } -#endif - CloseHandle(hProcess); - return PyUnicode_FromWideChar(exe, wcslen(exe)); -} - - -/* - * Return process base name. - * Note: psutil_proc_exe() is attempted first because it's faster - * but it raise AccessDenied for processes owned by other users - * in which case we fall back on using this. - */ -static PyObject * -psutil_proc_name(PyObject *self, PyObject *args) { - long pid; - int ok; - PROCESSENTRY32W pentry; - HANDLE hSnapShot; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, pid); - if (hSnapShot == INVALID_HANDLE_VALUE) - return PyErr_SetFromOSErrnoWithSyscall("CreateToolhelp32Snapshot"); - pentry.dwSize = sizeof(PROCESSENTRY32W); - ok = Process32FirstW(hSnapShot, &pentry); - if (! ok) { - PyErr_SetFromOSErrnoWithSyscall("Process32FirstW"); - CloseHandle(hSnapShot); - return NULL; - } - while (ok) { - if (pentry.th32ProcessID == pid) { - CloseHandle(hSnapShot); - return PyUnicode_FromWideChar( - pentry.szExeFile, wcslen(pentry.szExeFile)); - } - ok = Process32NextW(hSnapShot, &pentry); - } - - CloseHandle(hSnapShot); - NoSuchProcess(""); - return NULL; -} - - -/* - * Return process memory information as a Python tuple. - */ -static PyObject * -psutil_proc_memory_info(PyObject *self, PyObject *args) { - HANDLE hProcess; - DWORD pid; -#if (_WIN32_WINNT >= 0x0501) // Windows XP with SP2 - PROCESS_MEMORY_COUNTERS_EX cnt; -#else - PROCESS_MEMORY_COUNTERS cnt; -#endif - SIZE_T private = 0; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - hProcess = psutil_handle_from_pid(pid, PROCESS_QUERY_LIMITED_INFORMATION); - if (NULL == hProcess) - return NULL; - - if (! GetProcessMemoryInfo(hProcess, (PPROCESS_MEMORY_COUNTERS)&cnt, - sizeof(cnt))) { - PyErr_SetFromWindowsErr(0); - CloseHandle(hProcess); - return NULL; - } - -#if (_WIN32_WINNT >= 0x0501) // Windows XP with SP2 - private = cnt.PrivateUsage; -#endif - - CloseHandle(hProcess); - - // PROCESS_MEMORY_COUNTERS values are defined as SIZE_T which on 64bits - // is an (unsigned long long) and on 32bits is an (unsigned int). - // "_WIN64" is defined if we're running a 64bit Python interpreter not - // exclusively if the *system* is 64bit. -#if defined(_WIN64) - return Py_BuildValue( - "(kKKKKKKKKK)", - cnt.PageFaultCount, // unsigned long - (unsigned long long)cnt.PeakWorkingSetSize, - (unsigned long long)cnt.WorkingSetSize, - (unsigned long long)cnt.QuotaPeakPagedPoolUsage, - (unsigned long long)cnt.QuotaPagedPoolUsage, - (unsigned long long)cnt.QuotaPeakNonPagedPoolUsage, - (unsigned long long)cnt.QuotaNonPagedPoolUsage, - (unsigned long long)cnt.PagefileUsage, - (unsigned long long)cnt.PeakPagefileUsage, - (unsigned long long)private); -#else - return Py_BuildValue( - "(kIIIIIIIII)", - cnt.PageFaultCount, // unsigned long - (unsigned int)cnt.PeakWorkingSetSize, - (unsigned int)cnt.WorkingSetSize, - (unsigned int)cnt.QuotaPeakPagedPoolUsage, - (unsigned int)cnt.QuotaPagedPoolUsage, - (unsigned int)cnt.QuotaPeakNonPagedPoolUsage, - (unsigned int)cnt.QuotaNonPagedPoolUsage, - (unsigned int)cnt.PagefileUsage, - (unsigned int)cnt.PeakPagefileUsage, - (unsigned int)private); -#endif -} - - -static int -psutil_GetProcWsetInformation( - DWORD pid, - HANDLE hProcess, - PMEMORY_WORKING_SET_INFORMATION *wSetInfo) -{ - NTSTATUS status; - PVOID buffer; - SIZE_T bufferSize; - - bufferSize = 0x8000; - buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bufferSize); - - while ((status = psutil_NtQueryVirtualMemory( - hProcess, - NULL, - MemoryWorkingSetInformation, - buffer, - bufferSize, - NULL)) == STATUS_INFO_LENGTH_MISMATCH) - { - HeapFree(GetProcessHeap(), 0, buffer); - bufferSize *= 2; - psutil_debug("NtQueryVirtualMemory increase bufsize %zd", bufferSize); - // Fail if we're resizing the buffer to something very large. - if (bufferSize > 256 * 1024 * 1024) { - PyErr_SetString(PyExc_RuntimeError, - "NtQueryVirtualMemory bufsize is too large"); - return 1; - } - buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bufferSize); - } - - if (!NT_SUCCESS(status)) { - if (status == STATUS_ACCESS_DENIED) { - AccessDenied("originated from NtQueryVirtualMemory"); - } - else if (psutil_pid_is_running(pid) == 0) { - NoSuchProcess(""); - } - else { - PyErr_Clear(); - psutil_SetFromNTStatusErr( - status, "NtQueryVirtualMemory(MemoryWorkingSetInformation)"); - } - HeapFree(GetProcessHeap(), 0, buffer); - return 1; - } - - *wSetInfo = (PMEMORY_WORKING_SET_INFORMATION)buffer; - return 0; -} - - -/* - * Returns the USS of the process. - * Reference: - * https://dxr.mozilla.org/mozilla-central/source/xpcom/base/ - * nsMemoryReporterManager.cpp - */ -static PyObject * -psutil_proc_memory_uss(PyObject *self, PyObject *args) { - DWORD pid; - HANDLE hProcess; - PSUTIL_PROCESS_WS_COUNTERS wsCounters; - PMEMORY_WORKING_SET_INFORMATION wsInfo; - ULONG_PTR i; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - hProcess = psutil_handle_from_pid(pid, PROCESS_QUERY_LIMITED_INFORMATION); - if (hProcess == NULL) - return NULL; - - if (psutil_GetProcWsetInformation(pid, hProcess, &wsInfo) != 0) { - CloseHandle(hProcess); - return NULL; - } - memset(&wsCounters, 0, sizeof(PSUTIL_PROCESS_WS_COUNTERS)); - - for (i = 0; i < wsInfo->NumberOfEntries; i++) { - // This is what ProcessHacker does. - /* - wsCounters.NumberOfPages++; - if (wsInfo->WorkingSetInfo[i].ShareCount > 1) - wsCounters.NumberOfSharedPages++; - if (wsInfo->WorkingSetInfo[i].ShareCount == 0) - wsCounters.NumberOfPrivatePages++; - if (wsInfo->WorkingSetInfo[i].Shared) - wsCounters.NumberOfShareablePages++; - */ - - // This is what we do: count shared pages that only one process - // is using as private (USS). - if (!wsInfo->WorkingSetInfo[i].Shared || - wsInfo->WorkingSetInfo[i].ShareCount <= 1) { - wsCounters.NumberOfPrivatePages++; - } - } - - HeapFree(GetProcessHeap(), 0, wsInfo); - CloseHandle(hProcess); - - return Py_BuildValue("I", wsCounters.NumberOfPrivatePages); -} - - -/* - * Return a Python integer indicating the total amount of physical memory - * in bytes. - */ -static PyObject * -psutil_virtual_mem(PyObject *self, PyObject *args) { - MEMORYSTATUSEX memInfo; - memInfo.dwLength = sizeof(MEMORYSTATUSEX); - - if (! GlobalMemoryStatusEx(&memInfo)) - return PyErr_SetFromWindowsErr(0); - return Py_BuildValue("(LLLLLL)", - memInfo.ullTotalPhys, // total - memInfo.ullAvailPhys, // avail - memInfo.ullTotalPageFile, // total page file - memInfo.ullAvailPageFile, // avail page file - memInfo.ullTotalVirtual, // total virtual - memInfo.ullAvailVirtual); // avail virtual -} - -/* - * Retrieves system CPU timing information as a (user, system, idle) - * tuple. On a multiprocessor system, the values returned are the - * sum of the designated times across all processors. - */ -static PyObject * -psutil_cpu_times(PyObject *self, PyObject *args) { - double idle, kernel, user, system; - FILETIME idle_time, kernel_time, user_time; - - if (!GetSystemTimes(&idle_time, &kernel_time, &user_time)) - return PyErr_SetFromWindowsErr(0); - - idle = (double)((HI_T * idle_time.dwHighDateTime) + \ - (LO_T * idle_time.dwLowDateTime)); - user = (double)((HI_T * user_time.dwHighDateTime) + \ - (LO_T * user_time.dwLowDateTime)); - kernel = (double)((HI_T * kernel_time.dwHighDateTime) + \ - (LO_T * kernel_time.dwLowDateTime)); - - // Kernel time includes idle time. - // We return only busy kernel time subtracting idle time from - // kernel time. - system = (kernel - idle); - return Py_BuildValue("(ddd)", user, system, idle); -} - - -/* - * Same as above but for all system CPUs. - */ -static PyObject * -psutil_per_cpu_times(PyObject *self, PyObject *args) { - double idle, kernel, systemt, user, interrupt, dpc; - NTSTATUS status; - _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *sppi = NULL; - UINT i; - unsigned int ncpus; - PyObject *py_tuple = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - - // retrieves number of processors - ncpus = psutil_get_num_cpus(1); - if (ncpus == 0) - goto error; - - // allocates an array of _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION - // structures, one per processor - sppi = (_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *) \ - malloc(ncpus * sizeof(_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)); - if (sppi == NULL) { - PyErr_NoMemory(); - goto error; - } - - // gets cpu time informations - status = psutil_NtQuerySystemInformation( - SystemProcessorPerformanceInformation, - sppi, - ncpus * sizeof(_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION), - NULL); - if (! NT_SUCCESS(status)) { - psutil_SetFromNTStatusErr( - status, - "NtQuerySystemInformation(SystemProcessorPerformanceInformation)" - ); - goto error; - } - - // computes system global times summing each - // processor value - idle = user = kernel = interrupt = dpc = 0; - for (i = 0; i < ncpus; i++) { - py_tuple = NULL; - user = (double)((HI_T * sppi[i].UserTime.HighPart) + - (LO_T * sppi[i].UserTime.LowPart)); - idle = (double)((HI_T * sppi[i].IdleTime.HighPart) + - (LO_T * sppi[i].IdleTime.LowPart)); - kernel = (double)((HI_T * sppi[i].KernelTime.HighPart) + - (LO_T * sppi[i].KernelTime.LowPart)); - interrupt = (double)((HI_T * sppi[i].InterruptTime.HighPart) + - (LO_T * sppi[i].InterruptTime.LowPart)); - dpc = (double)((HI_T * sppi[i].DpcTime.HighPart) + - (LO_T * sppi[i].DpcTime.LowPart)); - - // kernel time includes idle time on windows - // we return only busy kernel time subtracting - // idle time from kernel time - systemt = kernel - idle; - py_tuple = Py_BuildValue( - "(ddddd)", - user, - systemt, - idle, - interrupt, - dpc - ); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_tuple); - } - - free(sppi); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (sppi) - free(sppi); - return NULL; -} - - -/* - * Return process current working directory as a Python string. - */ -static PyObject * -psutil_proc_cwd(PyObject *self, PyObject *args) { - long pid; - int pid_return; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - pid_return = psutil_pid_is_running(pid); - if (pid_return == 0) - return NoSuchProcess(""); - if (pid_return == -1) - return NULL; - - return psutil_get_cwd(pid); -} - - -/* - * Resume or suspends a process - */ -static PyObject * -psutil_proc_suspend_or_resume(PyObject *self, PyObject *args) { - long pid; - NTSTATUS status; - HANDLE hProcess; - PyObject* suspend; - - if (! PyArg_ParseTuple(args, "lO", &pid, &suspend)) - return NULL; - - hProcess = psutil_handle_from_pid(pid, PROCESS_SUSPEND_RESUME); - if (hProcess == NULL) - return NULL; - - if (PyObject_IsTrue(suspend)) - status = psutil_NtSuspendProcess(hProcess); - else - status = psutil_NtResumeProcess(hProcess); - - if (! NT_SUCCESS(status)) { - CloseHandle(hProcess); - return psutil_SetFromNTStatusErr(status, "NtSuspend|ResumeProcess"); - } - - CloseHandle(hProcess); - Py_RETURN_NONE; -} - - -static PyObject * -psutil_proc_threads(PyObject *self, PyObject *args) { - HANDLE hThread; - THREADENTRY32 te32 = {0}; - long pid; - int pid_return; - int rc; - FILETIME ftDummy, ftKernel, ftUser; - HANDLE hThreadSnap = NULL; - PyObject *py_tuple = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - if (! PyArg_ParseTuple(args, "l", &pid)) - goto error; - if (pid == 0) { - // raise AD instead of returning 0 as procexp is able to - // retrieve useful information somehow - AccessDenied(""); - goto error; - } - - pid_return = psutil_pid_is_running(pid); - if (pid_return == 0) { - NoSuchProcess(""); - goto error; - } - if (pid_return == -1) - goto error; - - hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); - if (hThreadSnap == INVALID_HANDLE_VALUE) { - PyErr_SetFromOSErrnoWithSyscall("CreateToolhelp32Snapshot"); - goto error; - } - - // Fill in the size of the structure before using it - te32.dwSize = sizeof(THREADENTRY32); - - if (! Thread32First(hThreadSnap, &te32)) { - PyErr_SetFromOSErrnoWithSyscall("Thread32First"); - goto error; - } - - // Walk the thread snapshot to find all threads of the process. - // If the thread belongs to the process, increase the counter. - do { - if (te32.th32OwnerProcessID == pid) { - py_tuple = NULL; - hThread = NULL; - hThread = OpenThread(THREAD_QUERY_INFORMATION, - FALSE, te32.th32ThreadID); - if (hThread == NULL) { - // thread has disappeared on us - continue; - } - - rc = GetThreadTimes(hThread, &ftDummy, &ftDummy, &ftKernel, - &ftUser); - if (rc == 0) { - PyErr_SetFromOSErrnoWithSyscall("GetThreadTimes"); - goto error; - } - - /* - * User and kernel times are represented as a FILETIME structure - * which contains a 64-bit value representing the number of - * 100-nanosecond intervals since January 1, 1601 (UTC): - * http://msdn.microsoft.com/en-us/library/ms724284(VS.85).aspx - * To convert it into a float representing the seconds that the - * process has executed in user/kernel mode I borrowed the code - * below from Python's Modules/posixmodule.c - */ - py_tuple = Py_BuildValue( - "kdd", - te32.th32ThreadID, - (double)(ftUser.dwHighDateTime * 429.4967296 + \ - ftUser.dwLowDateTime * 1e-7), - (double)(ftKernel.dwHighDateTime * 429.4967296 + \ - ftKernel.dwLowDateTime * 1e-7)); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_tuple); - - CloseHandle(hThread); - } - } while (Thread32Next(hThreadSnap, &te32)); - - CloseHandle(hThreadSnap); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (hThread != NULL) - CloseHandle(hThread); - if (hThreadSnap != NULL) - CloseHandle(hThreadSnap); - return NULL; -} - - -static PyObject * -psutil_proc_open_files(PyObject *self, PyObject *args) { - long pid; - HANDLE processHandle; - DWORD access = PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION; - PyObject *py_retlist; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - processHandle = psutil_handle_from_pid(pid, access); - if (processHandle == NULL) - return NULL; - - py_retlist = psutil_get_open_files(pid, processHandle); - if (py_retlist == NULL) { - PyErr_SetFromWindowsErr(0); - CloseHandle(processHandle); - return NULL; - } - - CloseHandle(processHandle); - return py_retlist; -} - - -/* - Accept a filename's drive in native format like "\Device\HarddiskVolume1\" - and return the corresponding drive letter (e.g. "C:\\"). - If no match is found return an empty string. -*/ -static PyObject * -psutil_win32_QueryDosDevice(PyObject *self, PyObject *args) { - LPCTSTR lpDevicePath; - TCHAR d = TEXT('A'); - TCHAR szBuff[5]; - - if (!PyArg_ParseTuple(args, "s", &lpDevicePath)) - return NULL; - - while (d <= TEXT('Z')) { - TCHAR szDeviceName[3] = {d, TEXT(':'), TEXT('\0')}; - TCHAR szTarget[512] = {0}; - if (QueryDosDevice(szDeviceName, szTarget, 511) != 0) { - if (_tcscmp(lpDevicePath, szTarget) == 0) { - _stprintf_s(szBuff, _countof(szBuff), TEXT("%c:"), d); - return Py_BuildValue("s", szBuff); - } - } - d++; - } - return Py_BuildValue("s", ""); -} - - -/* - * Return process username as a "DOMAIN//USERNAME" string. - */ -static PyObject * -psutil_proc_username(PyObject *self, PyObject *args) { - long pid; - HANDLE processHandle = NULL; - HANDLE tokenHandle = NULL; - PTOKEN_USER user = NULL; - ULONG bufferSize; - WCHAR *name = NULL; - WCHAR *domainName = NULL; - ULONG nameSize; - ULONG domainNameSize; - SID_NAME_USE nameUse; - PyObject *py_username = NULL; - PyObject *py_domain = NULL; - PyObject *py_tuple = NULL; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - processHandle = psutil_handle_from_pid( - pid, PROCESS_QUERY_LIMITED_INFORMATION); - if (processHandle == NULL) - return NULL; - - if (!OpenProcessToken(processHandle, TOKEN_QUERY, &tokenHandle)) { - PyErr_SetFromOSErrnoWithSyscall("OpenProcessToken"); - goto error; - } - - CloseHandle(processHandle); - processHandle = NULL; - - // Get the user SID. - bufferSize = 0x100; - while (1) { - user = malloc(bufferSize); - if (user == NULL) { - PyErr_NoMemory(); - goto error; - } - if (!GetTokenInformation(tokenHandle, TokenUser, user, bufferSize, - &bufferSize)) - { - if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - free(user); - continue; - } - else { - PyErr_SetFromOSErrnoWithSyscall("GetTokenInformation"); - goto error; - } - } - break; - } - - CloseHandle(tokenHandle); - tokenHandle = NULL; - - // resolve the SID to a name - nameSize = 0x100; - domainNameSize = 0x100; - while (1) { - name = malloc(nameSize * sizeof(WCHAR)); - if (name == NULL) { - PyErr_NoMemory(); - goto error; - } - domainName = malloc(domainNameSize * sizeof(WCHAR)); - if (domainName == NULL) { - PyErr_NoMemory(); - goto error; - } - if (!LookupAccountSidW(NULL, user->User.Sid, name, &nameSize, - domainName, &domainNameSize, &nameUse)) - { - if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - free(name); - free(domainName); - continue; - } - else { - PyErr_SetFromOSErrnoWithSyscall("LookupAccountSidW"); - goto error; - } - } - break; - } - - py_domain = PyUnicode_FromWideChar(domainName, wcslen(domainName)); - if (! py_domain) - goto error; - py_username = PyUnicode_FromWideChar(name, wcslen(name)); - if (! py_username) - goto error; - py_tuple = Py_BuildValue("OO", py_domain, py_username); - if (! py_tuple) - goto error; - Py_DECREF(py_domain); - Py_DECREF(py_username); - - free(name); - free(domainName); - free(user); - - return py_tuple; - -error: - if (processHandle != NULL) - CloseHandle(processHandle); - if (tokenHandle != NULL) - CloseHandle(tokenHandle); - if (name != NULL) - free(name); - if (domainName != NULL) - free(domainName); - if (user != NULL) - free(user); - Py_XDECREF(py_domain); - Py_XDECREF(py_username); - Py_XDECREF(py_tuple); - return NULL; -} - - -// https://msdn.microsoft.com/library/aa365928.aspx -// TODO properly handle return code -static DWORD __GetExtendedTcpTable(_GetExtendedTcpTable call, - ULONG address_family, - PVOID * data, DWORD * size) -{ - // Due to other processes being active on the machine, it's possible - // that the size of the table increases between the moment where we - // query the size and the moment where we query the data. Therefore, it's - // important to call this in a loop to retry if that happens. - // See https://github.com/giampaolo/psutil/pull/1335 concerning 0xC0000001 error - // and https://github.com/giampaolo/psutil/issues/1294 - DWORD error = ERROR_INSUFFICIENT_BUFFER; - *size = 0; - *data = NULL; - error = call(NULL, size, FALSE, address_family, - TCP_TABLE_OWNER_PID_ALL, 0); - while (error == ERROR_INSUFFICIENT_BUFFER || error == 0xC0000001) - { - *data = malloc(*size); - if (*data == NULL) { - error = ERROR_NOT_ENOUGH_MEMORY; - continue; - } - error = call(*data, size, FALSE, address_family, - TCP_TABLE_OWNER_PID_ALL, 0); - if (error != NO_ERROR) { - free(*data); - *data = NULL; - } - } - return error; -} - - -// https://msdn.microsoft.com/library/aa365930.aspx -// TODO properly check return value -static DWORD __GetExtendedUdpTable(_GetExtendedUdpTable call, - ULONG address_family, - PVOID * data, DWORD * size) -{ - // Due to other processes being active on the machine, it's possible - // that the size of the table increases between the moment where we - // query the size and the moment where we query the data. Therefore, it's - // important to call this in a loop to retry if that happens. - // See https://github.com/giampaolo/psutil/pull/1335 concerning 0xC0000001 error - // and https://github.com/giampaolo/psutil/issues/1294 - DWORD error = ERROR_INSUFFICIENT_BUFFER; - *size = 0; - *data = NULL; - error = call(NULL, size, FALSE, address_family, - UDP_TABLE_OWNER_PID, 0); - while (error == ERROR_INSUFFICIENT_BUFFER || error == 0xC0000001) - { - *data = malloc(*size); - if (*data == NULL) { - error = ERROR_NOT_ENOUGH_MEMORY; - continue; - } - error = call(*data, size, FALSE, address_family, - UDP_TABLE_OWNER_PID, 0); - if (error != NO_ERROR) { - free(*data); - *data = NULL; - } - } - - if (error == ERROR_NOT_ENOUGH_MEMORY) { - PyErr_NoMemory(); - return 1; - } - if (error != NO_ERROR) { - PyErr_SetFromWindowsErr(error); - return 1; - } - return 0; -} - - -#define psutil_conn_decref_objs() \ - Py_DECREF(_AF_INET); \ - Py_DECREF(_AF_INET6);\ - Py_DECREF(_SOCK_STREAM);\ - Py_DECREF(_SOCK_DGRAM); - - -/* - * Return a list of network connections opened by a process - */ -static PyObject * -psutil_net_connections(PyObject *self, PyObject *args) { - static long null_address[4] = { 0, 0, 0, 0 }; - unsigned long pid; - int pid_return; - PVOID table = NULL; - DWORD tableSize; - DWORD error; - PMIB_TCPTABLE_OWNER_PID tcp4Table; - PMIB_UDPTABLE_OWNER_PID udp4Table; - PMIB_TCP6TABLE_OWNER_PID tcp6Table; - PMIB_UDP6TABLE_OWNER_PID udp6Table; - ULONG i; - CHAR addressBufferLocal[65]; - CHAR addressBufferRemote[65]; - - PyObject *py_retlist; - PyObject *py_conn_tuple = NULL; - PyObject *py_af_filter = NULL; - PyObject *py_type_filter = NULL; - PyObject *py_addr_tuple_local = NULL; - PyObject *py_addr_tuple_remote = NULL; - PyObject *_AF_INET = PyLong_FromLong((long)AF_INET); - PyObject *_AF_INET6 = PyLong_FromLong((long)AF_INET6); - PyObject *_SOCK_STREAM = PyLong_FromLong((long)SOCK_STREAM); - PyObject *_SOCK_DGRAM = PyLong_FromLong((long)SOCK_DGRAM); - - // Import some functions. - if (! PyArg_ParseTuple(args, "lOO", &pid, &py_af_filter, &py_type_filter)) - goto error; - - if (!PySequence_Check(py_af_filter) || !PySequence_Check(py_type_filter)) { - psutil_conn_decref_objs(); - PyErr_SetString(PyExc_TypeError, "arg 2 or 3 is not a sequence"); - return NULL; - } - - if (pid != -1) { - pid_return = psutil_pid_is_running(pid); - if (pid_return == 0) { - psutil_conn_decref_objs(); - return NoSuchProcess(""); - } - else if (pid_return == -1) { - psutil_conn_decref_objs(); - return NULL; - } - } - - py_retlist = PyList_New(0); - if (py_retlist == NULL) { - psutil_conn_decref_objs(); - return NULL; - } - - // TCP IPv4 - - if ((PySequence_Contains(py_af_filter, _AF_INET) == 1) && - (PySequence_Contains(py_type_filter, _SOCK_STREAM) == 1)) - { - table = NULL; - py_conn_tuple = NULL; - py_addr_tuple_local = NULL; - py_addr_tuple_remote = NULL; - tableSize = 0; - - error = __GetExtendedTcpTable(psutil_GetExtendedTcpTable, - AF_INET, &table, &tableSize); - if (error != 0) - goto error; - tcp4Table = table; - for (i = 0; i < tcp4Table->dwNumEntries; i++) { - if (pid != -1) { - if (tcp4Table->table[i].dwOwningPid != pid) { - continue; - } - } - - if (tcp4Table->table[i].dwLocalAddr != 0 || - tcp4Table->table[i].dwLocalPort != 0) - { - struct in_addr addr; - - addr.S_un.S_addr = tcp4Table->table[i].dwLocalAddr; - psutil_rtlIpv4AddressToStringA(&addr, addressBufferLocal); - py_addr_tuple_local = Py_BuildValue( - "(si)", - addressBufferLocal, - BYTESWAP_USHORT(tcp4Table->table[i].dwLocalPort)); - } - else { - py_addr_tuple_local = PyTuple_New(0); - } - - if (py_addr_tuple_local == NULL) - goto error; - - // On Windows <= XP, remote addr is filled even if socket - // is in LISTEN mode in which case we just ignore it. - if ((tcp4Table->table[i].dwRemoteAddr != 0 || - tcp4Table->table[i].dwRemotePort != 0) && - (tcp4Table->table[i].dwState != MIB_TCP_STATE_LISTEN)) - { - struct in_addr addr; - - addr.S_un.S_addr = tcp4Table->table[i].dwRemoteAddr; - psutil_rtlIpv4AddressToStringA(&addr, addressBufferRemote); - py_addr_tuple_remote = Py_BuildValue( - "(si)", - addressBufferRemote, - BYTESWAP_USHORT(tcp4Table->table[i].dwRemotePort)); - } - else - { - py_addr_tuple_remote = PyTuple_New(0); - } - - if (py_addr_tuple_remote == NULL) - goto error; - - py_conn_tuple = Py_BuildValue( - "(iiiNNiI)", - -1, - AF_INET, - SOCK_STREAM, - py_addr_tuple_local, - py_addr_tuple_remote, - tcp4Table->table[i].dwState, - tcp4Table->table[i].dwOwningPid); - if (!py_conn_tuple) - goto error; - if (PyList_Append(py_retlist, py_conn_tuple)) - goto error; - Py_CLEAR(py_conn_tuple); - } - - free(table); - table = NULL; - tableSize = 0; - } - - // TCP IPv6 - if ((PySequence_Contains(py_af_filter, _AF_INET6) == 1) && - (PySequence_Contains(py_type_filter, _SOCK_STREAM) == 1) && - (psutil_rtlIpv6AddressToStringA != NULL)) - { - table = NULL; - py_conn_tuple = NULL; - py_addr_tuple_local = NULL; - py_addr_tuple_remote = NULL; - tableSize = 0; - - error = __GetExtendedTcpTable(psutil_GetExtendedTcpTable, - AF_INET6, &table, &tableSize); - if (error != 0) - goto error; - tcp6Table = table; - for (i = 0; i < tcp6Table->dwNumEntries; i++) - { - if (pid != -1) { - if (tcp6Table->table[i].dwOwningPid != pid) { - continue; - } - } - - if (memcmp(tcp6Table->table[i].ucLocalAddr, null_address, 16) - != 0 || tcp6Table->table[i].dwLocalPort != 0) - { - struct in6_addr addr; - - memcpy(&addr, tcp6Table->table[i].ucLocalAddr, 16); - psutil_rtlIpv6AddressToStringA(&addr, addressBufferLocal); - py_addr_tuple_local = Py_BuildValue( - "(si)", - addressBufferLocal, - BYTESWAP_USHORT(tcp6Table->table[i].dwLocalPort)); - } - else { - py_addr_tuple_local = PyTuple_New(0); - } - - if (py_addr_tuple_local == NULL) - goto error; - - // On Windows <= XP, remote addr is filled even if socket - // is in LISTEN mode in which case we just ignore it. - if ((memcmp(tcp6Table->table[i].ucRemoteAddr, null_address, 16) - != 0 || - tcp6Table->table[i].dwRemotePort != 0) && - (tcp6Table->table[i].dwState != MIB_TCP_STATE_LISTEN)) - { - struct in6_addr addr; - - memcpy(&addr, tcp6Table->table[i].ucRemoteAddr, 16); - psutil_rtlIpv6AddressToStringA(&addr, addressBufferRemote); - py_addr_tuple_remote = Py_BuildValue( - "(si)", - addressBufferRemote, - BYTESWAP_USHORT(tcp6Table->table[i].dwRemotePort)); - } - else { - py_addr_tuple_remote = PyTuple_New(0); - } - - if (py_addr_tuple_remote == NULL) - goto error; - - py_conn_tuple = Py_BuildValue( - "(iiiNNiI)", - -1, - AF_INET6, - SOCK_STREAM, - py_addr_tuple_local, - py_addr_tuple_remote, - tcp6Table->table[i].dwState, - tcp6Table->table[i].dwOwningPid); - if (!py_conn_tuple) - goto error; - if (PyList_Append(py_retlist, py_conn_tuple)) - goto error; - Py_CLEAR(py_conn_tuple); - } - - free(table); - table = NULL; - tableSize = 0; - } - - // UDP IPv4 - - if ((PySequence_Contains(py_af_filter, _AF_INET) == 1) && - (PySequence_Contains(py_type_filter, _SOCK_DGRAM) == 1)) - { - table = NULL; - py_conn_tuple = NULL; - py_addr_tuple_local = NULL; - py_addr_tuple_remote = NULL; - tableSize = 0; - error = __GetExtendedUdpTable(psutil_GetExtendedUdpTable, - AF_INET, &table, &tableSize); - if (error != 0) - goto error; - udp4Table = table; - for (i = 0; i < udp4Table->dwNumEntries; i++) - { - if (pid != -1) { - if (udp4Table->table[i].dwOwningPid != pid) { - continue; - } - } - - if (udp4Table->table[i].dwLocalAddr != 0 || - udp4Table->table[i].dwLocalPort != 0) - { - struct in_addr addr; - - addr.S_un.S_addr = udp4Table->table[i].dwLocalAddr; - psutil_rtlIpv4AddressToStringA(&addr, addressBufferLocal); - py_addr_tuple_local = Py_BuildValue( - "(si)", - addressBufferLocal, - BYTESWAP_USHORT(udp4Table->table[i].dwLocalPort)); - } - else { - py_addr_tuple_local = PyTuple_New(0); - } - - if (py_addr_tuple_local == NULL) - goto error; - - py_conn_tuple = Py_BuildValue( - "(iiiNNiI)", - -1, - AF_INET, - SOCK_DGRAM, - py_addr_tuple_local, - PyTuple_New(0), - PSUTIL_CONN_NONE, - udp4Table->table[i].dwOwningPid); - if (!py_conn_tuple) - goto error; - if (PyList_Append(py_retlist, py_conn_tuple)) - goto error; - Py_CLEAR(py_conn_tuple); - } - - free(table); - table = NULL; - tableSize = 0; - } - - // UDP IPv6 - - if ((PySequence_Contains(py_af_filter, _AF_INET6) == 1) && - (PySequence_Contains(py_type_filter, _SOCK_DGRAM) == 1) && - (psutil_rtlIpv6AddressToStringA != NULL)) - { - table = NULL; - py_conn_tuple = NULL; - py_addr_tuple_local = NULL; - py_addr_tuple_remote = NULL; - tableSize = 0; - error = __GetExtendedUdpTable(psutil_GetExtendedUdpTable, - AF_INET6, &table, &tableSize); - if (error != 0) - goto error; - udp6Table = table; - for (i = 0; i < udp6Table->dwNumEntries; i++) { - if (pid != -1) { - if (udp6Table->table[i].dwOwningPid != pid) { - continue; - } - } - - if (memcmp(udp6Table->table[i].ucLocalAddr, null_address, 16) - != 0 || udp6Table->table[i].dwLocalPort != 0) - { - struct in6_addr addr; - - memcpy(&addr, udp6Table->table[i].ucLocalAddr, 16); - psutil_rtlIpv6AddressToStringA(&addr, addressBufferLocal); - py_addr_tuple_local = Py_BuildValue( - "(si)", - addressBufferLocal, - BYTESWAP_USHORT(udp6Table->table[i].dwLocalPort)); - } - else { - py_addr_tuple_local = PyTuple_New(0); - } - - if (py_addr_tuple_local == NULL) - goto error; - - py_conn_tuple = Py_BuildValue( - "(iiiNNiI)", - -1, - AF_INET6, - SOCK_DGRAM, - py_addr_tuple_local, - PyTuple_New(0), - PSUTIL_CONN_NONE, - udp6Table->table[i].dwOwningPid); - if (!py_conn_tuple) - goto error; - if (PyList_Append(py_retlist, py_conn_tuple)) - goto error; - Py_CLEAR(py_conn_tuple); - } - - free(table); - table = NULL; - tableSize = 0; - } - - psutil_conn_decref_objs(); - return py_retlist; - -error: - psutil_conn_decref_objs(); - Py_XDECREF(py_conn_tuple); - Py_XDECREF(py_addr_tuple_local); - Py_XDECREF(py_addr_tuple_remote); - Py_DECREF(py_retlist); - if (table != NULL) - free(table); - return NULL; -} - - -/* - * Get process priority as a Python integer. - */ -static PyObject * -psutil_proc_priority_get(PyObject *self, PyObject *args) { - long pid; - DWORD priority; - HANDLE hProcess; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - hProcess = psutil_handle_from_pid(pid, PROCESS_QUERY_LIMITED_INFORMATION); - if (hProcess == NULL) - return NULL; - - priority = GetPriorityClass(hProcess); - if (priority == 0) { - PyErr_SetFromWindowsErr(0); - CloseHandle(hProcess); - return NULL; - } - CloseHandle(hProcess); - return Py_BuildValue("i", priority); -} - - -/* - * Set process priority. - */ -static PyObject * -psutil_proc_priority_set(PyObject *self, PyObject *args) { - long pid; - int priority; - int retval; - HANDLE hProcess; - DWORD access = PROCESS_QUERY_INFORMATION | PROCESS_SET_INFORMATION; - - if (! PyArg_ParseTuple(args, "li", &pid, &priority)) - return NULL; - hProcess = psutil_handle_from_pid(pid, access); - if (hProcess == NULL) - return NULL; - - retval = SetPriorityClass(hProcess, priority); - if (retval == 0) { - PyErr_SetFromWindowsErr(0); - CloseHandle(hProcess); - return NULL; - } - - CloseHandle(hProcess); - Py_RETURN_NONE; -} - - -#if (_WIN32_WINNT >= 0x0600) // Windows Vista -/* - * Get process IO priority as a Python integer. - */ -static PyObject * -psutil_proc_io_priority_get(PyObject *self, PyObject *args) { - long pid; - HANDLE hProcess; - DWORD IoPriority; - NTSTATUS status; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - hProcess = psutil_handle_from_pid(pid, PROCESS_QUERY_LIMITED_INFORMATION); - if (hProcess == NULL) - return NULL; - - status = psutil_NtQueryInformationProcess( - hProcess, - ProcessIoPriority, - &IoPriority, - sizeof(DWORD), - NULL - ); - - CloseHandle(hProcess); - if (! NT_SUCCESS(status)) - return psutil_SetFromNTStatusErr(status, "NtQueryInformationProcess"); - return Py_BuildValue("i", IoPriority); -} - - -/* - * Set process IO priority. - */ -static PyObject * -psutil_proc_io_priority_set(PyObject *self, PyObject *args) { - long pid; - DWORD prio; - HANDLE hProcess; - NTSTATUS status; - DWORD access = PROCESS_QUERY_INFORMATION | PROCESS_SET_INFORMATION; - - if (! PyArg_ParseTuple(args, "li", &pid, &prio)) - return NULL; - - hProcess = psutil_handle_from_pid(pid, access); - if (hProcess == NULL) - return NULL; - - status = psutil_NtSetInformationProcess( - hProcess, - ProcessIoPriority, - (PVOID)&prio, - sizeof(DWORD) - ); - - CloseHandle(hProcess); - if (! NT_SUCCESS(status)) - return psutil_SetFromNTStatusErr(status, "NtSetInformationProcess"); - Py_RETURN_NONE; -} -#endif - - -/* - * Return a Python tuple referencing process I/O counters. - */ -static PyObject * -psutil_proc_io_counters(PyObject *self, PyObject *args) { - DWORD pid; - HANDLE hProcess; - IO_COUNTERS IoCounters; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - hProcess = psutil_handle_from_pid(pid, PROCESS_QUERY_LIMITED_INFORMATION); - if (NULL == hProcess) - return NULL; - - if (! GetProcessIoCounters(hProcess, &IoCounters)) { - PyErr_SetFromWindowsErr(0); - CloseHandle(hProcess); - return NULL; - } - - CloseHandle(hProcess); - return Py_BuildValue("(KKKKKK)", - IoCounters.ReadOperationCount, - IoCounters.WriteOperationCount, - IoCounters.ReadTransferCount, - IoCounters.WriteTransferCount, - IoCounters.OtherOperationCount, - IoCounters.OtherTransferCount); -} - - -/* - * Return process CPU affinity as a bitmask - */ -static PyObject * -psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args) { - DWORD pid; - HANDLE hProcess; - DWORD_PTR proc_mask; - DWORD_PTR system_mask; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - hProcess = psutil_handle_from_pid(pid, PROCESS_QUERY_LIMITED_INFORMATION); - if (hProcess == NULL) { - return NULL; - } - if (GetProcessAffinityMask(hProcess, &proc_mask, &system_mask) == 0) { - PyErr_SetFromWindowsErr(0); - CloseHandle(hProcess); - return NULL; - } - - CloseHandle(hProcess); -#ifdef _WIN64 - return Py_BuildValue("K", (unsigned long long)proc_mask); -#else - return Py_BuildValue("k", (unsigned long)proc_mask); -#endif -} - - -/* - * Set process CPU affinity - */ -static PyObject * -psutil_proc_cpu_affinity_set(PyObject *self, PyObject *args) { - DWORD pid; - HANDLE hProcess; - DWORD access = PROCESS_QUERY_INFORMATION | PROCESS_SET_INFORMATION; - DWORD_PTR mask; - -#ifdef _WIN64 - if (! PyArg_ParseTuple(args, "lK", &pid, &mask)) -#else - if (! PyArg_ParseTuple(args, "lk", &pid, &mask)) -#endif - { - return NULL; - } - hProcess = psutil_handle_from_pid(pid, access); - if (hProcess == NULL) - return NULL; - - if (SetProcessAffinityMask(hProcess, mask) == 0) { - PyErr_SetFromWindowsErr(0); - CloseHandle(hProcess); - return NULL; - } - - CloseHandle(hProcess); - Py_RETURN_NONE; -} - - -/* - * Return True if all process threads are in waiting/suspended state. - */ -static PyObject * -psutil_proc_is_suspended(PyObject *self, PyObject *args) { - DWORD pid; - ULONG i; - PSYSTEM_PROCESS_INFORMATION process; - PVOID buffer; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (! psutil_get_proc_info(pid, &process, &buffer)) - return NULL; - for (i = 0; i < process->NumberOfThreads; i++) { - if (process->Threads[i].ThreadState != Waiting || - process->Threads[i].WaitReason != Suspended) - { - free(buffer); - Py_RETURN_FALSE; - } - } - free(buffer); - Py_RETURN_TRUE; -} - - -/* - * Return path's disk total and free as a Python tuple. - */ -static PyObject * -psutil_disk_usage(PyObject *self, PyObject *args) { - BOOL retval; - ULARGE_INTEGER _, total, free; - char *path; - - if (PyArg_ParseTuple(args, "u", &path)) { - Py_BEGIN_ALLOW_THREADS - retval = GetDiskFreeSpaceExW((LPCWSTR)path, &_, &total, &free); - Py_END_ALLOW_THREADS - goto return_; - } - - // on Python 2 we also want to accept plain strings other - // than Unicode -#if PY_MAJOR_VERSION <= 2 - PyErr_Clear(); // drop the argument parsing error - if (PyArg_ParseTuple(args, "s", &path)) { - Py_BEGIN_ALLOW_THREADS - retval = GetDiskFreeSpaceEx(path, &_, &total, &free); - Py_END_ALLOW_THREADS - goto return_; - } -#endif - - return NULL; - -return_: - if (retval == 0) - return PyErr_SetFromWindowsErrWithFilename(0, path); - else - return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart); -} - - -/* - * Return a Python list of named tuples with overall network I/O information - */ -static PyObject * -psutil_net_io_counters(PyObject *self, PyObject *args) { - DWORD dwRetVal = 0; - -#if (_WIN32_WINNT >= 0x0600) // Windows Vista and above - MIB_IF_ROW2 *pIfRow = NULL; -#else // Windows XP - MIB_IFROW *pIfRow = NULL; -#endif - - PIP_ADAPTER_ADDRESSES pAddresses = NULL; - PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL; - PyObject *py_retdict = PyDict_New(); - PyObject *py_nic_info = NULL; - PyObject *py_nic_name = NULL; - - if (py_retdict == NULL) - return NULL; - pAddresses = psutil_get_nic_addresses(); - if (pAddresses == NULL) - goto error; - pCurrAddresses = pAddresses; - - while (pCurrAddresses) { - py_nic_name = NULL; - py_nic_info = NULL; - -#if (_WIN32_WINNT >= 0x0600) // Windows Vista and above - pIfRow = (MIB_IF_ROW2 *) malloc(sizeof(MIB_IF_ROW2)); -#else // Windows XP - pIfRow = (MIB_IFROW *) malloc(sizeof(MIB_IFROW)); -#endif - - if (pIfRow == NULL) { - PyErr_NoMemory(); - goto error; - } - -#if (_WIN32_WINNT >= 0x0600) // Windows Vista and above - SecureZeroMemory((PVOID)pIfRow, sizeof(MIB_IF_ROW2)); - pIfRow->InterfaceIndex = pCurrAddresses->IfIndex; - dwRetVal = GetIfEntry2(pIfRow); -#else // Windows XP - pIfRow->dwIndex = pCurrAddresses->IfIndex; - dwRetVal = GetIfEntry(pIfRow); -#endif - - if (dwRetVal != NO_ERROR) { - PyErr_SetString(PyExc_RuntimeError, - "GetIfEntry() or GetIfEntry2() syscalls failed."); - goto error; - } - -#if (_WIN32_WINNT >= 0x0600) // Windows Vista and above - py_nic_info = Py_BuildValue("(KKKKKKKK)", - pIfRow->OutOctets, - pIfRow->InOctets, - (pIfRow->OutUcastPkts + pIfRow->OutNUcastPkts), - (pIfRow->InUcastPkts + pIfRow->InNUcastPkts), - pIfRow->InErrors, - pIfRow->OutErrors, - pIfRow->InDiscards, - pIfRow->OutDiscards); -#else // Windows XP - py_nic_info = Py_BuildValue("(kkkkkkkk)", - pIfRow->dwOutOctets, - pIfRow->dwInOctets, - (pIfRow->dwOutUcastPkts + pIfRow->dwOutNUcastPkts), - (pIfRow->dwInUcastPkts + pIfRow->dwInNUcastPkts), - pIfRow->dwInErrors, - pIfRow->dwOutErrors, - pIfRow->dwInDiscards, - pIfRow->dwOutDiscards); -#endif - - if (!py_nic_info) - goto error; - - py_nic_name = PyUnicode_FromWideChar( - pCurrAddresses->FriendlyName, - wcslen(pCurrAddresses->FriendlyName)); - - if (py_nic_name == NULL) - goto error; - if (PyDict_SetItem(py_retdict, py_nic_name, py_nic_info)) - goto error; - Py_CLEAR(py_nic_name); - Py_CLEAR(py_nic_info); - - free(pIfRow); - pCurrAddresses = pCurrAddresses->Next; - } - - free(pAddresses); - return py_retdict; - -error: - Py_XDECREF(py_nic_name); - Py_XDECREF(py_nic_info); - Py_DECREF(py_retdict); - if (pAddresses != NULL) - free(pAddresses); - if (pIfRow != NULL) - free(pIfRow); - return NULL; -} - - -/* - * Return a Python dict of tuples for disk I/O information. This may - * require running "diskperf -y" command first. - */ -static PyObject * -psutil_disk_io_counters(PyObject *self, PyObject *args) { - DISK_PERFORMANCE diskPerformance; - DWORD dwSize; - HANDLE hDevice = NULL; - char szDevice[MAX_PATH]; - char szDeviceDisplay[MAX_PATH]; - int devNum; - int i; - DWORD ioctrlSize; - BOOL ret; - PyObject *py_retdict = PyDict_New(); - PyObject *py_tuple = NULL; - - if (py_retdict == NULL) - return NULL; - // Apparently there's no way to figure out how many times we have - // to iterate in order to find valid drives. - // Let's assume 32, which is higher than 26, the number of letters - // in the alphabet (from A:\ to Z:\). - for (devNum = 0; devNum <= 32; ++devNum) { - py_tuple = NULL; - sprintf_s(szDevice, MAX_PATH, "\\\\.\\PhysicalDrive%d", devNum); - hDevice = CreateFile(szDevice, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, 0, NULL); - if (hDevice == INVALID_HANDLE_VALUE) - continue; - - // DeviceIoControl() sucks! - i = 0; - ioctrlSize = sizeof(diskPerformance); - while (1) { - i += 1; - ret = DeviceIoControl( - hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0, &diskPerformance, - ioctrlSize, &dwSize, NULL); - if (ret != 0) - break; // OK! - if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - // Retry with a bigger buffer (+ limit for retries). - if (i <= 1024) { - ioctrlSize *= 2; - continue; - } - } - else if (GetLastError() == ERROR_INVALID_FUNCTION) { - // This happens on AppVeyor: - // https://ci.appveyor.com/project/giampaolo/psutil/build/ - // 1364/job/ascpdi271b06jle3 - // Assume it means we're dealing with some exotic disk - // and go on. - psutil_debug("DeviceIoControl -> ERROR_INVALID_FUNCTION; " - "ignore PhysicalDrive%i", devNum); - goto next; - } - else if (GetLastError() == ERROR_NOT_SUPPORTED) { - // Again, let's assume we're dealing with some exotic disk. - psutil_debug("DeviceIoControl -> ERROR_NOT_SUPPORTED; " - "ignore PhysicalDrive%i", devNum); - goto next; - } - // XXX: it seems we should also catch ERROR_INVALID_PARAMETER: - // https://sites.ualberta.ca/dept/aict/uts/software/openbsd/ - // ports/4.1/i386/openafs/w-openafs-1.4.14-transarc/ - // openafs-1.4.14/src/usd/usd_nt.c - - // XXX: we can also bump into ERROR_MORE_DATA in which case - // (quoting doc) we're supposed to retry with a bigger buffer - // and specify a new "starting point", whatever it means. - PyErr_SetFromWindowsErr(0); - goto error; - } - - sprintf_s(szDeviceDisplay, MAX_PATH, "PhysicalDrive%i", devNum); - py_tuple = Py_BuildValue( - "(IILLKK)", - diskPerformance.ReadCount, - diskPerformance.WriteCount, - diskPerformance.BytesRead, - diskPerformance.BytesWritten, - // convert to ms: - // https://github.com/giampaolo/psutil/issues/1012 - (unsigned long long) - (diskPerformance.ReadTime.QuadPart) / 10000000, - (unsigned long long) - (diskPerformance.WriteTime.QuadPart) / 10000000); - if (!py_tuple) - goto error; - if (PyDict_SetItemString(py_retdict, szDeviceDisplay, py_tuple)) - goto error; - Py_CLEAR(py_tuple); - -next: - CloseHandle(hDevice); - } - - return py_retdict; - -error: - Py_XDECREF(py_tuple); - Py_DECREF(py_retdict); - if (hDevice != NULL) - CloseHandle(hDevice); - return NULL; -} - - -static char *psutil_get_drive_type(int type) { - switch (type) { - case DRIVE_FIXED: - return "fixed"; - case DRIVE_CDROM: - return "cdrom"; - case DRIVE_REMOVABLE: - return "removable"; - case DRIVE_UNKNOWN: - return "unknown"; - case DRIVE_NO_ROOT_DIR: - return "unmounted"; - case DRIVE_REMOTE: - return "remote"; - case DRIVE_RAMDISK: - return "ramdisk"; - default: - return "?"; - } -} - - -#ifndef _ARRAYSIZE -#define _ARRAYSIZE(a) (sizeof(a)/sizeof(a[0])) -#endif - - -/* - * Return disk partitions as a list of tuples such as - * (drive_letter, drive_letter, type, "") - */ -static PyObject * -psutil_disk_partitions(PyObject *self, PyObject *args) { - DWORD num_bytes; - char drive_strings[255]; - char *drive_letter = drive_strings; - char mp_buf[MAX_PATH]; - char mp_path[MAX_PATH]; - int all; - int type; - int ret; - unsigned int old_mode = 0; - char opts[20]; - HANDLE mp_h; - BOOL mp_flag= TRUE; - LPTSTR fs_type[MAX_PATH + 1] = { 0 }; - DWORD pflags = 0; - PyObject *py_all; - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - - if (py_retlist == NULL) { - return NULL; - } - - // avoid to visualize a message box in case something goes wrong - // see https://github.com/giampaolo/psutil/issues/264 - old_mode = SetErrorMode(SEM_FAILCRITICALERRORS); - - if (! PyArg_ParseTuple(args, "O", &py_all)) - goto error; - all = PyObject_IsTrue(py_all); - - Py_BEGIN_ALLOW_THREADS - num_bytes = GetLogicalDriveStrings(254, drive_letter); - Py_END_ALLOW_THREADS - - if (num_bytes == 0) { - PyErr_SetFromWindowsErr(0); - goto error; - } - - while (*drive_letter != 0) { - py_tuple = NULL; - opts[0] = 0; - fs_type[0] = 0; - - Py_BEGIN_ALLOW_THREADS - type = GetDriveType(drive_letter); - Py_END_ALLOW_THREADS - - // by default we only show hard drives and cd-roms - if (all == 0) { - if ((type == DRIVE_UNKNOWN) || - (type == DRIVE_NO_ROOT_DIR) || - (type == DRIVE_REMOTE) || - (type == DRIVE_RAMDISK)) { - goto next; - } - // floppy disk: skip it by default as it introduces a - // considerable slowdown. - if ((type == DRIVE_REMOVABLE) && - (strcmp(drive_letter, "A:\\") == 0)) { - goto next; - } - } - - ret = GetVolumeInformation( - (LPCTSTR)drive_letter, NULL, _ARRAYSIZE(drive_letter), - NULL, NULL, &pflags, (LPTSTR)fs_type, _ARRAYSIZE(fs_type)); - if (ret == 0) { - // We might get here in case of a floppy hard drive, in - // which case the error is (21, "device not ready"). - // Let's pretend it didn't happen as we already have - // the drive name and type ('removable'). - strcat_s(opts, _countof(opts), ""); - SetLastError(0); - } - else { - if (pflags & FILE_READ_ONLY_VOLUME) - strcat_s(opts, _countof(opts), "ro"); - else - strcat_s(opts, _countof(opts), "rw"); - if (pflags & FILE_VOLUME_IS_COMPRESSED) - strcat_s(opts, _countof(opts), ",compressed"); - - // Check for mount points on this volume and add/get info - // (checks first to know if we can even have mount points) - if (pflags & FILE_SUPPORTS_REPARSE_POINTS) { - - mp_h = FindFirstVolumeMountPoint(drive_letter, mp_buf, MAX_PATH); - if (mp_h != INVALID_HANDLE_VALUE) { - while (mp_flag) { - - // Append full mount path with drive letter - strcpy_s(mp_path, _countof(mp_path), drive_letter); - strcat_s(mp_path, _countof(mp_path), mp_buf); - - py_tuple = Py_BuildValue( - "(ssss)", - drive_letter, - mp_path, - fs_type, // Typically NTFS - opts); - - if (!py_tuple || PyList_Append(py_retlist, py_tuple) == -1) { - FindVolumeMountPointClose(mp_h); - goto error; - } - - Py_CLEAR(py_tuple); - - // Continue looking for more mount points - mp_flag = FindNextVolumeMountPoint(mp_h, mp_buf, MAX_PATH); - } - FindVolumeMountPointClose(mp_h); - } - - } - } - - if (strlen(opts) > 0) - strcat_s(opts, _countof(opts), ","); - strcat_s(opts, _countof(opts), psutil_get_drive_type(type)); - - py_tuple = Py_BuildValue( - "(ssss)", - drive_letter, - drive_letter, - fs_type, // either FAT, FAT32, NTFS, HPFS, CDFS, UDF or NWFS - opts); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_tuple); - goto next; - -next: - drive_letter = strchr(drive_letter, 0) + 1; - } - - SetErrorMode(old_mode); - return py_retlist; - -error: - SetErrorMode(old_mode); - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - return NULL; -} - -/* - * Return a Python dict of tuples for disk I/O information - */ -static PyObject * -psutil_users(PyObject *self, PyObject *args) { - HANDLE hServer = WTS_CURRENT_SERVER_HANDLE; - WCHAR *buffer_user = NULL; - LPTSTR buffer_addr = NULL; - PWTS_SESSION_INFO sessions = NULL; - DWORD count; - DWORD i; - DWORD sessionId; - DWORD bytes; - PWTS_CLIENT_ADDRESS address; - char address_str[50]; - long long unix_time; - WINSTATION_INFO station_info; - ULONG returnLen; - PyObject *py_tuple = NULL; - PyObject *py_address = NULL; - PyObject *py_username = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - - if (WTSEnumerateSessions(hServer, 0, 1, &sessions, &count) == 0) { - PyErr_SetFromOSErrnoWithSyscall("WTSEnumerateSessions"); - goto error; - } - - for (i = 0; i < count; i++) { - py_address = NULL; - py_tuple = NULL; - sessionId = sessions[i].SessionId; - if (buffer_user != NULL) - WTSFreeMemory(buffer_user); - if (buffer_addr != NULL) - WTSFreeMemory(buffer_addr); - - buffer_user = NULL; - buffer_addr = NULL; - - // username - bytes = 0; - if (WTSQuerySessionInformationW(hServer, sessionId, WTSUserName, - &buffer_user, &bytes) == 0) { - PyErr_SetFromOSErrnoWithSyscall("WTSQuerySessionInformationW"); - goto error; - } - if (bytes <= 2) - continue; - - // address - bytes = 0; - if (WTSQuerySessionInformation(hServer, sessionId, WTSClientAddress, - &buffer_addr, &bytes) == 0) { - PyErr_SetFromOSErrnoWithSyscall("WTSQuerySessionInformation"); - goto error; - } - - address = (PWTS_CLIENT_ADDRESS)buffer_addr; - if (address->AddressFamily == 0) { // AF_INET - sprintf_s(address_str, - _countof(address_str), - "%u.%u.%u.%u", - address->Address[0], - address->Address[1], - address->Address[2], - address->Address[3]); - py_address = Py_BuildValue("s", address_str); - if (!py_address) - goto error; - } - else { - py_address = Py_None; - } - - // login time - if (! psutil_WinStationQueryInformationW( - hServer, - sessionId, - WinStationInformation, - &station_info, - sizeof(station_info), - &returnLen)) - { - PyErr_SetFromOSErrnoWithSyscall("WinStationQueryInformationW"); - goto error; - } - - unix_time = ((LONGLONG)station_info.ConnectTime.dwHighDateTime) << 32; - unix_time += \ - station_info.ConnectTime.dwLowDateTime - 116444736000000000LL; - unix_time /= 10000000; - - py_username = PyUnicode_FromWideChar(buffer_user, wcslen(buffer_user)); - if (py_username == NULL) - goto error; - py_tuple = Py_BuildValue("OOd", - py_username, - py_address, - (double)unix_time); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_username); - Py_CLEAR(py_address); - Py_CLEAR(py_tuple); - } - - WTSFreeMemory(sessions); - WTSFreeMemory(buffer_user); - WTSFreeMemory(buffer_addr); - return py_retlist; - -error: - Py_XDECREF(py_username); - Py_XDECREF(py_tuple); - Py_XDECREF(py_address); - Py_DECREF(py_retlist); - - if (sessions != NULL) - WTSFreeMemory(sessions); - if (buffer_user != NULL) - WTSFreeMemory(buffer_user); - if (buffer_addr != NULL) - WTSFreeMemory(buffer_addr); - return NULL; -} - - -/* - * Return the number of handles opened by process. - */ -static PyObject * -psutil_proc_num_handles(PyObject *self, PyObject *args) { - DWORD pid; - HANDLE hProcess; - DWORD handleCount; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - hProcess = psutil_handle_from_pid(pid, PROCESS_QUERY_LIMITED_INFORMATION); - if (NULL == hProcess) - return NULL; - if (! GetProcessHandleCount(hProcess, &handleCount)) { - PyErr_SetFromWindowsErr(0); - CloseHandle(hProcess); - return NULL; - } - CloseHandle(hProcess); - return Py_BuildValue("k", handleCount); -} - - -/* - * Get various process information by using NtQuerySystemInformation. - * We use this as a fallback when faster functions fail with access - * denied. This is slower because it iterates over all processes. - * Returned tuple includes the following process info: - * - * - num_threads() - * - ctx_switches() - * - num_handles() (fallback) - * - cpu_times() (fallback) - * - create_time() (fallback) - * - io_counters() (fallback) - * - memory_info() (fallback) - */ -static PyObject * -psutil_proc_info(PyObject *self, PyObject *args) { - DWORD pid; - PSYSTEM_PROCESS_INFORMATION process; - PVOID buffer; - ULONG i; - ULONG ctx_switches = 0; - double user_time; - double kernel_time; - long long create_time; - SIZE_T mem_private; - PyObject *py_retlist; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (! psutil_get_proc_info(pid, &process, &buffer)) - return NULL; - - for (i = 0; i < process->NumberOfThreads; i++) - ctx_switches += process->Threads[i].ContextSwitches; - user_time = (double)process->UserTime.HighPart * HI_T + \ - (double)process->UserTime.LowPart * LO_T; - kernel_time = (double)process->KernelTime.HighPart * HI_T + \ - (double)process->KernelTime.LowPart * LO_T; - - // Convert the LARGE_INTEGER union to a Unix time. - // It's the best I could find by googling and borrowing code here - // and there. The time returned has a precision of 1 second. - if (0 == pid || 4 == pid) { - // the python module will translate this into BOOT_TIME later - create_time = 0; - } - else { - create_time = ((LONGLONG)process->CreateTime.HighPart) << 32; - create_time += process->CreateTime.LowPart - 116444736000000000LL; - create_time /= 10000000; - } - -#if (_WIN32_WINNT >= 0x0501) // Windows XP with SP2 - mem_private = process->PrivatePageCount; -#else - mem_private = 0; -#endif - - py_retlist = Py_BuildValue( -#if defined(_WIN64) - "kkdddiKKKKKK" "kKKKKKKKKK", -#else - "kkdddiKKKKKK" "kIIIIIIIII", -#endif - process->HandleCount, // num handles - ctx_switches, // num ctx switches - user_time, // cpu user time - kernel_time, // cpu kernel time - (double)create_time, // create time - (int)process->NumberOfThreads, // num threads - // IO counters - process->ReadOperationCount.QuadPart, // io rcount - process->WriteOperationCount.QuadPart, // io wcount - process->ReadTransferCount.QuadPart, // io rbytes - process->WriteTransferCount.QuadPart, // io wbytes - process->OtherOperationCount.QuadPart, // io others count - process->OtherTransferCount.QuadPart, // io others bytes - // memory - process->PageFaultCount, // num page faults - process->PeakWorkingSetSize, // peak wset - process->WorkingSetSize, // wset - process->QuotaPeakPagedPoolUsage, // peak paged pool - process->QuotaPagedPoolUsage, // paged pool - process->QuotaPeakNonPagedPoolUsage, // peak non paged pool - process->QuotaNonPagedPoolUsage, // non paged pool - process->PagefileUsage, // pagefile - process->PeakPagefileUsage, // peak pagefile - mem_private // private - ); - - free(buffer); - return py_retlist; -} - - -static char *get_region_protection_string(ULONG protection) { - switch (protection & 0xff) { - case PAGE_NOACCESS: - return ""; - case PAGE_READONLY: - return "r"; - case PAGE_READWRITE: - return "rw"; - case PAGE_WRITECOPY: - return "wc"; - case PAGE_EXECUTE: - return "x"; - case PAGE_EXECUTE_READ: - return "xr"; - case PAGE_EXECUTE_READWRITE: - return "xrw"; - case PAGE_EXECUTE_WRITECOPY: - return "xwc"; - default: - return "?"; - } -} - - -/* - * Return a list of process's memory mappings. - */ -static PyObject * -psutil_proc_memory_maps(PyObject *self, PyObject *args) { - MEMORY_BASIC_INFORMATION basicInfo; - DWORD pid; - HANDLE hProcess = NULL; - PVOID baseAddress; - ULONGLONG previousAllocationBase; - WCHAR mappedFileName[MAX_PATH]; - LPVOID maxAddr; - // required by GetMappedFileNameW - DWORD access = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ; - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - PyObject *py_str = NULL; - - if (py_retlist == NULL) - return NULL; - if (! PyArg_ParseTuple(args, "l", &pid)) - goto error; - hProcess = psutil_handle_from_pid(pid, access); - if (NULL == hProcess) - goto error; - - maxAddr = PSUTIL_SYSTEM_INFO.lpMaximumApplicationAddress; - baseAddress = NULL; - - while (VirtualQueryEx(hProcess, baseAddress, &basicInfo, - sizeof(MEMORY_BASIC_INFORMATION))) - { - py_tuple = NULL; - if (baseAddress > maxAddr) - break; - if (GetMappedFileNameW(hProcess, baseAddress, mappedFileName, - sizeof(mappedFileName))) - { - py_str = PyUnicode_FromWideChar(mappedFileName, - wcslen(mappedFileName)); - if (py_str == NULL) - goto error; -#ifdef _WIN64 - py_tuple = Py_BuildValue( - "(KsOI)", - (unsigned long long)baseAddress, -#else - py_tuple = Py_BuildValue( - "(ksOI)", - (unsigned long)baseAddress, -#endif - get_region_protection_string(basicInfo.Protect), - py_str, - basicInfo.RegionSize); - - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_tuple); - Py_CLEAR(py_str); - } - previousAllocationBase = (ULONGLONG)basicInfo.AllocationBase; - baseAddress = (PCHAR)baseAddress + basicInfo.RegionSize; - } - - CloseHandle(hProcess); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_XDECREF(py_str); - Py_DECREF(py_retlist); - if (hProcess != NULL) - CloseHandle(hProcess); - return NULL; -} - - -/* - * Return a {pid:ppid, ...} dict for all running processes. - */ -static PyObject * -psutil_ppid_map(PyObject *self, PyObject *args) { - PyObject *py_pid = NULL; - PyObject *py_ppid = NULL; - PyObject *py_retdict = PyDict_New(); - HANDLE handle = NULL; - PROCESSENTRY32 pe = {0}; - pe.dwSize = sizeof(PROCESSENTRY32); - - if (py_retdict == NULL) - return NULL; - handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - if (handle == INVALID_HANDLE_VALUE) { - PyErr_SetFromWindowsErr(0); - Py_DECREF(py_retdict); - return NULL; - } - - if (Process32First(handle, &pe)) { - do { - py_pid = Py_BuildValue("I", pe.th32ProcessID); - if (py_pid == NULL) - goto error; - py_ppid = Py_BuildValue("I", pe.th32ParentProcessID); - if (py_ppid == NULL) - goto error; - if (PyDict_SetItem(py_retdict, py_pid, py_ppid)) - goto error; - Py_CLEAR(py_pid); - Py_CLEAR(py_ppid); - } while (Process32Next(handle, &pe)); - } - - CloseHandle(handle); - return py_retdict; - -error: - Py_XDECREF(py_pid); - Py_XDECREF(py_ppid); - Py_DECREF(py_retdict); - CloseHandle(handle); - return NULL; -} - - -/* - * Return NICs addresses. - */ - -static PyObject * -psutil_net_if_addrs(PyObject *self, PyObject *args) { - unsigned int i = 0; - ULONG family; - PCTSTR intRet; - PCTSTR netmaskIntRet; - char *ptr; - char buff_addr[1024]; - char buff_macaddr[1024]; - char buff_netmask[1024]; - DWORD dwRetVal = 0; -#if (_WIN32_WINNT >= 0x0600) // Windows Vista and above - ULONG converted_netmask; - UINT netmask_bits; - struct in_addr in_netmask; -#endif - PIP_ADAPTER_ADDRESSES pAddresses = NULL; - PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL; - PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL; - - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - PyObject *py_address = NULL; - PyObject *py_mac_address = NULL; - PyObject *py_nic_name = NULL; - PyObject *py_netmask = NULL; - - if (py_retlist == NULL) - return NULL; - - pAddresses = psutil_get_nic_addresses(); - if (pAddresses == NULL) - goto error; - pCurrAddresses = pAddresses; - - while (pCurrAddresses) { - pUnicast = pCurrAddresses->FirstUnicastAddress; - - netmaskIntRet = NULL; - py_nic_name = NULL; - py_nic_name = PyUnicode_FromWideChar( - pCurrAddresses->FriendlyName, - wcslen(pCurrAddresses->FriendlyName)); - if (py_nic_name == NULL) - goto error; - - // MAC address - if (pCurrAddresses->PhysicalAddressLength != 0) { - ptr = buff_macaddr; - *ptr = '\0'; - for (i = 0; i < (int) pCurrAddresses->PhysicalAddressLength; i++) { - if (i == (pCurrAddresses->PhysicalAddressLength - 1)) { - sprintf_s(ptr, _countof(buff_macaddr), "%.2X\n", - (int)pCurrAddresses->PhysicalAddress[i]); - } - else { - sprintf_s(ptr, _countof(buff_macaddr), "%.2X-", - (int)pCurrAddresses->PhysicalAddress[i]); - } - ptr += 3; - } - *--ptr = '\0'; - - py_mac_address = Py_BuildValue("s", buff_macaddr); - if (py_mac_address == NULL) - goto error; - - Py_INCREF(Py_None); - Py_INCREF(Py_None); - Py_INCREF(Py_None); - py_tuple = Py_BuildValue( - "(OiOOOO)", - py_nic_name, - -1, // this will be converted later to AF_LINK - py_mac_address, - Py_None, // netmask (not supported) - Py_None, // broadcast (not supported) - Py_None // ptp (not supported on Windows) - ); - if (! py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_tuple); - Py_CLEAR(py_mac_address); - } - - // find out the IP address associated with the NIC - if (pUnicast != NULL) { - for (i = 0; pUnicast != NULL; i++) { - family = pUnicast->Address.lpSockaddr->sa_family; - if (family == AF_INET) { - struct sockaddr_in *sa_in = (struct sockaddr_in *) - pUnicast->Address.lpSockaddr; - intRet = inet_ntop(AF_INET, &(sa_in->sin_addr), buff_addr, - sizeof(buff_addr)); - if (!intRet) - goto error; -#if (_WIN32_WINNT >= 0x0600) // Windows Vista and above - netmask_bits = pUnicast->OnLinkPrefixLength; - dwRetVal = ConvertLengthToIpv4Mask(netmask_bits, &converted_netmask); - if (dwRetVal == NO_ERROR) { - in_netmask.s_addr = converted_netmask; - netmaskIntRet = inet_ntop( - AF_INET, &in_netmask, buff_netmask, - sizeof(buff_netmask)); - if (!netmaskIntRet) - goto error; - } -#endif - } - else if (family == AF_INET6) { - struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *) - pUnicast->Address.lpSockaddr; - intRet = inet_ntop(AF_INET6, &(sa_in6->sin6_addr), - buff_addr, sizeof(buff_addr)); - if (!intRet) - goto error; - } - else { - // we should never get here - pUnicast = pUnicast->Next; - continue; - } - -#if PY_MAJOR_VERSION >= 3 - py_address = PyUnicode_FromString(buff_addr); -#else - py_address = PyString_FromString(buff_addr); -#endif - if (py_address == NULL) - goto error; - - if (netmaskIntRet != NULL) { -#if PY_MAJOR_VERSION >= 3 - py_netmask = PyUnicode_FromString(buff_netmask); -#else - py_netmask = PyString_FromString(buff_netmask); -#endif - } else { - Py_INCREF(Py_None); - py_netmask = Py_None; - } - - Py_INCREF(Py_None); - Py_INCREF(Py_None); - py_tuple = Py_BuildValue( - "(OiOOOO)", - py_nic_name, - family, - py_address, - py_netmask, - Py_None, // broadcast (not supported) - Py_None // ptp (not supported on Windows) - ); - - if (! py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_tuple); - Py_CLEAR(py_address); - Py_CLEAR(py_netmask); - - pUnicast = pUnicast->Next; - } - } - Py_CLEAR(py_nic_name); - pCurrAddresses = pCurrAddresses->Next; - } - - free(pAddresses); - return py_retlist; - -error: - if (pAddresses) - free(pAddresses); - Py_DECREF(py_retlist); - Py_XDECREF(py_tuple); - Py_XDECREF(py_address); - Py_XDECREF(py_nic_name); - Py_XDECREF(py_netmask); - return NULL; -} - - -/* - * Provides stats about NIC interfaces installed on the system. - * TODO: get 'duplex' (currently it's hard coded to '2', aka - 'full duplex') - */ -static PyObject * -psutil_net_if_stats(PyObject *self, PyObject *args) { - int i; - DWORD dwSize = 0; - DWORD dwRetVal = 0; - MIB_IFTABLE *pIfTable; - MIB_IFROW *pIfRow; - PIP_ADAPTER_ADDRESSES pAddresses = NULL; - PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL; - char descr[MAX_PATH]; - int ifname_found; - - PyObject *py_nic_name = NULL; - PyObject *py_retdict = PyDict_New(); - PyObject *py_ifc_info = NULL; - PyObject *py_is_up = NULL; - - if (py_retdict == NULL) - return NULL; - - pAddresses = psutil_get_nic_addresses(); - if (pAddresses == NULL) - goto error; - - pIfTable = (MIB_IFTABLE *) malloc(sizeof (MIB_IFTABLE)); - if (pIfTable == NULL) { - PyErr_NoMemory(); - goto error; - } - dwSize = sizeof(MIB_IFTABLE); - if (GetIfTable(pIfTable, &dwSize, FALSE) == ERROR_INSUFFICIENT_BUFFER) { - free(pIfTable); - pIfTable = (MIB_IFTABLE *) malloc(dwSize); - if (pIfTable == NULL) { - PyErr_NoMemory(); - goto error; - } - } - // Make a second call to GetIfTable to get the actual - // data we want. - if ((dwRetVal = GetIfTable(pIfTable, &dwSize, FALSE)) != NO_ERROR) { - PyErr_SetString(PyExc_RuntimeError, "GetIfTable() syscall failed"); - goto error; - } - - for (i = 0; i < (int) pIfTable->dwNumEntries; i++) { - pIfRow = (MIB_IFROW *) & pIfTable->table[i]; - - // GetIfTable is not able to give us NIC with "friendly names" - // so we determine them via GetAdapterAddresses() which - // provides friendly names *and* descriptions and find the - // ones that match. - ifname_found = 0; - pCurrAddresses = pAddresses; - while (pCurrAddresses) { - sprintf_s(descr, MAX_PATH, "%wS", pCurrAddresses->Description); - if (lstrcmp(descr, pIfRow->bDescr) == 0) { - py_nic_name = PyUnicode_FromWideChar( - pCurrAddresses->FriendlyName, - wcslen(pCurrAddresses->FriendlyName)); - if (py_nic_name == NULL) - goto error; - ifname_found = 1; - break; - } - pCurrAddresses = pCurrAddresses->Next; - } - if (ifname_found == 0) { - // Name not found means GetAdapterAddresses() doesn't list - // this NIC, only GetIfTable, meaning it's not really a NIC - // interface so we skip it. - continue; - } - - // is up? - if((pIfRow->dwOperStatus == MIB_IF_OPER_STATUS_CONNECTED || - pIfRow->dwOperStatus == MIB_IF_OPER_STATUS_OPERATIONAL) && - pIfRow->dwAdminStatus == 1 ) { - py_is_up = Py_True; - } - else { - py_is_up = Py_False; - } - Py_INCREF(py_is_up); - - py_ifc_info = Py_BuildValue( - "(Oikk)", - py_is_up, - 2, // there's no way to know duplex so let's assume 'full' - pIfRow->dwSpeed / 1000000, // expressed in bytes, we want Mb - pIfRow->dwMtu - ); - if (!py_ifc_info) - goto error; - if (PyDict_SetItem(py_retdict, py_nic_name, py_ifc_info)) - goto error; - Py_CLEAR(py_nic_name); - Py_CLEAR(py_ifc_info); - } - - free(pIfTable); - free(pAddresses); - return py_retdict; - -error: - Py_XDECREF(py_is_up); - Py_XDECREF(py_ifc_info); - Py_XDECREF(py_nic_name); - Py_DECREF(py_retdict); - if (pIfTable != NULL) - free(pIfTable); - if (pAddresses != NULL) - free(pAddresses); - return NULL; -} - - -/* - * Return CPU statistics. - */ -static PyObject * -psutil_cpu_stats(PyObject *self, PyObject *args) { - NTSTATUS status; - _SYSTEM_PERFORMANCE_INFORMATION *spi = NULL; - _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *sppi = NULL; - _SYSTEM_INTERRUPT_INFORMATION *InterruptInformation = NULL; - unsigned int ncpus; - UINT i; - ULONG64 dpcs = 0; - ULONG interrupts = 0; - - // retrieves number of processors - ncpus = psutil_get_num_cpus(1); - if (ncpus == 0) - goto error; - - // get syscalls / ctx switches - spi = (_SYSTEM_PERFORMANCE_INFORMATION *) \ - malloc(ncpus * sizeof(_SYSTEM_PERFORMANCE_INFORMATION)); - if (spi == NULL) { - PyErr_NoMemory(); - goto error; - } - status = psutil_NtQuerySystemInformation( - SystemPerformanceInformation, - spi, - ncpus * sizeof(_SYSTEM_PERFORMANCE_INFORMATION), - NULL); - if (! NT_SUCCESS(status)) { - psutil_SetFromNTStatusErr( - status, "NtQuerySystemInformation(SystemPerformanceInformation)"); - goto error; - } - - // get DPCs - InterruptInformation = \ - malloc(sizeof(_SYSTEM_INTERRUPT_INFORMATION) * ncpus); - if (InterruptInformation == NULL) { - PyErr_NoMemory(); - goto error; - } - - status = psutil_NtQuerySystemInformation( - SystemInterruptInformation, - InterruptInformation, - ncpus * sizeof(SYSTEM_INTERRUPT_INFORMATION), - NULL); - if (! NT_SUCCESS(status)) { - psutil_SetFromNTStatusErr( - status, "NtQuerySystemInformation(SystemInterruptInformation)"); - goto error; - } - for (i = 0; i < ncpus; i++) { - dpcs += InterruptInformation[i].DpcCount; - } - - // get interrupts - sppi = (_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *) \ - malloc(ncpus * sizeof(_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)); - if (sppi == NULL) { - PyErr_NoMemory(); - goto error; - } - - status = psutil_NtQuerySystemInformation( - SystemProcessorPerformanceInformation, - sppi, - ncpus * sizeof(_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION), - NULL); - if (! NT_SUCCESS(status)) { - psutil_SetFromNTStatusErr( - status, - "NtQuerySystemInformation(SystemProcessorPerformanceInformation)"); - goto error; - } - - for (i = 0; i < ncpus; i++) { - interrupts += sppi[i].InterruptCount; - } - - // done - free(spi); - free(InterruptInformation); - free(sppi); - return Py_BuildValue( - "kkkk", - spi->ContextSwitches, - interrupts, - (unsigned long)dpcs, - spi->SystemCalls - ); - -error: - if (spi) - free(spi); - if (InterruptInformation) - free(InterruptInformation); - if (sppi) - free(sppi); - return NULL; -} - - -/* - * Return CPU frequency. - */ -static PyObject * -psutil_cpu_freq(PyObject *self, PyObject *args) { - PROCESSOR_POWER_INFORMATION *ppi; - NTSTATUS ret; - ULONG size; - LPBYTE pBuffer = NULL; - ULONG current; - ULONG max; - unsigned int ncpus; - - // Get the number of CPUs. - ncpus = psutil_get_num_cpus(1); - if (ncpus == 0) - return NULL; - - // Allocate size. - size = ncpus * sizeof(PROCESSOR_POWER_INFORMATION); - pBuffer = (BYTE*)LocalAlloc(LPTR, size); - if (! pBuffer) - return PyErr_SetFromWindowsErr(0); - - // Syscall. - ret = CallNtPowerInformation( - ProcessorInformation, NULL, 0, pBuffer, size); - if (ret != 0) { - PyErr_SetString(PyExc_RuntimeError, - "CallNtPowerInformation syscall failed"); - goto error; - } - - // Results. - ppi = (PROCESSOR_POWER_INFORMATION *)pBuffer; - max = ppi->MaxMhz; - current = ppi->CurrentMhz; - LocalFree(pBuffer); - - return Py_BuildValue("kk", current, max); - -error: - if (pBuffer != NULL) - LocalFree(pBuffer); - return NULL; -} - - -/* - * Return battery usage stats. - */ -static PyObject * -psutil_sensors_battery(PyObject *self, PyObject *args) { - SYSTEM_POWER_STATUS sps; - - if (GetSystemPowerStatus(&sps) == 0) - return PyErr_SetFromWindowsErr(0); - return Py_BuildValue( - "iiiI", - sps.ACLineStatus, // whether AC is connected: 0=no, 1=yes, 255=unknown - // status flag: - // 1, 2, 4 = high, low, critical - // 8 = charging - // 128 = no battery - sps.BatteryFlag, - sps.BatteryLifePercent, // percent - sps.BatteryLifeTime // remaining secs - ); -} - - -/* - * System memory page size as an int. - */ -static PyObject * -psutil_getpagesize(PyObject *self, PyObject *args) { - // XXX: we may want to use GetNativeSystemInfo to differentiate - // page size for WoW64 processes (but am not sure). - return Py_BuildValue("I", PSUTIL_SYSTEM_INFO.dwPageSize); -} - - -// ------------------------ Python init --------------------------- - -static PyMethodDef -PsutilMethods[] = { - // --- per-process functions - {"proc_cmdline", (PyCFunction)(void(*)(void))psutil_proc_cmdline, - METH_VARARGS | METH_KEYWORDS, - "Return process cmdline as a list of cmdline arguments"}, - {"proc_environ", psutil_proc_environ, METH_VARARGS, - "Return process environment data"}, - {"proc_exe", psutil_proc_exe, METH_VARARGS, - "Return path of the process executable"}, - {"proc_name", psutil_proc_name, METH_VARARGS, - "Return process name"}, - {"proc_kill", psutil_proc_kill, METH_VARARGS, - "Kill the process identified by the given PID"}, - {"proc_cpu_times", psutil_proc_cpu_times, METH_VARARGS, - "Return tuple of user/kern time for the given PID"}, - {"proc_create_time", psutil_proc_create_time, METH_VARARGS, - "Return a float indicating the process create time expressed in " - "seconds since the epoch"}, - {"proc_memory_info", psutil_proc_memory_info, METH_VARARGS, - "Return a tuple of process memory information"}, - {"proc_memory_uss", psutil_proc_memory_uss, METH_VARARGS, - "Return the USS of the process"}, - {"proc_cwd", psutil_proc_cwd, METH_VARARGS, - "Return process current working directory"}, - {"proc_suspend_or_resume", psutil_proc_suspend_or_resume, METH_VARARGS, - "Suspend or resume a process"}, - {"proc_open_files", psutil_proc_open_files, METH_VARARGS, - "Return files opened by process"}, - {"proc_username", psutil_proc_username, METH_VARARGS, - "Return the username of a process"}, - {"proc_threads", psutil_proc_threads, METH_VARARGS, - "Return process threads information as a list of tuple"}, - {"proc_wait", psutil_proc_wait, METH_VARARGS, - "Wait for process to terminate and return its exit code."}, - {"proc_priority_get", psutil_proc_priority_get, METH_VARARGS, - "Return process priority."}, - {"proc_priority_set", psutil_proc_priority_set, METH_VARARGS, - "Set process priority."}, -#if (_WIN32_WINNT >= 0x0600) // Windows Vista - {"proc_io_priority_get", psutil_proc_io_priority_get, METH_VARARGS, - "Return process IO priority."}, - {"proc_io_priority_set", psutil_proc_io_priority_set, METH_VARARGS, - "Set process IO priority."}, -#endif - {"proc_cpu_affinity_get", psutil_proc_cpu_affinity_get, METH_VARARGS, - "Return process CPU affinity as a bitmask."}, - {"proc_cpu_affinity_set", psutil_proc_cpu_affinity_set, METH_VARARGS, - "Set process CPU affinity."}, - {"proc_io_counters", psutil_proc_io_counters, METH_VARARGS, - "Get process I/O counters."}, - {"proc_is_suspended", psutil_proc_is_suspended, METH_VARARGS, - "Return True if one of the process threads is in a suspended state"}, - {"proc_num_handles", psutil_proc_num_handles, METH_VARARGS, - "Return the number of handles opened by process."}, - {"proc_memory_maps", psutil_proc_memory_maps, METH_VARARGS, - "Return a list of process's memory mappings"}, - - // --- alternative pinfo interface - {"proc_info", psutil_proc_info, METH_VARARGS, - "Various process information"}, - - // --- system-related functions - {"pids", psutil_pids, METH_VARARGS, - "Returns a list of PIDs currently running on the system"}, - {"ppid_map", psutil_ppid_map, METH_VARARGS, - "Return a {pid:ppid, ...} dict for all running processes"}, - {"pid_exists", psutil_pid_exists, METH_VARARGS, - "Determine if the process exists in the current process list."}, - {"cpu_count_logical", psutil_cpu_count_logical, METH_VARARGS, - "Returns the number of logical CPUs on the system"}, - {"cpu_count_phys", psutil_cpu_count_phys, METH_VARARGS, - "Returns the number of physical CPUs on the system"}, - {"boot_time", psutil_boot_time, METH_VARARGS, - "Return the system boot time expressed in seconds since the epoch."}, - {"virtual_mem", psutil_virtual_mem, METH_VARARGS, - "Return the total amount of physical memory, in bytes"}, - {"cpu_times", psutil_cpu_times, METH_VARARGS, - "Return system cpu times as a list"}, - {"per_cpu_times", psutil_per_cpu_times, METH_VARARGS, - "Return system per-cpu times as a list of tuples"}, - {"disk_usage", psutil_disk_usage, METH_VARARGS, - "Return path's disk total and free as a Python tuple."}, - {"net_io_counters", psutil_net_io_counters, METH_VARARGS, - "Return dict of tuples of networks I/O information."}, - {"disk_io_counters", psutil_disk_io_counters, METH_VARARGS, - "Return dict of tuples of disks I/O information."}, - {"users", psutil_users, METH_VARARGS, - "Return a list of currently connected users."}, - {"disk_partitions", psutil_disk_partitions, METH_VARARGS, - "Return disk partitions."}, - {"net_connections", psutil_net_connections, METH_VARARGS, - "Return system-wide connections"}, - {"net_if_addrs", psutil_net_if_addrs, METH_VARARGS, - "Return NICs addresses."}, - {"net_if_stats", psutil_net_if_stats, METH_VARARGS, - "Return NICs stats."}, - {"cpu_stats", psutil_cpu_stats, METH_VARARGS, - "Return NICs stats."}, - {"cpu_freq", psutil_cpu_freq, METH_VARARGS, - "Return CPU frequency."}, -#if (_WIN32_WINNT >= 0x0600) // Windows Vista - {"init_loadavg_counter", (PyCFunction)psutil_init_loadavg_counter, - METH_VARARGS, - "Initializes the emulated load average calculator."}, - {"getloadavg", (PyCFunction)psutil_get_loadavg, METH_VARARGS, - "Returns the emulated POSIX-like load average."}, -#endif - {"sensors_battery", psutil_sensors_battery, METH_VARARGS, - "Return battery metrics usage."}, - {"getpagesize", psutil_getpagesize, METH_VARARGS, - "Return system memory page size."}, - - // --- windows services - {"winservice_enumerate", psutil_winservice_enumerate, METH_VARARGS, - "List all services"}, - {"winservice_query_config", psutil_winservice_query_config, METH_VARARGS, - "Return service config"}, - {"winservice_query_status", psutil_winservice_query_status, METH_VARARGS, - "Return service config"}, - {"winservice_query_descr", psutil_winservice_query_descr, METH_VARARGS, - "Return the description of a service"}, - {"winservice_start", psutil_winservice_start, METH_VARARGS, - "Start a service"}, - {"winservice_stop", psutil_winservice_stop, METH_VARARGS, - "Stop a service"}, - - // --- windows API bindings - {"win32_QueryDosDevice", psutil_win32_QueryDosDevice, METH_VARARGS, - "QueryDosDevice binding"}, - - // --- others - {"set_testing", psutil_set_testing, METH_NOARGS, - "Set psutil in testing mode"}, - - {NULL, NULL, 0, NULL} -}; - - -struct module_state { - PyObject *error; -}; - -#if PY_MAJOR_VERSION >= 3 -#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) -#else -#define GETSTATE(m) (&_state) -static struct module_state _state; -#endif - -#if PY_MAJOR_VERSION >= 3 - -static int psutil_windows_traverse(PyObject *m, visitproc visit, void *arg) { - Py_VISIT(GETSTATE(m)->error); - return 0; -} - -static int psutil_windows_clear(PyObject *m) { - Py_CLEAR(GETSTATE(m)->error); - return 0; -} - -static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, - "psutil_windows", - NULL, - sizeof(struct module_state), - PsutilMethods, - NULL, - psutil_windows_traverse, - psutil_windows_clear, - NULL -}; - -#define INITERROR return NULL - -PyMODINIT_FUNC PyInit__psutil_windows(void) - -#else -#define INITERROR return -void init_psutil_windows(void) -#endif -{ - struct module_state *st = NULL; -#if PY_MAJOR_VERSION >= 3 - PyObject *module = PyModule_Create(&moduledef); -#else - PyObject *module = Py_InitModule("_psutil_windows", PsutilMethods); -#endif - if (module == NULL) - INITERROR; - - if (psutil_setup() != 0) - INITERROR; - if (psutil_load_globals() != 0) - INITERROR; - if (psutil_set_se_debug() != 0) - INITERROR; - - st = GETSTATE(module); - st->error = PyErr_NewException("_psutil_windows.Error", NULL, NULL); - if (st->error == NULL) { - Py_DECREF(module); - INITERROR; - } - - // Exceptions. - TimeoutExpired = PyErr_NewException( - "_psutil_windows.TimeoutExpired", NULL, NULL); - Py_INCREF(TimeoutExpired); - PyModule_AddObject(module, "TimeoutExpired", TimeoutExpired); - - TimeoutAbandoned = PyErr_NewException( - "_psutil_windows.TimeoutAbandoned", NULL, NULL); - Py_INCREF(TimeoutAbandoned); - PyModule_AddObject(module, "TimeoutAbandoned", TimeoutAbandoned); - - // version constant - PyModule_AddIntConstant(module, "version", PSUTIL_VERSION); - - // process status constants - // http://msdn.microsoft.com/en-us/library/ms683211(v=vs.85).aspx - PyModule_AddIntConstant( - module, "ABOVE_NORMAL_PRIORITY_CLASS", ABOVE_NORMAL_PRIORITY_CLASS); - PyModule_AddIntConstant( - module, "BELOW_NORMAL_PRIORITY_CLASS", BELOW_NORMAL_PRIORITY_CLASS); - PyModule_AddIntConstant( - module, "HIGH_PRIORITY_CLASS", HIGH_PRIORITY_CLASS); - PyModule_AddIntConstant( - module, "IDLE_PRIORITY_CLASS", IDLE_PRIORITY_CLASS); - PyModule_AddIntConstant( - module, "NORMAL_PRIORITY_CLASS", NORMAL_PRIORITY_CLASS); - PyModule_AddIntConstant( - module, "REALTIME_PRIORITY_CLASS", REALTIME_PRIORITY_CLASS); - - // connection status constants - // http://msdn.microsoft.com/en-us/library/cc669305.aspx - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_CLOSED", MIB_TCP_STATE_CLOSED); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_CLOSING", MIB_TCP_STATE_CLOSING); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_CLOSE_WAIT", MIB_TCP_STATE_CLOSE_WAIT); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_LISTEN", MIB_TCP_STATE_LISTEN); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_ESTAB", MIB_TCP_STATE_ESTAB); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_SYN_SENT", MIB_TCP_STATE_SYN_SENT); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_SYN_RCVD", MIB_TCP_STATE_SYN_RCVD); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_FIN_WAIT1", MIB_TCP_STATE_FIN_WAIT1); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_FIN_WAIT2", MIB_TCP_STATE_FIN_WAIT2); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_LAST_ACK", MIB_TCP_STATE_LAST_ACK); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_TIME_WAIT", MIB_TCP_STATE_TIME_WAIT); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_TIME_WAIT", MIB_TCP_STATE_TIME_WAIT); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_DELETE_TCB", MIB_TCP_STATE_DELETE_TCB); - PyModule_AddIntConstant( - module, "PSUTIL_CONN_NONE", PSUTIL_CONN_NONE); - - // service status constants - /* - PyModule_AddIntConstant( - module, "SERVICE_CONTINUE_PENDING", SERVICE_CONTINUE_PENDING); - PyModule_AddIntConstant( - module, "SERVICE_PAUSE_PENDING", SERVICE_PAUSE_PENDING); - PyModule_AddIntConstant( - module, "SERVICE_PAUSED", SERVICE_PAUSED); - PyModule_AddIntConstant( - module, "SERVICE_RUNNING", SERVICE_RUNNING); - PyModule_AddIntConstant( - module, "SERVICE_START_PENDING", SERVICE_START_PENDING); - PyModule_AddIntConstant( - module, "SERVICE_STOP_PENDING", SERVICE_STOP_PENDING); - PyModule_AddIntConstant( - module, "SERVICE_STOPPED", SERVICE_STOPPED); - */ - - // ...for internal use in _psutil_windows.py - PyModule_AddIntConstant( - module, "INFINITE", INFINITE); - PyModule_AddIntConstant( - module, "ERROR_ACCESS_DENIED", ERROR_ACCESS_DENIED); - PyModule_AddIntConstant( - module, "ERROR_INVALID_NAME", ERROR_INVALID_NAME); - PyModule_AddIntConstant( - module, "ERROR_SERVICE_DOES_NOT_EXIST", ERROR_SERVICE_DOES_NOT_EXIST); - PyModule_AddIntConstant( - module, "ERROR_PRIVILEGE_NOT_HELD", ERROR_PRIVILEGE_NOT_HELD); - PyModule_AddIntConstant( - module, "WINVER", PSUTIL_WINVER); - PyModule_AddIntConstant( - module, "WINDOWS_XP", PSUTIL_WINDOWS_XP); - PyModule_AddIntConstant( - module, "WINDOWS_SERVER_2003", PSUTIL_WINDOWS_SERVER_2003); - PyModule_AddIntConstant( - module, "WINDOWS_VISTA", PSUTIL_WINDOWS_VISTA); - PyModule_AddIntConstant( - module, "WINDOWS_7", PSUTIL_WINDOWS_7); - PyModule_AddIntConstant( - module, "WINDOWS_8", PSUTIL_WINDOWS_8); - PyModule_AddIntConstant( - module, "WINDOWS_8_1", PSUTIL_WINDOWS_8_1); - PyModule_AddIntConstant( - module, "WINDOWS_10", PSUTIL_WINDOWS_10); - -#if PY_MAJOR_VERSION >= 3 - return module; -#endif -} diff --git a/ddtrace/vendor/psutil/_pswindows.py b/ddtrace/vendor/psutil/_pswindows.py deleted file mode 100644 index 636b0af905c..00000000000 --- a/ddtrace/vendor/psutil/_pswindows.py +++ /dev/null @@ -1,1127 +0,0 @@ -# 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. - -"""Windows platform implementation.""" - -import contextlib -import errno -import functools -import os -import sys -import time -from collections import namedtuple - -from . import _common -try: - from . import _psutil_windows as cext -except ImportError as err: - if str(err).lower().startswith("dll load failed") and \ - sys.getwindowsversion()[0] < 6: - # We may get here if: - # 1) we are on an old Windows version - # 2) psutil was installed via pip + wheel - # See: https://github.com/giampaolo/psutil/issues/811 - # It must be noted that psutil can still (kind of) work - # on outdated systems if compiled / installed from sources, - # but if we get here it means this this was a wheel (or exe). - msg = "this Windows version is too old (< Windows Vista); " - msg += "psutil 3.4.2 is the latest version which supports Windows " - msg += "2000, XP and 2003 server" - raise RuntimeError(msg) - else: - raise - -from ._common import conn_tmap -from ._common import conn_to_ntuple -from ._common import ENCODING -from ._common import ENCODING_ERRS -from ._common import isfile_strict -from ._common import memoize -from ._common import memoize_when_activated -from ._common import parse_environ_block -from ._common import usage_percent -from ._compat import long -from ._compat import lru_cache -from ._compat import PY3 -from ._compat import unicode -from ._compat import xrange -from ._psutil_windows import ABOVE_NORMAL_PRIORITY_CLASS -from ._psutil_windows import BELOW_NORMAL_PRIORITY_CLASS -from ._psutil_windows import HIGH_PRIORITY_CLASS -from ._psutil_windows import IDLE_PRIORITY_CLASS -from ._psutil_windows import NORMAL_PRIORITY_CLASS -from ._psutil_windows import REALTIME_PRIORITY_CLASS - -if sys.version_info >= (3, 4): - import enum -else: - enum = None - -# process priority constants, import from __init__.py: -# http://msdn.microsoft.com/en-us/library/ms686219(v=vs.85).aspx -__extra__all__ = [ - "win_service_iter", "win_service_get", - # Process priority - "ABOVE_NORMAL_PRIORITY_CLASS", "BELOW_NORMAL_PRIORITY_CLASS", - "HIGH_PRIORITY_CLASS", "IDLE_PRIORITY_CLASS", "NORMAL_PRIORITY_CLASS", - "REALTIME_PRIORITY_CLASS", - # IO priority - "IOPRIO_VERYLOW", "IOPRIO_LOW", "IOPRIO_NORMAL", "IOPRIO_HIGH", - # others - "CONN_DELETE_TCB", "AF_LINK", -] - - -# ===================================================================== -# --- globals -# ===================================================================== - -CONN_DELETE_TCB = "DELETE_TCB" -HAS_PROC_IO_PRIORITY = hasattr(cext, "proc_io_priority_get") -HAS_GETLOADAVG = hasattr(cext, "getloadavg") -ERROR_PARTIAL_COPY = 299 - - -if enum is None: - AF_LINK = -1 -else: - AddressFamily = enum.IntEnum('AddressFamily', {'AF_LINK': -1}) - AF_LINK = AddressFamily.AF_LINK - -TCP_STATUSES = { - cext.MIB_TCP_STATE_ESTAB: _common.CONN_ESTABLISHED, - cext.MIB_TCP_STATE_SYN_SENT: _common.CONN_SYN_SENT, - cext.MIB_TCP_STATE_SYN_RCVD: _common.CONN_SYN_RECV, - cext.MIB_TCP_STATE_FIN_WAIT1: _common.CONN_FIN_WAIT1, - cext.MIB_TCP_STATE_FIN_WAIT2: _common.CONN_FIN_WAIT2, - cext.MIB_TCP_STATE_TIME_WAIT: _common.CONN_TIME_WAIT, - cext.MIB_TCP_STATE_CLOSED: _common.CONN_CLOSE, - cext.MIB_TCP_STATE_CLOSE_WAIT: _common.CONN_CLOSE_WAIT, - cext.MIB_TCP_STATE_LAST_ACK: _common.CONN_LAST_ACK, - cext.MIB_TCP_STATE_LISTEN: _common.CONN_LISTEN, - cext.MIB_TCP_STATE_CLOSING: _common.CONN_CLOSING, - cext.MIB_TCP_STATE_DELETE_TCB: CONN_DELETE_TCB, - cext.PSUTIL_CONN_NONE: _common.CONN_NONE, -} - -if enum is not None: - class Priority(enum.IntEnum): - ABOVE_NORMAL_PRIORITY_CLASS = ABOVE_NORMAL_PRIORITY_CLASS - BELOW_NORMAL_PRIORITY_CLASS = BELOW_NORMAL_PRIORITY_CLASS - HIGH_PRIORITY_CLASS = HIGH_PRIORITY_CLASS - IDLE_PRIORITY_CLASS = IDLE_PRIORITY_CLASS - NORMAL_PRIORITY_CLASS = NORMAL_PRIORITY_CLASS - REALTIME_PRIORITY_CLASS = REALTIME_PRIORITY_CLASS - - globals().update(Priority.__members__) - -if enum is None: - IOPRIO_VERYLOW = 0 - IOPRIO_LOW = 1 - IOPRIO_NORMAL = 2 - IOPRIO_HIGH = 3 -else: - class IOPriority(enum.IntEnum): - IOPRIO_VERYLOW = 0 - IOPRIO_LOW = 1 - IOPRIO_NORMAL = 2 - IOPRIO_HIGH = 3 - globals().update(IOPriority.__members__) - -pinfo_map = dict( - num_handles=0, - ctx_switches=1, - user_time=2, - kernel_time=3, - create_time=4, - num_threads=5, - io_rcount=6, - io_wcount=7, - io_rbytes=8, - io_wbytes=9, - io_count_others=10, - io_bytes_others=11, - num_page_faults=12, - peak_wset=13, - wset=14, - peak_paged_pool=15, - paged_pool=16, - peak_non_paged_pool=17, - non_paged_pool=18, - pagefile=19, - peak_pagefile=20, - mem_private=21, -) - -# These objects get set on "import psutil" from the __init__.py -# file, see: https://github.com/giampaolo/psutil/issues/1402 -NoSuchProcess = None -ZombieProcess = None -AccessDenied = None -TimeoutExpired = None - -# More values at: https://stackoverflow.com/a/20804735/376587 -WIN_10 = (10, 0) -WIN_8 = (6, 2) -WIN_7 = (6, 1) -WIN_SERVER_2008 = (6, 0) -WIN_VISTA = (6, 0) -WIN_SERVER_2003 = (5, 2) -WIN_XP = (5, 1) - - -@lru_cache() -def get_winver(): - """Usage: - >>> if get_winver() <= WIN_VISTA: - ... ... - """ - wv = sys.getwindowsversion() - return (wv.major, wv.minor) - - -IS_WIN_XP = get_winver() < WIN_VISTA - - -# ===================================================================== -# --- named tuples -# ===================================================================== - - -# psutil.cpu_times() -scputimes = namedtuple('scputimes', - ['user', 'system', 'idle', 'interrupt', 'dpc']) -# psutil.virtual_memory() -svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free']) -# psutil.Process.memory_info() -pmem = namedtuple( - 'pmem', ['rss', 'vms', - 'num_page_faults', 'peak_wset', 'wset', 'peak_paged_pool', - 'paged_pool', 'peak_nonpaged_pool', 'nonpaged_pool', - 'pagefile', 'peak_pagefile', 'private']) -# psutil.Process.memory_full_info() -pfullmem = namedtuple('pfullmem', pmem._fields + ('uss', )) -# psutil.Process.memory_maps(grouped=True) -pmmap_grouped = namedtuple('pmmap_grouped', ['path', 'rss']) -# psutil.Process.memory_maps(grouped=False) -pmmap_ext = namedtuple( - 'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields)) -# psutil.Process.io_counters() -pio = namedtuple('pio', ['read_count', 'write_count', - 'read_bytes', 'write_bytes', - 'other_count', 'other_bytes']) - - -# ===================================================================== -# --- utils -# ===================================================================== - - -@lru_cache(maxsize=512) -def convert_dos_path(s): - r"""Convert paths using native DOS format like: - "\Device\HarddiskVolume1\Windows\systemew\file.txt" - into: - "C:\Windows\systemew\file.txt" - """ - rawdrive = '\\'.join(s.split('\\')[:3]) - driveletter = cext.win32_QueryDosDevice(rawdrive) - return os.path.join(driveletter, s[len(rawdrive):]) - - -def py2_strencode(s): - """Encode a unicode string to a byte string by using the default fs - encoding + "replace" error handler. - """ - if PY3: - return s - else: - if isinstance(s, str): - return s - else: - return s.encode(ENCODING, ENCODING_ERRS) - - -@memoize -def getpagesize(): - return cext.getpagesize() - - -# ===================================================================== -# --- memory -# ===================================================================== - - -def virtual_memory(): - """System virtual memory as a namedtuple.""" - mem = cext.virtual_mem() - totphys, availphys, totpagef, availpagef, totvirt, freevirt = mem - # - total = totphys - avail = availphys - free = availphys - used = total - avail - percent = usage_percent((total - avail), total, round_=1) - return svmem(total, avail, percent, used, free) - - -def swap_memory(): - """Swap system memory as a (total, used, free, sin, sout) tuple.""" - mem = cext.virtual_mem() - total = mem[2] - free = mem[3] - used = total - free - percent = usage_percent(used, total, round_=1) - return _common.sswap(total, used, free, percent, 0, 0) - - -# ===================================================================== -# --- disk -# ===================================================================== - - -disk_io_counters = cext.disk_io_counters - - -def disk_usage(path): - """Return disk usage associated with path.""" - if PY3 and isinstance(path, bytes): - # XXX: do we want to use "strict"? Probably yes, in order - # to fail immediately. After all we are accepting input here... - path = path.decode(ENCODING, errors="strict") - total, free = cext.disk_usage(path) - used = total - free - percent = usage_percent(used, total, round_=1) - return _common.sdiskusage(total, used, free, percent) - - -def disk_partitions(all): - """Return disk partitions.""" - rawlist = cext.disk_partitions(all) - return [_common.sdiskpart(*x) for x in rawlist] - - -# ===================================================================== -# --- CPU -# ===================================================================== - - -def cpu_times(): - """Return system CPU times as a named tuple.""" - user, system, idle = cext.cpu_times() - # Internally, GetSystemTimes() is used, and it doesn't return - # interrupt and dpc times. cext.per_cpu_times() does, so we - # rely on it to get those only. - percpu_summed = scputimes(*[sum(n) for n in zip(*cext.per_cpu_times())]) - return scputimes(user, system, idle, - percpu_summed.interrupt, percpu_summed.dpc) - - -def per_cpu_times(): - """Return system per-CPU times as a list of named tuples.""" - ret = [] - for user, system, idle, interrupt, dpc in cext.per_cpu_times(): - item = scputimes(user, system, idle, interrupt, dpc) - 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 CPU cores in the system.""" - return cext.cpu_count_phys() - - -def cpu_stats(): - """Return CPU statistics.""" - ctx_switches, interrupts, dpcs, syscalls = cext.cpu_stats() - soft_interrupts = 0 - return _common.scpustats(ctx_switches, interrupts, soft_interrupts, - syscalls) - - -def cpu_freq(): - """Return CPU frequency. - On Windows per-cpu frequency is not supported. - """ - curr, max_ = cext.cpu_freq() - min_ = 0.0 - return [_common.scpufreq(float(curr), min_, float(max_))] - - -if HAS_GETLOADAVG: - _loadavg_inititialized = False - - def getloadavg(): - """Return the number of processes in the system run queue averaged - over the last 1, 5, and 15 minutes respectively as a tuple""" - global _loadavg_inititialized - - if not _loadavg_inititialized: - cext.init_loadavg_counter() - _loadavg_inititialized = True - - # Drop to 2 decimal points which is what Linux does - raw_loads = cext.getloadavg() - return tuple([round(load, 2) for load in raw_loads]) - - -# ===================================================================== -# --- network -# ===================================================================== - - -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). - """ - 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] - rawlist = cext.net_connections(_pid, families, types) - ret = set() - for item in rawlist: - fd, fam, type, laddr, raddr, status, pid = item - nt = conn_to_ntuple(fd, fam, type, laddr, raddr, status, TCP_STATUSES, - pid=pid if _pid == -1 else None) - ret.add(nt) - return list(ret) - - -def net_if_stats(): - """Get NIC stats (isup, duplex, speed, mtu).""" - ret = {} - rawdict = cext.net_if_stats() - for name, items in rawdict.items(): - if not PY3: - assert isinstance(name, unicode), type(name) - name = py2_strencode(name) - isup, duplex, speed, mtu = items - if hasattr(_common, 'NicDuplex'): - duplex = _common.NicDuplex(duplex) - ret[name] = _common.snicstats(isup, duplex, speed, mtu) - return ret - - -def net_io_counters(): - """Return network I/O statistics for every network interface - installed on the system as a dict of raw tuples. - """ - ret = cext.net_io_counters() - return dict([(py2_strencode(k), v) for k, v in ret.items()]) - - -def net_if_addrs(): - """Return the addresses associated to each NIC.""" - ret = [] - for items in cext.net_if_addrs(): - items = list(items) - items[0] = py2_strencode(items[0]) - ret.append(items) - return ret - - -# ===================================================================== -# --- sensors -# ===================================================================== - - -def sensors_battery(): - """Return battery information.""" - # For constants meaning see: - # https://msdn.microsoft.com/en-us/library/windows/desktop/ - # aa373232(v=vs.85).aspx - acline_status, flags, percent, secsleft = cext.sensors_battery() - power_plugged = acline_status == 1 - no_battery = bool(flags & 128) - charging = bool(flags & 8) - - if no_battery: - return None - if power_plugged or charging: - secsleft = _common.POWER_TIME_UNLIMITED - elif secsleft == -1: - secsleft = _common.POWER_TIME_UNKNOWN - - return _common.sbattery(percent, secsleft, power_plugged) - - -# ===================================================================== -# --- other system functions -# ===================================================================== - - -_last_btime = 0 - - -def boot_time(): - """The system boot time expressed in seconds since the epoch.""" - # This dirty hack is to adjust the precision of the returned - # value which may have a 1 second fluctuation, see: - # https://github.com/giampaolo/psutil/issues/1007 - global _last_btime - ret = float(cext.boot_time()) - if abs(ret - _last_btime) <= 1: - return _last_btime - else: - _last_btime = ret - return ret - - -def users(): - """Return currently connected users as a list of namedtuples.""" - retlist = [] - rawlist = cext.users() - for item in rawlist: - user, hostname, tstamp = item - user = py2_strencode(user) - nt = _common.suser(user, None, hostname, tstamp, None) - retlist.append(nt) - return retlist - - -# ===================================================================== -# --- Windows services -# ===================================================================== - - -def win_service_iter(): - """Yields a list of WindowsService instances.""" - for name, display_name in cext.winservice_enumerate(): - yield WindowsService(py2_strencode(name), py2_strencode(display_name)) - - -def win_service_get(name): - """Open a Windows service and return it as a WindowsService instance.""" - service = WindowsService(name, None) - service._display_name = service._query_config()['display_name'] - return service - - -class WindowsService(object): - """Represents an installed Windows service.""" - - def __init__(self, name, display_name): - self._name = name - self._display_name = display_name - - def __str__(self): - details = "(name=%r, display_name=%r)" % ( - self._name, self._display_name) - return "%s%s" % (self.__class__.__name__, details) - - def __repr__(self): - return "<%s at %s>" % (self.__str__(), id(self)) - - def __eq__(self, other): - # Test for equality with another WindosService object based - # on name. - if not isinstance(other, WindowsService): - return NotImplemented - return self._name == other._name - - def __ne__(self, other): - return not self == other - - def _query_config(self): - with self._wrap_exceptions(): - display_name, binpath, username, start_type = \ - cext.winservice_query_config(self._name) - # XXX - update _self.display_name? - return dict( - display_name=py2_strencode(display_name), - binpath=py2_strencode(binpath), - username=py2_strencode(username), - start_type=py2_strencode(start_type)) - - def _query_status(self): - with self._wrap_exceptions(): - status, pid = cext.winservice_query_status(self._name) - if pid == 0: - pid = None - return dict(status=status, pid=pid) - - @contextlib.contextmanager - def _wrap_exceptions(self): - """Ctx manager which translates bare OSError and WindowsError - exceptions into NoSuchProcess and AccessDenied. - """ - try: - yield - except OSError as err: - if is_permission_err(err): - raise AccessDenied( - pid=None, name=self._name, - msg="service %r is not querable (not enough privileges)" % - self._name) - elif err.winerror in (cext.ERROR_INVALID_NAME, - cext.ERROR_SERVICE_DOES_NOT_EXIST): - raise NoSuchProcess( - pid=None, name=self._name, - msg="service %r does not exist)" % self._name) - else: - raise - - # config query - - def name(self): - """The service name. This string is how a service is referenced - and can be passed to win_service_get() to get a new - WindowsService instance. - """ - return self._name - - def display_name(self): - """The service display name. The value is cached when this class - is instantiated. - """ - return self._display_name - - def binpath(self): - """The fully qualified path to the service binary/exe file as - a string, including command line arguments. - """ - return self._query_config()['binpath'] - - def username(self): - """The name of the user that owns this service.""" - return self._query_config()['username'] - - def start_type(self): - """A string which can either be "automatic", "manual" or - "disabled". - """ - return self._query_config()['start_type'] - - # status query - - def pid(self): - """The process PID, if any, else None. This can be passed - to Process class to control the service's process. - """ - return self._query_status()['pid'] - - def status(self): - """Service status as a string.""" - return self._query_status()['status'] - - def description(self): - """Service long description.""" - return py2_strencode(cext.winservice_query_descr(self.name())) - - # utils - - def as_dict(self): - """Utility method retrieving all the information above as a - dictionary. - """ - d = self._query_config() - d.update(self._query_status()) - d['name'] = self.name() - d['display_name'] = self.display_name() - d['description'] = self.description() - return d - - # actions - # XXX: the necessary C bindings for start() and stop() are - # implemented but for now I prefer not to expose them. - # I may change my mind in the future. Reasons: - # - they require Administrator privileges - # - can't implement a timeout for stop() (unless by using a thread, - # which sucks) - # - would require adding ServiceAlreadyStarted and - # ServiceAlreadyStopped exceptions, adding two new APIs. - # - we might also want to have modify(), which would basically mean - # rewriting win32serviceutil.ChangeServiceConfig, which involves a - # lot of stuff (and API constants which would pollute the API), see: - # http://pyxr.sourceforge.net/PyXR/c/python24/lib/site-packages/ - # win32/lib/win32serviceutil.py.html#0175 - # - psutil is typically about "read only" monitoring stuff; - # win_service_* APIs should only be used to retrieve a service and - # check whether it's running - - # def start(self, timeout=None): - # with self._wrap_exceptions(): - # cext.winservice_start(self.name()) - # if timeout: - # giveup_at = time.time() + timeout - # while True: - # if self.status() == "running": - # return - # else: - # if time.time() > giveup_at: - # raise TimeoutExpired(timeout) - # else: - # time.sleep(.1) - - # def stop(self): - # # Note: timeout is not implemented because it's just not - # # possible, see: - # # http://stackoverflow.com/questions/11973228/ - # with self._wrap_exceptions(): - # return cext.winservice_stop(self.name()) - - -# ===================================================================== -# --- processes -# ===================================================================== - - -pids = cext.pids -pid_exists = cext.pid_exists -ppid_map = cext.ppid_map # used internally by Process.children() - - -def is_permission_err(exc): - """Return True if this is a permission error.""" - assert isinstance(exc, OSError), exc - # On Python 2 OSError doesn't always have 'winerror'. Sometimes - # it does, in which case the original exception was WindowsError - # (which is a subclass of OSError). - return exc.errno in (errno.EPERM, errno.EACCES) or \ - getattr(exc, "winerror", -1) in (cext.ERROR_ACCESS_DENIED, - cext.ERROR_PRIVILEGE_NOT_HELD) - - -def convert_oserror(exc, pid=None, name=None): - """Convert OSError into NoSuchProcess or AccessDenied.""" - assert isinstance(exc, OSError), exc - if is_permission_err(exc): - return AccessDenied(pid=pid, name=name) - if exc.errno == errno.ESRCH: - return NoSuchProcess(pid=pid, name=name) - raise exc - - -def wrap_exceptions(fun): - """Decorator which converts OSError into NoSuchProcess or AccessDenied.""" - @functools.wraps(fun) - def wrapper(self, *args, **kwargs): - try: - return fun(self, *args, **kwargs) - except OSError as err: - raise convert_oserror(err, pid=self.pid, name=self._name) - return wrapper - - -def retry_error_partial_copy(fun): - """Workaround for https://github.com/giampaolo/psutil/issues/875. - See: https://stackoverflow.com/questions/4457745#4457745 - """ - @functools.wraps(fun) - def wrapper(self, *args, **kwargs): - delay = 0.0001 - times = 33 - for x in range(times): # retries for roughly 1 second - try: - return fun(self, *args, **kwargs) - except WindowsError as _: - err = _ - if err.winerror == ERROR_PARTIAL_COPY: - time.sleep(delay) - delay = min(delay * 2, 0.04) - continue - else: - raise - else: - msg = "%s retried %s times, converted to AccessDenied as it's " \ - "still returning %r" % (fun, times, err) - raise AccessDenied(pid=self.pid, name=self._name, msg=msg) - return wrapper - - -class Process(object): - """Wrapper class around underlying C implementation.""" - - __slots__ = ["pid", "_name", "_ppid", "_cache"] - - def __init__(self, pid): - self.pid = pid - self._name = None - self._ppid = None - - # --- oneshot() stuff - - def oneshot_enter(self): - self.oneshot_info.cache_activate(self) - - def oneshot_exit(self): - self.oneshot_info.cache_deactivate(self) - - @wrap_exceptions - @memoize_when_activated - def oneshot_info(self): - """Return multiple information about this process as a - raw tuple. - """ - ret = cext.proc_info(self.pid) - assert len(ret) == len(pinfo_map) - return ret - - @wrap_exceptions - def name(self): - """Return process name, which on Windows is always the final - part of the executable. - """ - # This is how PIDs 0 and 4 are always represented in taskmgr - # and process-hacker. - if self.pid == 0: - return "System Idle Process" - elif self.pid == 4: - return "System" - else: - try: - # Note: this will fail with AD for most PIDs owned - # by another user but it's faster. - return py2_strencode(os.path.basename(self.exe())) - except AccessDenied: - return py2_strencode(cext.proc_name(self.pid)) - - @wrap_exceptions - def exe(self): - # Dual implementation, see: - # https://github.com/giampaolo/psutil/pull/1413 - if not IS_WIN_XP: - exe = cext.proc_exe(self.pid) - else: - if self.pid in (0, 4): - # https://github.com/giampaolo/psutil/issues/414 - # https://github.com/giampaolo/psutil/issues/528 - raise AccessDenied(self.pid, self._name) - exe = cext.proc_exe(self.pid) - exe = convert_dos_path(exe) - return py2_strencode(exe) - - @wrap_exceptions - @retry_error_partial_copy - def cmdline(self): - if cext.WINVER >= cext.WINDOWS_8_1: - # PEB method detects cmdline changes but requires more - # privileges: https://github.com/giampaolo/psutil/pull/1398 - try: - ret = cext.proc_cmdline(self.pid, use_peb=True) - except OSError as err: - if is_permission_err(err): - ret = cext.proc_cmdline(self.pid, use_peb=False) - else: - raise - else: - ret = cext.proc_cmdline(self.pid, use_peb=True) - if PY3: - return ret - else: - return [py2_strencode(s) for s in ret] - - @wrap_exceptions - @retry_error_partial_copy - def environ(self): - ustr = cext.proc_environ(self.pid) - if ustr and not PY3: - assert isinstance(ustr, unicode), type(ustr) - return parse_environ_block(py2_strencode(ustr)) - - def ppid(self): - try: - return ppid_map()[self.pid] - except KeyError: - raise NoSuchProcess(self.pid, self._name) - - def _get_raw_meminfo(self): - try: - return cext.proc_memory_info(self.pid) - except OSError as err: - if is_permission_err(err): - # TODO: the C ext can probably be refactored in order - # to get this from cext.proc_info() - info = self.oneshot_info() - return ( - info[pinfo_map['num_page_faults']], - info[pinfo_map['peak_wset']], - info[pinfo_map['wset']], - info[pinfo_map['peak_paged_pool']], - info[pinfo_map['paged_pool']], - info[pinfo_map['peak_non_paged_pool']], - info[pinfo_map['non_paged_pool']], - info[pinfo_map['pagefile']], - info[pinfo_map['peak_pagefile']], - info[pinfo_map['mem_private']], - ) - raise - - @wrap_exceptions - def memory_info(self): - # on Windows RSS == WorkingSetSize and VSM == PagefileUsage. - # Underlying C function returns fields of PROCESS_MEMORY_COUNTERS - # struct. - t = self._get_raw_meminfo() - rss = t[2] # wset - vms = t[7] # pagefile - return pmem(*(rss, vms, ) + t) - - @wrap_exceptions - def memory_full_info(self): - basic_mem = self.memory_info() - uss = cext.proc_memory_uss(self.pid) - uss *= getpagesize() - return pfullmem(*basic_mem + (uss, )) - - def memory_maps(self): - try: - raw = cext.proc_memory_maps(self.pid) - except OSError as err: - # XXX - can't use wrap_exceptions decorator as we're - # returning a generator; probably needs refactoring. - raise convert_oserror(err, self.pid, self._name) - else: - for addr, perm, path, rss in raw: - path = convert_dos_path(path) - if not PY3: - assert isinstance(path, unicode), type(path) - path = py2_strencode(path) - addr = hex(addr) - yield (addr, perm, path, rss) - - @wrap_exceptions - def kill(self): - return cext.proc_kill(self.pid) - - @wrap_exceptions - def send_signal(self, sig): - os.kill(self.pid, sig) - - @wrap_exceptions - def wait(self, timeout=None): - if timeout is None: - cext_timeout = cext.INFINITE - else: - # WaitForSingleObject() expects time in milliseconds. - cext_timeout = int(timeout * 1000) - - timer = getattr(time, 'monotonic', time.time) - stop_at = timer() + timeout if timeout is not None else None - - try: - # Exit code is supposed to come from GetExitCodeProcess(). - # May also be None if OpenProcess() failed with - # ERROR_INVALID_PARAMETER, meaning PID is already gone. - exit_code = cext.proc_wait(self.pid, cext_timeout) - except cext.TimeoutExpired: - # WaitForSingleObject() returned WAIT_TIMEOUT. Just raise. - raise TimeoutExpired(timeout, self.pid, self._name) - except cext.TimeoutAbandoned: - # WaitForSingleObject() returned WAIT_ABANDONED, see: - # https://github.com/giampaolo/psutil/issues/1224 - # We'll just rely on the internal polling and return None - # when the PID disappears. Subprocess module does the same - # (return None): - # https://github.com/python/cpython/blob/ - # be50a7b627d0aa37e08fa8e2d5568891f19903ce/ - # Lib/subprocess.py#L1193-L1194 - exit_code = None - - # At this point WaitForSingleObject() returned WAIT_OBJECT_0, - # meaning the process is gone. Stupidly there are cases where - # its PID may still stick around so we do a further internal - # polling. - delay = 0.0001 - while True: - if not pid_exists(self.pid): - return exit_code - if stop_at and timer() >= stop_at: - raise TimeoutExpired(timeout, pid=self.pid, name=self._name) - time.sleep(delay) - delay = min(delay * 2, 0.04) # incremental delay - - @wrap_exceptions - def username(self): - if self.pid in (0, 4): - return 'NT AUTHORITY\\SYSTEM' - domain, user = cext.proc_username(self.pid) - return py2_strencode(domain) + '\\' + py2_strencode(user) - - @wrap_exceptions - def create_time(self): - # special case for kernel process PIDs; return system boot time - if self.pid in (0, 4): - return boot_time() - try: - return cext.proc_create_time(self.pid) - except OSError as err: - if is_permission_err(err): - return self.oneshot_info()[pinfo_map['create_time']] - raise - - @wrap_exceptions - def num_threads(self): - return self.oneshot_info()[pinfo_map['num_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) - return retlist - - @wrap_exceptions - def cpu_times(self): - try: - user, system = cext.proc_cpu_times(self.pid) - except OSError as err: - if not is_permission_err(err): - raise - info = self.oneshot_info() - user = info[pinfo_map['user_time']] - system = info[pinfo_map['kernel_time']] - # Children user/system times are not retrievable (set to 0). - return _common.pcputimes(user, system, 0.0, 0.0) - - @wrap_exceptions - def suspend(self): - cext.proc_suspend_or_resume(self.pid, True) - - @wrap_exceptions - def resume(self): - cext.proc_suspend_or_resume(self.pid, False) - - @wrap_exceptions - @retry_error_partial_copy - def cwd(self): - if self.pid in (0, 4): - raise AccessDenied(self.pid, self._name) - # return a normalized pathname since the native C function appends - # "\\" at the and of the path - path = cext.proc_cwd(self.pid) - return py2_strencode(os.path.normpath(path)) - - @wrap_exceptions - def open_files(self): - if self.pid in (0, 4): - return [] - ret = set() - # Filenames come in in native format like: - # "\Device\HarddiskVolume1\Windows\systemew\file.txt" - # Convert the first part in the corresponding drive letter - # (e.g. "C:\") by using Windows's QueryDosDevice() - raw_file_names = cext.proc_open_files(self.pid) - for _file in raw_file_names: - _file = convert_dos_path(_file) - if isfile_strict(_file): - if not PY3: - _file = py2_strencode(_file) - ntuple = _common.popenfile(_file, -1) - ret.add(ntuple) - return list(ret) - - @wrap_exceptions - def connections(self, kind='inet'): - return net_connections(kind, _pid=self.pid) - - @wrap_exceptions - def nice_get(self): - value = cext.proc_priority_get(self.pid) - if enum is not None: - value = Priority(value) - return value - - @wrap_exceptions - def nice_set(self, value): - return cext.proc_priority_set(self.pid, value) - - # available on Windows >= Vista - if HAS_PROC_IO_PRIORITY: - @wrap_exceptions - def ionice_get(self): - ret = cext.proc_io_priority_get(self.pid) - if enum is not None: - ret = IOPriority(ret) - return ret - - @wrap_exceptions - def ionice_set(self, ioclass, value): - if value: - raise TypeError("value argument not accepted on Windows") - if ioclass not in (IOPRIO_VERYLOW, IOPRIO_LOW, IOPRIO_NORMAL, - IOPRIO_HIGH): - raise ValueError("%s is not a valid priority" % ioclass) - cext.proc_io_priority_set(self.pid, ioclass) - - @wrap_exceptions - def io_counters(self): - try: - ret = cext.proc_io_counters(self.pid) - except OSError as err: - if not is_permission_err(err): - raise - info = self.oneshot_info() - ret = ( - info[pinfo_map['io_rcount']], - info[pinfo_map['io_wcount']], - info[pinfo_map['io_rbytes']], - info[pinfo_map['io_wbytes']], - info[pinfo_map['io_count_others']], - info[pinfo_map['io_bytes_others']], - ) - return pio(*ret) - - @wrap_exceptions - def status(self): - suspended = cext.proc_is_suspended(self.pid) - if suspended: - return _common.STATUS_STOPPED - else: - return _common.STATUS_RUNNING - - @wrap_exceptions - def cpu_affinity_get(self): - def from_bitmask(x): - return [i for i in xrange(64) if (1 << i) & x] - bitmask = cext.proc_cpu_affinity_get(self.pid) - return from_bitmask(bitmask) - - @wrap_exceptions - def cpu_affinity_set(self, value): - def to_bitmask(l): - if not l: - raise ValueError("invalid argument %r" % l) - out = 0 - for b in l: - out |= 2 ** b - return out - - # SetProcessAffinityMask() states that ERROR_INVALID_PARAMETER - # is returned for an invalid CPU but this seems not to be true, - # therefore we check CPUs validy beforehand. - allcpus = list(range(len(per_cpu_times()))) - for cpu in value: - if cpu not in allcpus: - if not isinstance(cpu, (int, long)): - raise TypeError( - "invalid CPU %r; an integer is required" % cpu) - else: - raise ValueError("invalid CPU %r" % cpu) - - bitmask = to_bitmask(value) - cext.proc_cpu_affinity_set(self.pid, bitmask) - - @wrap_exceptions - def num_handles(self): - try: - return cext.proc_num_handles(self.pid) - except OSError as err: - if is_permission_err(err): - return self.oneshot_info()[pinfo_map['num_handles']] - raise - - @wrap_exceptions - def num_ctx_switches(self): - ctx_switches = self.oneshot_info()[pinfo_map['ctx_switches']] - # only voluntary ctx switches are supported - return _common.pctxsw(ctx_switches, 0) diff --git a/ddtrace/vendor/psutil/arch/aix/common.c b/ddtrace/vendor/psutil/arch/aix/common.c deleted file mode 100644 index 6115a15db51..00000000000 --- a/ddtrace/vendor/psutil/arch/aix/common.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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. - */ - -#include -#include -#include -#include "common.h" - -/* psutil_kread() - read from kernel memory */ -int -psutil_kread( - int Kd, /* kernel memory file descriptor */ - KA_T addr, /* kernel memory address */ - char *buf, /* buffer to receive data */ - size_t len) { /* length to read */ - int br; - - if (lseek64(Kd, (off64_t)addr, L_SET) == (off64_t)-1) { - PyErr_SetFromErrno(PyExc_OSError); - return 1; - } - br = read(Kd, buf, len); - if (br == -1) { - PyErr_SetFromErrno(PyExc_OSError); - return 1; - } - if (br != len) { - PyErr_SetString(PyExc_RuntimeError, - "size mismatch when reading kernel memory fd"); - return 1; - } - return 0; -} - -struct procentry64 * -psutil_read_process_table(int * num) { - size_t msz; - pid32_t pid = 0; - struct procentry64 *processes = (struct procentry64 *)NULL; - struct procentry64 *p; - int Np = 0; /* number of processes allocated in 'processes' */ - int np = 0; /* number of processes read into 'processes' */ - int i; /* number of processes read in current iteration */ - - msz = (size_t)(PROCSIZE * PROCINFO_INCR); - processes = (struct procentry64 *)malloc(msz); - if (!processes) { - PyErr_NoMemory(); - return NULL; - } - Np = PROCINFO_INCR; - p = processes; - while ((i = getprocs64(p, PROCSIZE, (struct fdsinfo64 *)NULL, 0, &pid, - PROCINFO_INCR)) - == PROCINFO_INCR) { - np += PROCINFO_INCR; - if (np >= Np) { - msz = (size_t)(PROCSIZE * (Np + PROCINFO_INCR)); - processes = (struct procentry64 *)realloc((char *)processes, msz); - if (!processes) { - PyErr_NoMemory(); - return NULL; - } - Np += PROCINFO_INCR; - } - p = (struct procentry64 *)((char *)processes + (np * PROCSIZE)); - } - - /* add the number of processes read in the last iteration */ - if (i > 0) - np += i; - - *num = np; - return processes; -} \ No newline at end of file diff --git a/ddtrace/vendor/psutil/arch/aix/common.h b/ddtrace/vendor/psutil/arch/aix/common.h deleted file mode 100644 index b677d8c29ee..00000000000 --- a/ddtrace/vendor/psutil/arch/aix/common.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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. - */ - -#ifndef __PSUTIL_AIX_COMMON_H__ -#define __PSUTIL_AIX_COMMON_H__ - -#include - -#define PROCINFO_INCR (256) -#define PROCSIZE (sizeof(struct procentry64)) -#define FDSINFOSIZE (sizeof(struct fdsinfo64)) -#define KMEM "/dev/kmem" - -typedef u_longlong_t KA_T; - -/* psutil_kread() - read from kernel memory */ -int psutil_kread(int Kd, /* kernel memory file descriptor */ - KA_T addr, /* kernel memory address */ - char *buf, /* buffer to receive data */ - size_t len); /* length to read */ - -struct procentry64 * -psutil_read_process_table( - int * num /* out - number of processes read */ -); - -#endif /* __PSUTIL_AIX_COMMON_H__ */ diff --git a/ddtrace/vendor/psutil/arch/aix/ifaddrs.c b/ddtrace/vendor/psutil/arch/aix/ifaddrs.c deleted file mode 100644 index 1a819365ab8..00000000000 --- a/ddtrace/vendor/psutil/arch/aix/ifaddrs.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * 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. - */ - -/*! Based on code from - https://lists.samba.org/archive/samba-technical/2009-February/063079.html -!*/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ifaddrs.h" - -#define MAX(x,y) ((x)>(y)?(x):(y)) -#define SIZE(p) MAX((p).sa_len,sizeof(p)) - - -static struct sockaddr * -sa_dup(struct sockaddr *sa1) -{ - struct sockaddr *sa2; - size_t sz = sa1->sa_len; - sa2 = (struct sockaddr *) calloc(1, sz); - if (sa2 == NULL) - return NULL; - memcpy(sa2, sa1, sz); - return sa2; -} - - -void freeifaddrs(struct ifaddrs *ifp) -{ - if (NULL == ifp) return; - free(ifp->ifa_name); - free(ifp->ifa_addr); - free(ifp->ifa_netmask); - free(ifp->ifa_dstaddr); - freeifaddrs(ifp->ifa_next); - free(ifp); -} - - -int getifaddrs(struct ifaddrs **ifap) -{ - int sd, ifsize; - char *ccp, *ecp; - struct ifconf ifc; - struct ifreq *ifr; - struct ifaddrs *cifa = NULL; /* current */ - struct ifaddrs *pifa = NULL; /* previous */ - const size_t IFREQSZ = sizeof(struct ifreq); - int fam; - - *ifap = NULL; - - sd = socket(AF_INET, SOCK_DGRAM, 0); - if (sd == -1) - goto error; - - /* find how much memory to allocate for the SIOCGIFCONF call */ - if (ioctl(sd, SIOCGSIZIFCONF, (caddr_t)&ifsize) < 0) - goto error; - - ifc.ifc_req = (struct ifreq *) calloc(1, ifsize); - if (ifc.ifc_req == NULL) - goto error; - ifc.ifc_len = ifsize; - - if (ioctl(sd, SIOCGIFCONF, &ifc) < 0) - goto error; - - ccp = (char *)ifc.ifc_req; - ecp = ccp + ifsize; - - while (ccp < ecp) { - - ifr = (struct ifreq *) ccp; - ifsize = sizeof(ifr->ifr_name) + SIZE(ifr->ifr_addr); - fam = ifr->ifr_addr.sa_family; - - if (fam == AF_INET || fam == AF_INET6) { - cifa = (struct ifaddrs *) calloc(1, sizeof(struct ifaddrs)); - if (cifa == NULL) - goto error; - cifa->ifa_next = NULL; - - if (pifa == NULL) *ifap = cifa; /* first one */ - else pifa->ifa_next = cifa; - - cifa->ifa_name = strdup(ifr->ifr_name); - if (cifa->ifa_name == NULL) - goto error; - cifa->ifa_flags = 0; - cifa->ifa_dstaddr = NULL; - - cifa->ifa_addr = sa_dup(&ifr->ifr_addr); - if (cifa->ifa_addr == NULL) - goto error; - - if (fam == AF_INET) { - if (ioctl(sd, SIOCGIFNETMASK, ifr, IFREQSZ) < 0) - goto error; - cifa->ifa_netmask = sa_dup(&ifr->ifr_addr); - if (cifa->ifa_netmask == NULL) - goto error; - } - - if (0 == ioctl(sd, SIOCGIFFLAGS, ifr)) /* optional */ - cifa->ifa_flags = ifr->ifr_flags; - - if (fam == AF_INET) { - if (ioctl(sd, SIOCGIFDSTADDR, ifr, IFREQSZ) < 0) { - if (0 == ioctl(sd, SIOCGIFBRDADDR, ifr, IFREQSZ)) { - cifa->ifa_dstaddr = sa_dup(&ifr->ifr_addr); - if (cifa->ifa_dstaddr == NULL) - goto error; - } - } - else { - cifa->ifa_dstaddr = sa_dup(&ifr->ifr_addr); - if (cifa->ifa_dstaddr == NULL) - goto error; - } - } - pifa = cifa; - } - - ccp += ifsize; - } - free(ifc.ifc_req); - close(sd); - return 0; -error: - if (ifc.ifc_req != NULL) - free(ifc.ifc_req); - if (sd != -1) - close(sd); - freeifaddrs(*ifap); - return (-1); -} \ No newline at end of file diff --git a/ddtrace/vendor/psutil/arch/aix/ifaddrs.h b/ddtrace/vendor/psutil/arch/aix/ifaddrs.h deleted file mode 100644 index 3920c1ccca7..00000000000 --- a/ddtrace/vendor/psutil/arch/aix/ifaddrs.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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. - */ - -/*! Based on code from - https://lists.samba.org/archive/samba-technical/2009-February/063079.html -!*/ - - -#ifndef GENERIC_AIX_IFADDRS_H -#define GENERIC_AIX_IFADDRS_H - -#include -#include - -#undef ifa_dstaddr -#undef ifa_broadaddr -#define ifa_broadaddr ifa_dstaddr - -struct ifaddrs { - struct ifaddrs *ifa_next; - char *ifa_name; - unsigned int ifa_flags; - struct sockaddr *ifa_addr; - struct sockaddr *ifa_netmask; - struct sockaddr *ifa_dstaddr; -}; - -extern int getifaddrs(struct ifaddrs **); -extern void freeifaddrs(struct ifaddrs *); - -#endif \ No newline at end of file diff --git a/ddtrace/vendor/psutil/arch/aix/net_connections.c b/ddtrace/vendor/psutil/arch/aix/net_connections.c deleted file mode 100644 index 69b43892012..00000000000 --- a/ddtrace/vendor/psutil/arch/aix/net_connections.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * 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. - */ - -/* Baded on code from lsof: - * http://www.ibm.com/developerworks/aix/library/au-lsof.html - * - dialects/aix/dproc.c:gather_proc_info - * - lib/prfp.c:process_file - * - dialects/aix/dsock.c:process_socket - * - dialects/aix/dproc.c:get_kernel_access -*/ - -#include -#include -#include -#define _KERNEL -#include -#undef _KERNEL -#include -#include -#include -#include -#include -#include - -#include "../../_psutil_common.h" -#include "net_kernel_structs.h" -#include "net_connections.h" -#include "common.h" - -#define NO_SOCKET (PyObject *)(-1) - -static int -read_unp_addr( - int Kd, - KA_T unp_addr, - char *buf, - size_t buflen -) { - struct sockaddr_un *ua = (struct sockaddr_un *)NULL; - struct sockaddr_un un; - struct mbuf64 mb; - int uo; - - if (psutil_kread(Kd, unp_addr, (char *)&mb, sizeof(mb))) { - return 1; - } - - uo = (int)(mb.m_hdr.mh_data - unp_addr); - if ((uo + sizeof(struct sockaddr)) <= sizeof(mb)) - ua = (struct sockaddr_un *)((char *)&mb + uo); - else { - if (psutil_kread(Kd, (KA_T)mb.m_hdr.mh_data, - (char *)&un, sizeof(un))) { - return 1; - } - ua = &un; - } - if (ua && ua->sun_path[0]) { - if (mb.m_len > sizeof(struct sockaddr_un)) - mb.m_len = sizeof(struct sockaddr_un); - *((char *)ua + mb.m_len - 1) = '\0'; - snprintf(buf, buflen, "%s", ua->sun_path); - } - return 0; -} - -static PyObject * -process_file(int Kd, pid32_t pid, int fd, KA_T fp) { - struct file64 f; - struct socket64 s; - struct protosw64 p; - struct domain d; - struct inpcb64 inp; - int fam; - struct tcpcb64 t; - int state = PSUTIL_CONN_NONE; - unsigned char *laddr = (unsigned char *)NULL; - unsigned char *raddr = (unsigned char *)NULL; - int rport, lport; - char laddr_str[INET6_ADDRSTRLEN]; - char raddr_str[INET6_ADDRSTRLEN]; - struct unpcb64 unp; - char unix_laddr_str[PATH_MAX] = { 0 }; - char unix_raddr_str[PATH_MAX] = { 0 }; - - /* Read file structure */ - if (psutil_kread(Kd, fp, (char *)&f, sizeof(f))) { - return NULL; - } - if (!f.f_count || f.f_type != DTYPE_SOCKET) { - return NO_SOCKET; - } - - if (psutil_kread(Kd, (KA_T) f.f_data, (char *) &s, sizeof(s))) { - return NULL; - } - - if (!s.so_type) { - return NO_SOCKET; - } - - if (!s.so_proto) { - PyErr_SetString(PyExc_RuntimeError, "invalid socket protocol handle"); - return NULL; - } - if (psutil_kread(Kd, (KA_T)s.so_proto, (char *)&p, sizeof(p))) { - return NULL; - } - - if (!p.pr_domain) { - PyErr_SetString(PyExc_RuntimeError, "invalid socket protocol domain"); - return NULL; - } - if (psutil_kread(Kd, (KA_T)p.pr_domain, (char *)&d, sizeof(d))) { - return NULL; - } - - fam = d.dom_family; - if (fam == AF_INET || fam == AF_INET6) { - /* Read protocol control block */ - if (!s.so_pcb) { - PyErr_SetString(PyExc_RuntimeError, "invalid socket PCB"); - return NULL; - } - if (psutil_kread(Kd, (KA_T) s.so_pcb, (char *) &inp, sizeof(inp))) { - return NULL; - } - - if (p.pr_protocol == IPPROTO_TCP) { - /* If this is a TCP socket, read its control block */ - if (inp.inp_ppcb - && !psutil_kread(Kd, (KA_T)inp.inp_ppcb, - (char *)&t, sizeof(t))) - state = t.t_state; - } - - if (fam == AF_INET6) { - laddr = (unsigned char *)&inp.inp_laddr6; - if (!IN6_IS_ADDR_UNSPECIFIED(&inp.inp_faddr6)) { - raddr = (unsigned char *)&inp.inp_faddr6; - rport = (int)ntohs(inp.inp_fport); - } - } - if (fam == AF_INET) { - laddr = (unsigned char *)&inp.inp_laddr; - if (inp.inp_faddr.s_addr != INADDR_ANY || inp.inp_fport != 0) { - raddr = (unsigned char *)&inp.inp_faddr; - rport = (int)ntohs(inp.inp_fport); - } - } - lport = (int)ntohs(inp.inp_lport); - - inet_ntop(fam, laddr, laddr_str, sizeof(laddr_str)); - - if (raddr != NULL) { - inet_ntop(fam, raddr, raddr_str, sizeof(raddr_str)); - return Py_BuildValue("(iii(si)(si)ii)", fd, fam, - s.so_type, laddr_str, lport, raddr_str, - rport, state, pid); - } - else { - return Py_BuildValue("(iii(si)()ii)", fd, fam, - s.so_type, laddr_str, lport, state, - pid); - } - } - - - if (fam == AF_UNIX) { - if (psutil_kread(Kd, (KA_T) s.so_pcb, (char *)&unp, sizeof(unp))) { - return NULL; - } - if ((KA_T) f.f_data != (KA_T) unp.unp_socket) { - PyErr_SetString(PyExc_RuntimeError, "unp_socket mismatch"); - return NULL; - } - - if (unp.unp_addr) { - if (read_unp_addr(Kd, unp.unp_addr, unix_laddr_str, - sizeof(unix_laddr_str))) { - return NULL; - } - } - - if (unp.unp_conn) { - if (psutil_kread(Kd, (KA_T) unp.unp_conn, (char *)&unp, - sizeof(unp))) { - return NULL; - } - if (read_unp_addr(Kd, unp.unp_addr, unix_raddr_str, - sizeof(unix_raddr_str))) { - return NULL; - } - } - - return Py_BuildValue("(iiissii)", fd, d.dom_family, - s.so_type, unix_laddr_str, unix_raddr_str, PSUTIL_CONN_NONE, - pid); - } - return NO_SOCKET; -} - -PyObject * -psutil_net_connections(PyObject *self, PyObject *args) { - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - KA_T fp; - int Kd = -1; - int i, np; - struct procentry64 *p; - struct fdsinfo64 *fds = (struct fdsinfo64 *)NULL; - pid32_t requested_pid; - pid32_t pid; - struct procentry64 *processes = (struct procentry64 *)NULL; - /* the process table */ - - if (py_retlist == NULL) - goto error; - if (! PyArg_ParseTuple(args, "i", &requested_pid)) - goto error; - - Kd = open(KMEM, O_RDONLY, 0); - if (Kd < 0) { - PyErr_SetFromErrnoWithFilename(PyExc_OSError, KMEM); - goto error; - } - - processes = psutil_read_process_table(&np); - if (!processes) - goto error; - - /* Loop through processes */ - for (p = processes; np > 0; np--, p++) { - pid = p->pi_pid; - if (requested_pid != -1 && requested_pid != pid) - continue; - if (p->pi_state == 0 || p->pi_state == SZOMB) - continue; - - if (!fds) { - fds = (struct fdsinfo64 *)malloc((size_t)FDSINFOSIZE); - if (!fds) { - PyErr_NoMemory(); - goto error; - } - } - if (getprocs64((struct procentry64 *)NULL, PROCSIZE, fds, FDSINFOSIZE, - &pid, 1) - != 1) - continue; - - /* loop over file descriptors */ - for (i = 0; i < p->pi_maxofile; i++) { - fp = (KA_T)fds->pi_ufd[i].fp; - if (fp) { - py_tuple = process_file(Kd, p->pi_pid, i, fp); - if (py_tuple == NULL) - goto error; - if (py_tuple != NO_SOCKET) { - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_tuple); - } - } - } - } - close(Kd); - free(processes); - if (fds != NULL) - free(fds); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (Kd > 0) - close(Kd); - if (processes != NULL) - free(processes); - if (fds != NULL) - free(fds); - return NULL; -} diff --git a/ddtrace/vendor/psutil/arch/aix/net_connections.h b/ddtrace/vendor/psutil/arch/aix/net_connections.h deleted file mode 100644 index 222bcaf354e..00000000000 --- a/ddtrace/vendor/psutil/arch/aix/net_connections.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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. - */ - -#ifndef __NET_CONNECTIONS_H__ -#define __NET_CONNECTIONS_H__ - -#include - -PyObject* psutil_net_connections(PyObject *self, PyObject *args); - -#endif /* __NET_CONNECTIONS_H__ */ \ No newline at end of file diff --git a/ddtrace/vendor/psutil/arch/aix/net_kernel_structs.h b/ddtrace/vendor/psutil/arch/aix/net_kernel_structs.h deleted file mode 100644 index 4e7a088c143..00000000000 --- a/ddtrace/vendor/psutil/arch/aix/net_kernel_structs.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * 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. - */ - -/* The kernel is always 64 bit but Python is usually compiled as a 32 bit - * process. We're reading the kernel memory to get the network connections, - * so we need the structs we read to be defined with 64 bit "pointers". - * Here are the partial definitions of the structs we use, taken from the - * header files, with data type sizes converted to their 64 bit counterparts, - * and unused data truncated. */ - -#ifdef __64BIT__ -/* In case we're in a 64 bit process after all */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#define file64 file -#define socket64 socket -#define protosw64 protosw -#define inpcb64 inpcb -#define tcpcb64 tcpcb -#define unpcb64 unpcb -#define mbuf64 mbuf -#else /* __64BIT__ */ - struct file64 { - int f_flag; - int f_count; - int f_options; - int f_type; - u_longlong_t f_data; - }; - - struct socket64 { - short so_type; /* generic type, see socket.h */ - short so_options; /* from socket call, see socket.h */ - ushort so_linger; /* time to linger while closing */ - short so_state; /* internal state flags SS_*, below */ - u_longlong_t so_pcb; /* protocol control block */ - u_longlong_t so_proto; /* protocol handle */ - }; - - struct protosw64 { - short pr_type; /* socket type used for */ - u_longlong_t pr_domain; /* domain protocol a member of */ - short pr_protocol; /* protocol number */ - short pr_flags; /* see below */ - }; - - struct inpcb64 { - u_longlong_t inp_next,inp_prev; - /* pointers to other pcb's */ - u_longlong_t inp_head; /* pointer back to chain of inpcb's - for this protocol */ - u_int32_t inp_iflowinfo; /* input flow label */ - u_short inp_fport; /* foreign port */ - u_int16_t inp_fatype; /* foreign address type */ - union in_addr_6 inp_faddr_6; /* foreign host table entry */ - u_int32_t inp_oflowinfo; /* output flow label */ - u_short inp_lport; /* local port */ - u_int16_t inp_latype; /* local address type */ - union in_addr_6 inp_laddr_6; /* local host table entry */ - u_longlong_t inp_socket; /* back pointer to socket */ - u_longlong_t inp_ppcb; /* pointer to per-protocol pcb */ - u_longlong_t space_rt; - struct sockaddr_in6 spare_dst; - u_longlong_t inp_ifa; /* interface address to use */ - int inp_flags; /* generic IP/datagram flags */ -}; - -struct tcpcb64 { - u_longlong_t seg__next; - u_longlong_t seg__prev; - short t_state; /* state of this connection */ -}; - -struct unpcb64 { - u_longlong_t unp_socket; /* pointer back to socket */ - u_longlong_t unp_vnode; /* if associated with file */ - ino_t unp_vno; /* fake vnode number */ - u_longlong_t unp_conn; /* control block of connected socket */ - u_longlong_t unp_refs; /* referencing socket linked list */ - u_longlong_t unp_nextref; /* link in unp_refs list */ - u_longlong_t unp_addr; /* bound address of socket */ -}; - -struct m_hdr64 -{ - u_longlong_t mh_next; /* next buffer in chain */ - u_longlong_t mh_nextpkt; /* next chain in queue/record */ - long mh_len; /* amount of data in this mbuf */ - u_longlong_t mh_data; /* location of data */ -}; - -struct mbuf64 -{ - struct m_hdr64 m_hdr; -}; - -#define m_len m_hdr.mh_len - -#endif /* __64BIT__ */ \ No newline at end of file diff --git a/ddtrace/vendor/psutil/arch/freebsd/proc_socks.c b/ddtrace/vendor/psutil/arch/freebsd/proc_socks.c deleted file mode 100644 index a458a01e531..00000000000 --- a/ddtrace/vendor/psutil/arch/freebsd/proc_socks.c +++ /dev/null @@ -1,368 +0,0 @@ -/* - * 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. - * - * Retrieves per-process open socket connections. - */ - -#include -#include -#include // for struct xsocket -#include -#include -#include // for xinpcb struct -#include -#include // for struct xtcpcb -#include // for inet_ntop() -#include - -#include "../../_psutil_common.h" -#include "../../_psutil_posix.h" - - -// The tcplist fetching and walking is borrowed from netstat/inet.c. -static char * -psutil_fetch_tcplist(void) { - char *buf; - size_t len; - - for (;;) { - if (sysctlbyname("net.inet.tcp.pcblist", NULL, &len, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - buf = malloc(len); - if (buf == NULL) { - PyErr_NoMemory(); - return NULL; - } - if (sysctlbyname("net.inet.tcp.pcblist", buf, &len, NULL, 0) < 0) { - free(buf); - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - return buf; - } -} - - -static int -psutil_sockaddr_port(int family, struct sockaddr_storage *ss) { - struct sockaddr_in6 *sin6; - struct sockaddr_in *sin; - - if (family == AF_INET) { - sin = (struct sockaddr_in *)ss; - return (sin->sin_port); - } - else { - sin6 = (struct sockaddr_in6 *)ss; - return (sin6->sin6_port); - } -} - - -static void * -psutil_sockaddr_addr(int family, struct sockaddr_storage *ss) { - struct sockaddr_in6 *sin6; - struct sockaddr_in *sin; - - if (family == AF_INET) { - sin = (struct sockaddr_in *)ss; - return (&sin->sin_addr); - } - else { - sin6 = (struct sockaddr_in6 *)ss; - return (&sin6->sin6_addr); - } -} - - -static socklen_t -psutil_sockaddr_addrlen(int family) { - if (family == AF_INET) - return (sizeof(struct in_addr)); - else - return (sizeof(struct in6_addr)); -} - - -static int -psutil_sockaddr_matches(int family, int port, void *pcb_addr, - struct sockaddr_storage *ss) { - if (psutil_sockaddr_port(family, ss) != port) - return (0); - return (memcmp(psutil_sockaddr_addr(family, ss), pcb_addr, - psutil_sockaddr_addrlen(family)) == 0); -} - - -#if __FreeBSD_version >= 1200026 -static struct xtcpcb * -psutil_search_tcplist(char *buf, struct kinfo_file *kif) { - struct xtcpcb *tp; - struct xinpcb *inp; -#else -static struct tcpcb * -psutil_search_tcplist(char *buf, struct kinfo_file *kif) { - struct tcpcb *tp; - struct inpcb *inp; -#endif - struct xinpgen *xig, *oxig; - struct xsocket *so; - - oxig = xig = (struct xinpgen *)buf; - for (xig = (struct xinpgen *)((char *)xig + xig->xig_len); - xig->xig_len > sizeof(struct xinpgen); - xig = (struct xinpgen *)((char *)xig + xig->xig_len)) { - -#if __FreeBSD_version >= 1200026 - tp = (struct xtcpcb *)xig; - inp = &tp->xt_inp; - so = &inp->xi_socket; -#else - tp = &((struct xtcpcb *)xig)->xt_tp; - inp = &((struct xtcpcb *)xig)->xt_inp; - so = &((struct xtcpcb *)xig)->xt_socket; -#endif - - if (so->so_type != kif->kf_sock_type || - so->xso_family != kif->kf_sock_domain || - so->xso_protocol != kif->kf_sock_protocol) - continue; - - if (kif->kf_sock_domain == AF_INET) { - if (!psutil_sockaddr_matches( - AF_INET, inp->inp_lport, &inp->inp_laddr, -#if __FreeBSD_version < 1200031 - &kif->kf_sa_local)) -#else - &kif->kf_un.kf_sock.kf_sa_local)) -#endif - continue; - if (!psutil_sockaddr_matches( - AF_INET, inp->inp_fport, &inp->inp_faddr, -#if __FreeBSD_version < 1200031 - &kif->kf_sa_peer)) -#else - &kif->kf_un.kf_sock.kf_sa_peer)) -#endif - continue; - } else { - if (!psutil_sockaddr_matches( - AF_INET6, inp->inp_lport, &inp->in6p_laddr, -#if __FreeBSD_version < 1200031 - &kif->kf_sa_local)) -#else - &kif->kf_un.kf_sock.kf_sa_local)) -#endif - continue; - if (!psutil_sockaddr_matches( - AF_INET6, inp->inp_fport, &inp->in6p_faddr, -#if __FreeBSD_version < 1200031 - &kif->kf_sa_peer)) -#else - &kif->kf_un.kf_sock.kf_sa_peer)) -#endif - continue; - } - - return (tp); - } - return NULL; -} - - - -PyObject * -psutil_proc_connections(PyObject *self, PyObject *args) { - // Return connections opened by process. - long pid; - int i; - int cnt; - struct kinfo_file *freep = NULL; - struct kinfo_file *kif; - char *tcplist = NULL; -#if __FreeBSD_version >= 1200026 - struct xtcpcb *tcp; -#else - struct tcpcb *tcp; -#endif - - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - PyObject *py_laddr = NULL; - PyObject *py_raddr = NULL; - PyObject *py_af_filter = NULL; - PyObject *py_type_filter = NULL; - PyObject *py_family = NULL; - PyObject *py_type = NULL; - - if (py_retlist == NULL) - return NULL; - if (! PyArg_ParseTuple(args, "lOO", &pid, &py_af_filter, &py_type_filter)) - goto error; - if (!PySequence_Check(py_af_filter) || !PySequence_Check(py_type_filter)) { - PyErr_SetString(PyExc_TypeError, "arg 2 or 3 is not a sequence"); - goto error; - } - - errno = 0; - freep = kinfo_getfile(pid, &cnt); - if (freep == NULL) { - psutil_raise_for_pid(pid, "kinfo_getfile()"); - goto error; - } - - tcplist = psutil_fetch_tcplist(); - if (tcplist == NULL) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (i = 0; i < cnt; i++) { - int lport, rport, state; - char lip[200], rip[200]; - char path[PATH_MAX]; - int inseq; - py_tuple = NULL; - py_laddr = NULL; - py_raddr = NULL; - - kif = &freep[i]; - if (kif->kf_type == KF_TYPE_SOCKET) { - // apply filters - py_family = PyLong_FromLong((long)kif->kf_sock_domain); - inseq = PySequence_Contains(py_af_filter, py_family); - Py_DECREF(py_family); - if (inseq == 0) - continue; - py_type = PyLong_FromLong((long)kif->kf_sock_type); - inseq = PySequence_Contains(py_type_filter, py_type); - Py_DECREF(py_type); - if (inseq == 0) - continue; - // IPv4 / IPv6 socket - if ((kif->kf_sock_domain == AF_INET) || - (kif->kf_sock_domain == AF_INET6)) { - // fill status - state = PSUTIL_CONN_NONE; - if (kif->kf_sock_type == SOCK_STREAM) { - tcp = psutil_search_tcplist(tcplist, kif); - if (tcp != NULL) - state = (int)tcp->t_state; - } - - // build addr and port - inet_ntop( - kif->kf_sock_domain, - psutil_sockaddr_addr(kif->kf_sock_domain, -#if __FreeBSD_version < 1200031 - &kif->kf_sa_local), -#else - &kif->kf_un.kf_sock.kf_sa_local), -#endif - lip, - sizeof(lip)); - inet_ntop( - kif->kf_sock_domain, - psutil_sockaddr_addr(kif->kf_sock_domain, -#if __FreeBSD_version < 1200031 - &kif->kf_sa_peer), -#else - &kif->kf_un.kf_sock.kf_sa_peer), -#endif - rip, - sizeof(rip)); - lport = htons(psutil_sockaddr_port(kif->kf_sock_domain, -#if __FreeBSD_version < 1200031 - &kif->kf_sa_local)); -#else - &kif->kf_un.kf_sock.kf_sa_local)); -#endif - rport = htons(psutil_sockaddr_port(kif->kf_sock_domain, -#if __FreeBSD_version < 1200031 - &kif->kf_sa_peer)); -#else - &kif->kf_un.kf_sock.kf_sa_peer)); -#endif - - // construct python tuple/list - py_laddr = Py_BuildValue("(si)", lip, lport); - if (!py_laddr) - goto error; - if (rport != 0) - py_raddr = Py_BuildValue("(si)", rip, rport); - else - py_raddr = Py_BuildValue("()"); - if (!py_raddr) - goto error; - py_tuple = Py_BuildValue( - "(iiiNNi)", - kif->kf_fd, - kif->kf_sock_domain, - kif->kf_sock_type, - py_laddr, - py_raddr, - state - ); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_tuple); - } - // UNIX socket. - // Note: remote path cannot be determined. - else if (kif->kf_sock_domain == AF_UNIX) { - struct sockaddr_un *sun; - -#if __FreeBSD_version < 1200031 - sun = (struct sockaddr_un *)&kif->kf_sa_local; -#else - sun = (struct sockaddr_un *)&kif->kf_un.kf_sock.kf_sa_local; -#endif - snprintf( - path, sizeof(path), "%.*s", - (int)(sun->sun_len - (sizeof(*sun) - sizeof(sun->sun_path))), - sun->sun_path); - - py_laddr = PyUnicode_DecodeFSDefault(path); - if (! py_laddr) - goto error; - - py_tuple = Py_BuildValue( - "(iiiOsi)", - kif->kf_fd, - kif->kf_sock_domain, - kif->kf_sock_type, - py_laddr, - "", // raddr can't be determined - PSUTIL_CONN_NONE - ); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_tuple); - Py_DECREF(py_laddr); - } - } - } - free(freep); - free(tcplist); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_XDECREF(py_laddr); - Py_XDECREF(py_raddr); - Py_DECREF(py_retlist); - if (freep != NULL) - free(freep); - if (tcplist != NULL) - free(tcplist); - return NULL; -} diff --git a/ddtrace/vendor/psutil/arch/freebsd/proc_socks.h b/ddtrace/vendor/psutil/arch/freebsd/proc_socks.h deleted file mode 100644 index a7996b10749..00000000000 --- a/ddtrace/vendor/psutil/arch/freebsd/proc_socks.h +++ /dev/null @@ -1,9 +0,0 @@ -/* - * 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. - */ - -#include - -PyObject* psutil_proc_connections(PyObject* self, PyObject* args); diff --git a/ddtrace/vendor/psutil/arch/freebsd/specific.c b/ddtrace/vendor/psutil/arch/freebsd/specific.c deleted file mode 100644 index 26b802422db..00000000000 --- a/ddtrace/vendor/psutil/arch/freebsd/specific.c +++ /dev/null @@ -1,1115 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, 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. - * - * Helper functions specific to FreeBSD. - * Used by _psutil_bsd module methods. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include // needed for vmtotal struct -#include // for swap mem -#include // process open files, shared libs (kinfo_getvmmap), cwd -#include - -#include "../../_psutil_common.h" -#include "../../_psutil_posix.h" - -#define PSUTIL_TV2DOUBLE(t) ((t).tv_sec + (t).tv_usec / 1000000.0) -#define PSUTIL_BT2MSEC(bt) (bt.sec * 1000 + (((uint64_t) 1000000000 * (uint32_t) \ - (bt.frac >> 32) ) >> 32 ) / 1000000) -#define DECIKELVIN_2_CELCIUS(t) (t - 2731) / 10 -#ifndef _PATH_DEVNULL -#define _PATH_DEVNULL "/dev/null" -#endif - - -// ============================================================================ -// Utility functions -// ============================================================================ - - -int -psutil_kinfo_proc(const pid_t pid, struct kinfo_proc *proc) { - // Fills a kinfo_proc struct based on process pid. - int mib[4]; - size_t size; - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID; - mib[3] = pid; - - size = sizeof(struct kinfo_proc); - if (sysctl((int *)mib, 4, proc, &size, NULL, 0) == -1) { - PyErr_SetFromOSErrnoWithSyscall("sysctl(KERN_PROC_PID)"); - return -1; - } - - // sysctl stores 0 in the size if we can't find the process information. - if (size == 0) { - NoSuchProcess(""); - return -1; - } - return 0; -} - - -// remove spaces from string -static void psutil_remove_spaces(char *str) { - char *p1 = str; - char *p2 = str; - do - while (*p2 == ' ') - p2++; - while ((*p1++ = *p2++)); -} - - -// ============================================================================ -// APIS -// ============================================================================ - -int -psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount) { - // Returns a list of all BSD processes on the system. This routine - // allocates the list and puts it in *procList and a count of the - // number of entries in *procCount. You are responsible for freeing - // this list (use "free" from System framework). - // On success, the function returns 0. - // On error, the function returns a BSD errno value. - int err; - struct kinfo_proc *result; - int done; - int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_PROC, 0 }; - size_t length; - - assert( procList != NULL); - assert(*procList == NULL); - assert(procCount != NULL); - - *procCount = 0; - - /* - * We start by calling sysctl with result == NULL and length == 0. - * That will succeed, and set length to the appropriate length. - * We then allocate a buffer of that size and call sysctl again - * with that buffer. If that succeeds, we're done. If that fails - * with ENOMEM, we have to throw away our buffer and loop. Note - * that the loop causes use to call sysctl with NULL again; this - * is necessary because the ENOMEM failure case sets length to - * the amount of data returned, not the amount of data that - * could have been returned. - */ - result = NULL; - done = 0; - do { - assert(result == NULL); - // Call sysctl with a NULL buffer. - length = 0; - err = sysctl((int *)name, (sizeof(name) / sizeof(*name)) - 1, - NULL, &length, NULL, 0); - if (err == -1) - err = errno; - - // Allocate an appropriately sized buffer based on the results - // from the previous call. - if (err == 0) { - result = malloc(length); - if (result == NULL) - err = ENOMEM; - } - - // Call sysctl again with the new buffer. If we get an ENOMEM - // error, toss away our buffer and start again. - if (err == 0) { - err = sysctl((int *) name, (sizeof(name) / sizeof(*name)) - 1, - result, &length, NULL, 0); - if (err == -1) - err = errno; - if (err == 0) { - done = 1; - } - else if (err == ENOMEM) { - assert(result != NULL); - free(result); - result = NULL; - err = 0; - } - } - } while (err == 0 && ! done); - - // Clean up and establish post conditions. - if (err != 0 && result != NULL) { - free(result); - result = NULL; - } - - *procList = result; - *procCount = length / sizeof(struct kinfo_proc); - - assert((err == 0) == (*procList != NULL)); - return err; -} - - -/* - * XXX no longer used; it probably makese sense to remove it. - * Borrowed from psi Python System Information project - * - * Get command arguments and environment variables. - * - * Based on code from ps. - * - * Returns: - * 0 for success; - * -1 for failure (Exception raised); - * 1 for insufficient privileges. - */ -static char -*psutil_get_cmd_args(long pid, size_t *argsize) { - int mib[4]; - int argmax; - size_t size = sizeof(argmax); - char *procargs = NULL; - - // Get the maximum process arguments size. - mib[0] = CTL_KERN; - mib[1] = KERN_ARGMAX; - - size = sizeof(argmax); - if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1) - return NULL; - - // Allocate space for the arguments. - procargs = (char *)malloc(argmax); - if (procargs == NULL) { - PyErr_NoMemory(); - return NULL; - } - - // Make a sysctl() call to get the raw argument space of the process. - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_ARGS; - mib[3] = pid; - - size = argmax; - if (sysctl(mib, 4, procargs, &size, NULL, 0) == -1) { - free(procargs); - PyErr_SetFromOSErrnoWithSyscall("sysctl(KERN_PROC_ARGS)"); - return NULL; - } - - // return string and set the length of arguments - *argsize = size; - return procargs; -} - - -// returns the command line as a python list object -PyObject * -psutil_get_cmdline(long pid) { - char *argstr = NULL; - size_t pos = 0; - size_t argsize = 0; - PyObject *py_retlist = Py_BuildValue("[]"); - PyObject *py_arg = NULL; - - if (pid < 0) - return py_retlist; - argstr = psutil_get_cmd_args(pid, &argsize); - if (argstr == NULL) - goto error; - - // args are returned as a flattened string with \0 separators between - // arguments add each string to the list then step forward to the next - // separator - if (argsize > 0) { - while (pos < argsize) { - py_arg = PyUnicode_DecodeFSDefault(&argstr[pos]); - if (!py_arg) - goto error; - if (PyList_Append(py_retlist, py_arg)) - goto error; - Py_DECREF(py_arg); - pos = pos + strlen(&argstr[pos]) + 1; - } - } - - free(argstr); - return py_retlist; - -error: - Py_XDECREF(py_arg); - Py_DECREF(py_retlist); - if (argstr != NULL) - free(argstr); - return NULL; -} - - -/* - * Return process pathname executable. - * Thanks to Robert N. M. Watson: - * http://fxr.googlebit.com/source/usr.bin/procstat/procstat_bin.c?v=8-CURRENT - */ -PyObject * -psutil_proc_exe(PyObject *self, PyObject *args) { - long pid; - char pathname[PATH_MAX]; - int error; - int mib[4]; - int ret; - size_t size; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PATHNAME; - mib[3] = pid; - - size = sizeof(pathname); - error = sysctl(mib, 4, pathname, &size, NULL, 0); - if (error == -1) { - // see: https://github.com/giampaolo/psutil/issues/907 - if (errno == ENOENT) { - return PyUnicode_DecodeFSDefault(""); - } - else { - return \ - PyErr_SetFromOSErrnoWithSyscall("sysctl(KERN_PROC_PATHNAME)"); - } - } - if (size == 0 || strlen(pathname) == 0) { - ret = psutil_pid_exists(pid); - if (ret == -1) - return NULL; - else if (ret == 0) - return NoSuchProcess(""); - else - strcpy(pathname, ""); - } - - return PyUnicode_DecodeFSDefault(pathname); -} - - -PyObject * -psutil_proc_num_threads(PyObject *self, PyObject *args) { - // Return number of threads used by process as a Python integer. - long pid; - struct kinfo_proc kp; - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (psutil_kinfo_proc(pid, &kp) == -1) - return NULL; - return Py_BuildValue("l", (long)kp.ki_numthreads); -} - - -PyObject * -psutil_proc_threads(PyObject *self, PyObject *args) { - // Retrieves all threads used by process returning a list of tuples - // including thread id, user time and system time. - // Thanks to Robert N. M. Watson: - // http://code.metager.de/source/xref/freebsd/usr.bin/procstat/ - // procstat_threads.c - long pid; - int mib[4]; - struct kinfo_proc *kip = NULL; - struct kinfo_proc *kipp = NULL; - int error; - unsigned int i; - size_t size; - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - - if (py_retlist == NULL) - return NULL; - if (! PyArg_ParseTuple(args, "l", &pid)) - goto error; - - // we need to re-query for thread information, so don't use *kipp - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID | KERN_PROC_INC_THREAD; - mib[3] = pid; - - size = 0; - error = sysctl(mib, 4, NULL, &size, NULL, 0); - if (error == -1) { - PyErr_SetFromOSErrnoWithSyscall("sysctl(KERN_PROC_INC_THREAD)"); - goto error; - } - if (size == 0) { - NoSuchProcess(""); - goto error; - } - - kip = malloc(size); - if (kip == NULL) { - PyErr_NoMemory(); - goto error; - } - - error = sysctl(mib, 4, kip, &size, NULL, 0); - if (error == -1) { - PyErr_SetFromOSErrnoWithSyscall("sysctl(KERN_PROC_INC_THREAD)"); - goto error; - } - if (size == 0) { - NoSuchProcess(""); - goto error; - } - - for (i = 0; i < size / sizeof(*kipp); i++) { - kipp = &kip[i]; - py_tuple = Py_BuildValue("Idd", - kipp->ki_tid, - PSUTIL_TV2DOUBLE(kipp->ki_rusage.ru_utime), - PSUTIL_TV2DOUBLE(kipp->ki_rusage.ru_stime)); - if (py_tuple == NULL) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_tuple); - } - free(kip); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (kip != NULL) - free(kip); - return NULL; -} - - -PyObject * -psutil_cpu_count_phys(PyObject *self, PyObject *args) { - // Return an XML string from which we'll determine the number of - // physical CPU cores in the system. - void *topology = NULL; - size_t size = 0; - PyObject *py_str; - - if (sysctlbyname("kern.sched.topology_spec", NULL, &size, NULL, 0)) - goto error; - - topology = malloc(size); - if (!topology) { - PyErr_NoMemory(); - return NULL; - } - - if (sysctlbyname("kern.sched.topology_spec", topology, &size, NULL, 0)) - goto error; - - py_str = Py_BuildValue("s", topology); - free(topology); - return py_str; - -error: - if (topology != NULL) - free(topology); - Py_RETURN_NONE; -} - - -/* - * Return virtual memory usage statistics. - */ -PyObject * -psutil_virtual_mem(PyObject *self, PyObject *args) { - unsigned long total; - unsigned int active, inactive, wired, cached, free; - size_t size = sizeof(total); - struct vmtotal vm; - int mib[] = {CTL_VM, VM_METER}; - long pagesize = getpagesize(); -#if __FreeBSD_version > 702101 - long buffers; -#else - int buffers; -#endif - size_t buffers_size = sizeof(buffers); - - if (sysctlbyname("hw.physmem", &total, &size, NULL, 0)) { - return PyErr_SetFromOSErrnoWithSyscall("sysctlbyname('hw.physmem')"); - } - if (sysctlbyname("vm.stats.vm.v_active_count", &active, &size, NULL, 0)) { - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('vm.stats.vm.v_active_count')"); - } - if (sysctlbyname("vm.stats.vm.v_inactive_count", &inactive, &size, NULL, 0)) - { - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('vm.stats.vm.v_inactive_count')"); - } - if (sysctlbyname("vm.stats.vm.v_wire_count", &wired, &size, NULL, 0)) { - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('vm.stats.vm.v_wire_count')"); - } - // https://github.com/giampaolo/psutil/issues/997 - if (sysctlbyname("vm.stats.vm.v_cache_count", &cached, &size, NULL, 0)) { - cached = 0; - } - if (sysctlbyname("vm.stats.vm.v_free_count", &free, &size, NULL, 0)) { - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('vm.stats.vm.v_free_count')"); - } - if (sysctlbyname("vfs.bufspace", &buffers, &buffers_size, NULL, 0)) { - return PyErr_SetFromOSErrnoWithSyscall("sysctlbyname('vfs.bufspace')"); - } - - size = sizeof(vm); - if (sysctl(mib, 2, &vm, &size, NULL, 0) != 0) { - return PyErr_SetFromOSErrnoWithSyscall("sysctl(CTL_VM | VM_METER)"); - } - - return Py_BuildValue("KKKKKKKK", - (unsigned long long) total, - (unsigned long long) free * pagesize, - (unsigned long long) active * pagesize, - (unsigned long long) inactive * pagesize, - (unsigned long long) wired * pagesize, - (unsigned long long) cached * pagesize, - (unsigned long long) buffers, - (unsigned long long) (vm.t_vmshr + vm.t_rmshr) * pagesize // shared - ); -} - - -PyObject * -psutil_swap_mem(PyObject *self, PyObject *args) { - // Return swap memory stats (see 'swapinfo' cmdline tool) - kvm_t *kd; - struct kvm_swap kvmsw[1]; - unsigned int swapin, swapout, nodein, nodeout; - size_t size = sizeof(unsigned int); - int pagesize; - - kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, "kvm_open failed"); - if (kd == NULL) { - PyErr_SetString(PyExc_RuntimeError, "kvm_open() syscall failed"); - return NULL; - } - - if (kvm_getswapinfo(kd, kvmsw, 1, 0) < 0) { - kvm_close(kd); - PyErr_SetString(PyExc_RuntimeError, - "kvm_getswapinfo() syscall failed"); - return NULL; - } - - kvm_close(kd); - - if (sysctlbyname("vm.stats.vm.v_swapin", &swapin, &size, NULL, 0) == -1) { - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('vm.stats.vm.v_swapin)'"); - } - if (sysctlbyname("vm.stats.vm.v_swapout", &swapout, &size, NULL, 0) == -1){ - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('vm.stats.vm.v_swapout)'"); - } - if (sysctlbyname("vm.stats.vm.v_vnodein", &nodein, &size, NULL, 0) == -1) { - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('vm.stats.vm.v_vnodein)'"); - } - if (sysctlbyname("vm.stats.vm.v_vnodeout", &nodeout, &size, NULL, 0) == -1) { - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('vm.stats.vm.v_vnodeout)'"); - } - - pagesize = getpagesize(); - if (pagesize <= 0) { - PyErr_SetString(PyExc_ValueError, "invalid getpagesize()"); - return NULL; - } - - return Py_BuildValue( - "(KKKII)", - (unsigned long long)kvmsw[0].ksw_total * pagesize, // total - (unsigned long long)kvmsw[0].ksw_used * pagesize, // used - (unsigned long long)kvmsw[0].ksw_total * pagesize - // free - kvmsw[0].ksw_used * pagesize, - swapin + swapout, // swap in - nodein + nodeout // swap out - ); -} - - -#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000 -PyObject * -psutil_proc_cwd(PyObject *self, PyObject *args) { - long pid; - struct kinfo_file *freep = NULL; - struct kinfo_file *kif; - struct kinfo_proc kipp; - PyObject *py_path = NULL; - - int i, cnt; - - if (! PyArg_ParseTuple(args, "l", &pid)) - goto error; - if (psutil_kinfo_proc(pid, &kipp) == -1) - goto error; - - errno = 0; - freep = kinfo_getfile(pid, &cnt); - if (freep == NULL) { - psutil_raise_for_pid(pid, "kinfo_getfile()"); - goto error; - } - - for (i = 0; i < cnt; i++) { - kif = &freep[i]; - if (kif->kf_fd == KF_FD_TYPE_CWD) { - py_path = PyUnicode_DecodeFSDefault(kif->kf_path); - if (!py_path) - goto error; - break; - } - } - /* - * For lower pids it seems we can't retrieve any information - * (lsof can't do that it either). Since this happens even - * as root we return an empty string instead of AccessDenied. - */ - if (py_path == NULL) - py_path = PyUnicode_DecodeFSDefault(""); - free(freep); - return py_path; - -error: - Py_XDECREF(py_path); - if (freep != NULL) - free(freep); - return NULL; -} -#endif - - -#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000 -PyObject * -psutil_proc_num_fds(PyObject *self, PyObject *args) { - long pid; - int cnt; - - struct kinfo_file *freep; - struct kinfo_proc kipp; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (psutil_kinfo_proc(pid, &kipp) == -1) - return NULL; - - errno = 0; - freep = kinfo_getfile(pid, &cnt); - if (freep == NULL) { - psutil_raise_for_pid(pid, "kinfo_getfile()"); - return NULL; - } - free(freep); - - return Py_BuildValue("i", cnt); -} -#endif - - -PyObject * -psutil_per_cpu_times(PyObject *self, PyObject *args) { - static int maxcpus; - int mib[2]; - int ncpu; - size_t len; - size_t size; - int i; - PyObject *py_retlist = PyList_New(0); - PyObject *py_cputime = NULL; - - if (py_retlist == NULL) - return NULL; - - // retrieve maxcpus value - size = sizeof(maxcpus); - if (sysctlbyname("kern.smp.maxcpus", &maxcpus, &size, NULL, 0) < 0) { - Py_DECREF(py_retlist); - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('kern.smp.maxcpus')"); - } - long cpu_time[maxcpus][CPUSTATES]; - - // retrieve the number of cpus - mib[0] = CTL_HW; - mib[1] = HW_NCPU; - len = sizeof(ncpu); - if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1) { - PyErr_SetFromOSErrnoWithSyscall("sysctl(HW_NCPU)"); - goto error; - } - - // per-cpu info - size = sizeof(cpu_time); - if (sysctlbyname("kern.cp_times", &cpu_time, &size, NULL, 0) == -1) { - PyErr_SetFromOSErrnoWithSyscall("sysctlbyname('kern.smp.maxcpus')"); - goto error; - } - - for (i = 0; i < ncpu; i++) { - py_cputime = Py_BuildValue( - "(ddddd)", - (double)cpu_time[i][CP_USER] / CLOCKS_PER_SEC, - (double)cpu_time[i][CP_NICE] / CLOCKS_PER_SEC, - (double)cpu_time[i][CP_SYS] / CLOCKS_PER_SEC, - (double)cpu_time[i][CP_IDLE] / CLOCKS_PER_SEC, - (double)cpu_time[i][CP_INTR] / CLOCKS_PER_SEC); - if (!py_cputime) - goto error; - if (PyList_Append(py_retlist, py_cputime)) - goto error; - Py_DECREF(py_cputime); - } - - return py_retlist; - -error: - Py_XDECREF(py_cputime); - Py_DECREF(py_retlist); - return NULL; -} - - -PyObject * -psutil_disk_io_counters(PyObject *self, PyObject *args) { - int i; - struct statinfo stats; - - PyObject *py_retdict = PyDict_New(); - PyObject *py_disk_info = NULL; - - if (py_retdict == NULL) - return NULL; - if (devstat_checkversion(NULL) < 0) { - PyErr_Format(PyExc_RuntimeError, - "devstat_checkversion() syscall failed"); - goto error; - } - - stats.dinfo = (struct devinfo *)malloc(sizeof(struct devinfo)); - if (stats.dinfo == NULL) { - PyErr_NoMemory(); - goto error; - } - bzero(stats.dinfo, sizeof(struct devinfo)); - - if (devstat_getdevs(NULL, &stats) == -1) { - PyErr_Format(PyExc_RuntimeError, "devstat_getdevs() syscall failed"); - goto error; - } - - for (i = 0; i < stats.dinfo->numdevs; i++) { - py_disk_info = NULL; - struct devstat current; - char disk_name[128]; - current = stats.dinfo->devices[i]; - snprintf(disk_name, sizeof(disk_name), "%s%d", - current.device_name, - current.unit_number); - - py_disk_info = Py_BuildValue( - "(KKKKLLL)", - current.operations[DEVSTAT_READ], // no reads - current.operations[DEVSTAT_WRITE], // no writes - current.bytes[DEVSTAT_READ], // bytes read - current.bytes[DEVSTAT_WRITE], // bytes written - (long long) PSUTIL_BT2MSEC(current.duration[DEVSTAT_READ]), // r time - (long long) PSUTIL_BT2MSEC(current.duration[DEVSTAT_WRITE]), // w time - (long long) PSUTIL_BT2MSEC(current.busy_time) // busy time - ); // finished transactions - if (!py_disk_info) - goto error; - if (PyDict_SetItemString(py_retdict, disk_name, py_disk_info)) - goto error; - Py_DECREF(py_disk_info); - } - - if (stats.dinfo->mem_ptr) - free(stats.dinfo->mem_ptr); - free(stats.dinfo); - return py_retdict; - -error: - Py_XDECREF(py_disk_info); - Py_DECREF(py_retdict); - if (stats.dinfo != NULL) - free(stats.dinfo); - return NULL; -} - - -PyObject * -psutil_proc_memory_maps(PyObject *self, PyObject *args) { - // Return a list of tuples for every process memory maps. - //'procstat' cmdline utility has been used as an example. - long pid; - int ptrwidth; - int i, cnt; - char addr[1000]; - char perms[4]; - char *path; - struct kinfo_proc kp; - struct kinfo_vmentry *freep = NULL; - struct kinfo_vmentry *kve; - ptrwidth = 2 * sizeof(void *); - PyObject *py_tuple = NULL; - PyObject *py_path = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - if (! PyArg_ParseTuple(args, "l", &pid)) - goto error; - if (psutil_kinfo_proc(pid, &kp) == -1) - goto error; - - errno = 0; - freep = kinfo_getvmmap(pid, &cnt); - if (freep == NULL) { - psutil_raise_for_pid(pid, "kinfo_getvmmap()"); - goto error; - } - for (i = 0; i < cnt; i++) { - py_tuple = NULL; - kve = &freep[i]; - addr[0] = '\0'; - perms[0] = '\0'; - sprintf(addr, "%#*jx-%#*jx", ptrwidth, (uintmax_t)kve->kve_start, - ptrwidth, (uintmax_t)kve->kve_end); - psutil_remove_spaces(addr); - strlcat(perms, kve->kve_protection & KVME_PROT_READ ? "r" : "-", - sizeof(perms)); - strlcat(perms, kve->kve_protection & KVME_PROT_WRITE ? "w" : "-", - sizeof(perms)); - strlcat(perms, kve->kve_protection & KVME_PROT_EXEC ? "x" : "-", - sizeof(perms)); - - if (strlen(kve->kve_path) == 0) { - switch (kve->kve_type) { - case KVME_TYPE_NONE: - path = "[none]"; - break; - case KVME_TYPE_DEFAULT: - path = "[default]"; - break; - case KVME_TYPE_VNODE: - path = "[vnode]"; - break; - case KVME_TYPE_SWAP: - path = "[swap]"; - break; - case KVME_TYPE_DEVICE: - path = "[device]"; - break; - case KVME_TYPE_PHYS: - path = "[phys]"; - break; - case KVME_TYPE_DEAD: - path = "[dead]"; - break; - case KVME_TYPE_SG: - path = "[sg]"; - break; - case KVME_TYPE_UNKNOWN: - path = "[unknown]"; - break; - default: - path = "[?]"; - break; - } - } - else { - path = kve->kve_path; - } - - py_path = PyUnicode_DecodeFSDefault(path); - if (! py_path) - goto error; - py_tuple = Py_BuildValue("ssOiiii", - addr, // "start-end" address - perms, // "rwx" permissions - py_path, // path - kve->kve_resident, // rss - kve->kve_private_resident, // private - kve->kve_ref_count, // ref count - kve->kve_shadow_count); // shadow count - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_path); - Py_DECREF(py_tuple); - } - free(freep); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_XDECREF(py_path); - Py_DECREF(py_retlist); - if (freep != NULL) - free(freep); - return NULL; -} - - -PyObject* -psutil_proc_cpu_affinity_get(PyObject* self, PyObject* args) { - // Get process CPU affinity. - // Reference: - // http://sources.freebsd.org/RELENG_9/src/usr.bin/cpuset/cpuset.c - long pid; - int ret; - int i; - cpuset_t mask; - PyObject* py_retlist; - PyObject* py_cpu_num; - - if (!PyArg_ParseTuple(args, "i", &pid)) - return NULL; - ret = cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, pid, - sizeof(mask), &mask); - if (ret != 0) - return PyErr_SetFromErrno(PyExc_OSError); - - py_retlist = PyList_New(0); - if (py_retlist == NULL) - return NULL; - - for (i = 0; i < CPU_SETSIZE; i++) { - if (CPU_ISSET(i, &mask)) { - py_cpu_num = Py_BuildValue("i", i); - if (py_cpu_num == NULL) - goto error; - if (PyList_Append(py_retlist, py_cpu_num)) - goto error; - } - } - - return py_retlist; - -error: - Py_XDECREF(py_cpu_num); - Py_DECREF(py_retlist); - return NULL; -} - - -PyObject * -psutil_proc_cpu_affinity_set(PyObject *self, PyObject *args) { - // Set process CPU affinity. - // Reference: - // http://sources.freebsd.org/RELENG_9/src/usr.bin/cpuset/cpuset.c - long pid; - int i; - int seq_len; - int ret; - cpuset_t cpu_set; - PyObject *py_cpu_set; - PyObject *py_cpu_seq = NULL; - - if (!PyArg_ParseTuple(args, "lO", &pid, &py_cpu_set)) - return NULL; - - py_cpu_seq = PySequence_Fast(py_cpu_set, "expected a sequence or integer"); - if (!py_cpu_seq) - return NULL; - seq_len = PySequence_Fast_GET_SIZE(py_cpu_seq); - - // calculate the mask - CPU_ZERO(&cpu_set); - for (i = 0; i < seq_len; i++) { - PyObject *item = PySequence_Fast_GET_ITEM(py_cpu_seq, i); -#if PY_MAJOR_VERSION >= 3 - long value = PyLong_AsLong(item); -#else - long value = PyInt_AsLong(item); -#endif - if (value == -1 || PyErr_Occurred()) - goto error; - CPU_SET(value, &cpu_set); - } - - // set affinity - ret = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, pid, - sizeof(cpu_set), &cpu_set); - if (ret != 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - Py_DECREF(py_cpu_seq); - Py_RETURN_NONE; - -error: - if (py_cpu_seq != NULL) - Py_DECREF(py_cpu_seq); - return NULL; -} - - -PyObject * -psutil_cpu_stats(PyObject *self, PyObject *args) { - unsigned int v_soft; - unsigned int v_intr; - unsigned int v_syscall; - unsigned int v_trap; - unsigned int v_swtch; - size_t size = sizeof(v_soft); - - if (sysctlbyname("vm.stats.sys.v_soft", &v_soft, &size, NULL, 0)) { - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('vm.stats.sys.v_soft')"); - } - if (sysctlbyname("vm.stats.sys.v_intr", &v_intr, &size, NULL, 0)) { - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('vm.stats.sys.v_intr')"); - } - if (sysctlbyname("vm.stats.sys.v_syscall", &v_syscall, &size, NULL, 0)) { - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('vm.stats.sys.v_syscall')"); - } - if (sysctlbyname("vm.stats.sys.v_trap", &v_trap, &size, NULL, 0)) { - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('vm.stats.sys.v_trap')"); - } - if (sysctlbyname("vm.stats.sys.v_swtch", &v_swtch, &size, NULL, 0)) { - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('vm.stats.sys.v_swtch')"); - } - - return Py_BuildValue( - "IIIII", - v_swtch, // ctx switches - v_intr, // interrupts - v_soft, // software interrupts - v_syscall, // syscalls - v_trap // traps - ); -} - - -/* - * Return battery information. - */ -PyObject * -psutil_sensors_battery(PyObject *self, PyObject *args) { - int percent; - int minsleft; - int power_plugged; - size_t size = sizeof(percent); - - if (sysctlbyname("hw.acpi.battery.life", &percent, &size, NULL, 0)) - goto error; - if (sysctlbyname("hw.acpi.battery.time", &minsleft, &size, NULL, 0)) - goto error; - if (sysctlbyname("hw.acpi.acline", &power_plugged, &size, NULL, 0)) - goto error; - return Py_BuildValue("iii", percent, minsleft, power_plugged); - -error: - // see: https://github.com/giampaolo/psutil/issues/1074 - if (errno == ENOENT) - PyErr_SetString(PyExc_NotImplementedError, "no battery"); - else - PyErr_SetFromErrno(PyExc_OSError); - return NULL; -} - - -/* - * Return temperature information for a given CPU core number. - */ -PyObject * -psutil_sensors_cpu_temperature(PyObject *self, PyObject *args) { - int current; - int tjmax; - int core; - char sensor[26]; - size_t size = sizeof(current); - - if (! PyArg_ParseTuple(args, "i", &core)) - return NULL; - sprintf(sensor, "dev.cpu.%d.temperature", core); - if (sysctlbyname(sensor, ¤t, &size, NULL, 0)) - goto error; - current = DECIKELVIN_2_CELCIUS(current); - - // Return -273 in case of faliure. - sprintf(sensor, "dev.cpu.%d.coretemp.tjmax", core); - if (sysctlbyname(sensor, &tjmax, &size, NULL, 0)) - tjmax = 0; - tjmax = DECIKELVIN_2_CELCIUS(tjmax); - - return Py_BuildValue("ii", current, tjmax); - -error: - if (errno == ENOENT) - PyErr_SetString(PyExc_NotImplementedError, "no temperature sensors"); - else - PyErr_SetFromErrno(PyExc_OSError); - return NULL; -} - - -/* - * Return frequency information of a given CPU. - * As of Dec 2018 only CPU 0 appears to be supported and all other - * cores match the frequency of CPU 0. - */ -PyObject * -psutil_cpu_freq(PyObject *self, PyObject *args) { - int current; - int core; - char sensor[26]; - char available_freq_levels[1000]; - size_t size = sizeof(current); - - if (! PyArg_ParseTuple(args, "i", &core)) - return NULL; - // https://www.unix.com/man-page/FreeBSD/4/cpufreq/ - sprintf(sensor, "dev.cpu.%d.freq", core); - if (sysctlbyname(sensor, ¤t, &size, NULL, 0)) - goto error; - - size = sizeof(available_freq_levels); - // https://www.unix.com/man-page/FreeBSD/4/cpufreq/ - // In case of failure, an empty string is returned. - sprintf(sensor, "dev.cpu.%d.freq_levels", core); - sysctlbyname(sensor, &available_freq_levels, &size, NULL, 0); - - return Py_BuildValue("is", current, available_freq_levels); - -error: - if (errno == ENOENT) - PyErr_SetString(PyExc_NotImplementedError, "unable to read frequency"); - else - PyErr_SetFromErrno(PyExc_OSError); - return NULL; -} diff --git a/ddtrace/vendor/psutil/arch/freebsd/specific.h b/ddtrace/vendor/psutil/arch/freebsd/specific.h deleted file mode 100644 index 875c8166465..00000000000 --- a/ddtrace/vendor/psutil/arch/freebsd/specific.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, 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. - */ - -#include - -typedef struct kinfo_proc kinfo_proc; - -int psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount); -int psutil_kinfo_proc(const pid_t pid, struct kinfo_proc *proc); - -// -PyObject* psutil_cpu_count_phys(PyObject* self, PyObject* args); -PyObject* psutil_disk_io_counters(PyObject* self, PyObject* args); -PyObject* psutil_get_cmdline(long pid); -PyObject* psutil_per_cpu_times(PyObject* self, PyObject* args); -PyObject* psutil_proc_cpu_affinity_get(PyObject* self, PyObject* args); -PyObject* psutil_proc_cpu_affinity_set(PyObject* self, PyObject* args); -PyObject* psutil_proc_cwd(PyObject* self, PyObject* args); -PyObject* psutil_proc_exe(PyObject* self, PyObject* args); -PyObject* psutil_proc_memory_maps(PyObject* self, PyObject* args); -PyObject* psutil_proc_num_fds(PyObject* self, PyObject* args); -PyObject* psutil_proc_num_threads(PyObject* self, PyObject* args); -PyObject* psutil_proc_threads(PyObject* self, PyObject* args); -PyObject* psutil_swap_mem(PyObject* self, PyObject* args); -PyObject* psutil_virtual_mem(PyObject* self, PyObject* args); -PyObject* psutil_cpu_stats(PyObject* self, PyObject* args); -#if defined(PSUTIL_FREEBSD) -PyObject* psutil_sensors_battery(PyObject* self, PyObject* args); -PyObject* psutil_sensors_cpu_temperature(PyObject* self, PyObject* args); -PyObject* psutil_cpu_freq(PyObject* self, PyObject* args); -#endif diff --git a/ddtrace/vendor/psutil/arch/freebsd/sys_socks.c b/ddtrace/vendor/psutil/arch/freebsd/sys_socks.c deleted file mode 100644 index e0e2046be6d..00000000000 --- a/ddtrace/vendor/psutil/arch/freebsd/sys_socks.c +++ /dev/null @@ -1,362 +0,0 @@ -/* - * 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. - * - * Retrieves system-wide open socket connections. This is based off of - * sockstat utility source code: - * https://github.com/freebsd/freebsd/blob/master/usr.bin/sockstat/sockstat.c - */ - -#include -#include -#include -#include // for struct xsocket -#include -#include -#include -#include // for xinpcb struct -#include -#include -#include // for struct xtcpcb -#include // for inet_ntop() - -#include "../../_psutil_common.h" -#include "../../_psutil_posix.h" - -static struct xfile *psutil_xfiles; -static int psutil_nxfiles; - - -int -psutil_populate_xfiles() { - size_t len; - - if ((psutil_xfiles = malloc(len = sizeof *psutil_xfiles)) == NULL) { - PyErr_NoMemory(); - return 0; - } - while (sysctlbyname("kern.file", psutil_xfiles, &len, 0, 0) == -1) { - if (errno != ENOMEM) { - PyErr_SetFromErrno(0); - return 0; - } - len *= 2; - if ((psutil_xfiles = realloc(psutil_xfiles, len)) == NULL) { - PyErr_NoMemory(); - return 0; - } - } - if (len > 0 && psutil_xfiles->xf_size != sizeof *psutil_xfiles) { - PyErr_Format(PyExc_RuntimeError, "struct xfile size mismatch"); - return 0; - } - psutil_nxfiles = len / sizeof *psutil_xfiles; - return 1; -} - - -struct xfile * -psutil_get_file_from_sock(void *sock) { - struct xfile *xf; - int n; - - for (xf = psutil_xfiles, n = 0; n < psutil_nxfiles; ++n, ++xf) { - if (xf->xf_data == sock) - return xf; - } - return NULL; -} - - -// Reference: -// https://github.com/freebsd/freebsd/blob/master/usr.bin/sockstat/sockstat.c -int psutil_gather_inet(int proto, PyObject *py_retlist) { - struct xinpgen *xig, *exig; - struct xinpcb *xip; - struct xtcpcb *xtp; -#if __FreeBSD_version >= 1200026 - struct xinpcb *inp; -#else - struct inpcb *inp; -#endif - struct xsocket *so; - const char *varname = NULL; - size_t len, bufsize; - void *buf; - int retry; - int type; - - PyObject *py_tuple = NULL; - PyObject *py_laddr = NULL; - PyObject *py_raddr = NULL; - - switch (proto) { - case IPPROTO_TCP: - varname = "net.inet.tcp.pcblist"; - type = SOCK_STREAM; - break; - case IPPROTO_UDP: - varname = "net.inet.udp.pcblist"; - type = SOCK_DGRAM; - break; - } - - buf = NULL; - bufsize = 8192; - retry = 5; - do { - for (;;) { - buf = realloc(buf, bufsize); - if (buf == NULL) - continue; // XXX - len = bufsize; - if (sysctlbyname(varname, buf, &len, NULL, 0) == 0) - break; - if (errno != ENOMEM) { - PyErr_SetFromErrno(0); - goto error; - } - bufsize *= 2; - } - xig = (struct xinpgen *)buf; - exig = (struct xinpgen *)(void *)((char *)buf + len - sizeof *exig); - if (xig->xig_len != sizeof *xig || exig->xig_len != sizeof *exig) { - PyErr_Format(PyExc_RuntimeError, "struct xinpgen size mismatch"); - goto error; - } - } while (xig->xig_gen != exig->xig_gen && retry--); - - for (;;) { - struct xfile *xf; - int lport, rport, status, family; - - xig = (struct xinpgen *)(void *)((char *)xig + xig->xig_len); - if (xig >= exig) - break; - - switch (proto) { - case IPPROTO_TCP: - xtp = (struct xtcpcb *)xig; - if (xtp->xt_len != sizeof *xtp) { - PyErr_Format(PyExc_RuntimeError, - "struct xtcpcb size mismatch"); - goto error; - } - inp = &xtp->xt_inp; -#if __FreeBSD_version >= 1200026 - so = &inp->xi_socket; - status = xtp->t_state; -#else - so = &xtp->xt_socket; - status = xtp->xt_tp.t_state; -#endif - break; - case IPPROTO_UDP: - xip = (struct xinpcb *)xig; - if (xip->xi_len != sizeof *xip) { - PyErr_Format(PyExc_RuntimeError, - "struct xinpcb size mismatch"); - goto error; - } -#if __FreeBSD_version >= 1200026 - inp = xip; -#else - inp = &xip->xi_inp; -#endif - so = &xip->xi_socket; - status = PSUTIL_CONN_NONE; - break; - default: - PyErr_Format(PyExc_RuntimeError, "invalid proto"); - goto error; - } - - char lip[200], rip[200]; - - xf = psutil_get_file_from_sock(so->xso_so); - if (xf == NULL) - continue; - lport = ntohs(inp->inp_lport); - rport = ntohs(inp->inp_fport); - - if (inp->inp_vflag & INP_IPV4) { - family = AF_INET; - inet_ntop(AF_INET, &inp->inp_laddr.s_addr, lip, sizeof(lip)); - inet_ntop(AF_INET, &inp->inp_faddr.s_addr, rip, sizeof(rip)); - } - else if (inp->inp_vflag & INP_IPV6) { - family = AF_INET6; - inet_ntop(AF_INET6, &inp->in6p_laddr.s6_addr, lip, sizeof(lip)); - inet_ntop(AF_INET6, &inp->in6p_faddr.s6_addr, rip, sizeof(rip)); - } - - // construct python tuple/list - py_laddr = Py_BuildValue("(si)", lip, lport); - if (!py_laddr) - goto error; - if (rport != 0) - py_raddr = Py_BuildValue("(si)", rip, rport); - else - py_raddr = Py_BuildValue("()"); - if (!py_raddr) - goto error; - py_tuple = Py_BuildValue( - "(iiiNNii)", - xf->xf_fd, // fd - family, // family - type, // type - py_laddr, // laddr - py_raddr, // raddr - status, // status - xf->xf_pid); // pid - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_tuple); - } - - free(buf); - return 1; - -error: - Py_XDECREF(py_tuple); - Py_XDECREF(py_laddr); - Py_XDECREF(py_raddr); - free(buf); - return 0; -} - - -int psutil_gather_unix(int proto, PyObject *py_retlist) { - struct xunpgen *xug, *exug; - struct xunpcb *xup; - const char *varname = NULL; - const char *protoname = NULL; - size_t len; - size_t bufsize; - void *buf; - int retry; - struct sockaddr_un *sun; - char path[PATH_MAX]; - - PyObject *py_tuple = NULL; - PyObject *py_lpath = NULL; - - switch (proto) { - case SOCK_STREAM: - varname = "net.local.stream.pcblist"; - protoname = "stream"; - break; - case SOCK_DGRAM: - varname = "net.local.dgram.pcblist"; - protoname = "dgram"; - break; - } - - buf = NULL; - bufsize = 8192; - retry = 5; - - do { - for (;;) { - buf = realloc(buf, bufsize); - if (buf == NULL) { - PyErr_NoMemory(); - goto error; - } - len = bufsize; - if (sysctlbyname(varname, buf, &len, NULL, 0) == 0) - break; - if (errno != ENOMEM) { - PyErr_SetFromErrno(0); - goto error; - } - bufsize *= 2; - } - xug = (struct xunpgen *)buf; - exug = (struct xunpgen *)(void *) - ((char *)buf + len - sizeof *exug); - if (xug->xug_len != sizeof *xug || exug->xug_len != sizeof *exug) { - PyErr_Format(PyExc_RuntimeError, "struct xinpgen size mismatch"); - goto error; - } - } while (xug->xug_gen != exug->xug_gen && retry--); - - for (;;) { - struct xfile *xf; - - xug = (struct xunpgen *)(void *)((char *)xug + xug->xug_len); - if (xug >= exug) - break; - xup = (struct xunpcb *)xug; - if (xup->xu_len != sizeof *xup) - goto error; - - xf = psutil_get_file_from_sock(xup->xu_socket.xso_so); - if (xf == NULL) - continue; - - sun = (struct sockaddr_un *)&xup->xu_addr; - snprintf(path, sizeof(path), "%.*s", - (int)(sun->sun_len - (sizeof(*sun) - sizeof(sun->sun_path))), - sun->sun_path); - py_lpath = PyUnicode_DecodeFSDefault(path); - if (! py_lpath) - goto error; - - py_tuple = Py_BuildValue("(iiiOsii)", - xf->xf_fd, // fd - AF_UNIX, // family - proto, // type - py_lpath, // lpath - "", // rath - PSUTIL_CONN_NONE, // status - xf->xf_pid); // pid - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_lpath); - Py_DECREF(py_tuple); - } - - free(buf); - return 1; - -error: - Py_XDECREF(py_tuple); - Py_XDECREF(py_lpath); - free(buf); - return 0; -} - - -PyObject* -psutil_net_connections(PyObject* self, PyObject* args) { - // Return system-wide open connections. - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - if (psutil_populate_xfiles() != 1) - goto error; - if (psutil_gather_inet(IPPROTO_TCP, py_retlist) == 0) - goto error; - if (psutil_gather_inet(IPPROTO_UDP, py_retlist) == 0) - goto error; - if (psutil_gather_unix(SOCK_STREAM, py_retlist) == 0) - goto error; - if (psutil_gather_unix(SOCK_DGRAM, py_retlist) == 0) - goto error; - - free(psutil_xfiles); - return py_retlist; - -error: - Py_DECREF(py_retlist); - free(psutil_xfiles); - return NULL; -} diff --git a/ddtrace/vendor/psutil/arch/freebsd/sys_socks.h b/ddtrace/vendor/psutil/arch/freebsd/sys_socks.h deleted file mode 100644 index 75247926556..00000000000 --- a/ddtrace/vendor/psutil/arch/freebsd/sys_socks.h +++ /dev/null @@ -1,10 +0,0 @@ -/* - * 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. - */ - -#include - -PyObject* psutil_net_connections(PyObject* self, PyObject* args); diff --git a/ddtrace/vendor/psutil/arch/netbsd/socks.c b/ddtrace/vendor/psutil/arch/netbsd/socks.c deleted file mode 100644 index f370f094667..00000000000 --- a/ddtrace/vendor/psutil/arch/netbsd/socks.c +++ /dev/null @@ -1,447 +0,0 @@ -/* - * Copyright (c) 2009, Giampaolo Rodola'. - * Copyright (c) 2015, Ryo ONODERA. - * All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../../_psutil_common.h" -#include "../../_psutil_posix.h" - - -// address family filter -enum af_filter { - INET, - INET4, - INET6, - TCP, - TCP4, - TCP6, - UDP, - UDP4, - UDP6, - UNIX, - ALL, -}; - -// kinfo_file results -struct kif { - SLIST_ENTRY(kif) kifs; - struct kinfo_file *kif; -}; - -// kinfo_file results list -SLIST_HEAD(kifhead, kif) kihead = SLIST_HEAD_INITIALIZER(kihead); - - -// kinfo_pcb results -struct kpcb { - SLIST_ENTRY(kpcb) kpcbs; - struct kinfo_pcb *kpcb; -}; - -// kinfo_pcb results list -SLIST_HEAD(kpcbhead, kpcb) kpcbhead = SLIST_HEAD_INITIALIZER(kpcbhead); - -static void psutil_kiflist_init(void); -static void psutil_kiflist_clear(void); -static void psutil_kpcblist_init(void); -static void psutil_kpcblist_clear(void); -static int psutil_get_files(void); -static int psutil_get_sockets(const char *name); -static int psutil_get_info(int aff); - - -// Initialize kinfo_file results list. -static void -psutil_kiflist_init(void) { - SLIST_INIT(&kihead); - return; -} - - -// Clear kinfo_file results list. -static void -psutil_kiflist_clear(void) { - while (!SLIST_EMPTY(&kihead)) { - SLIST_REMOVE_HEAD(&kihead, kifs); - } - - return; -} - - -// Initialize kinof_pcb result list. -static void -psutil_kpcblist_init(void) { - SLIST_INIT(&kpcbhead); - return; -} - - -// Clear kinof_pcb result list. -static void -psutil_kpcblist_clear(void) { - while (!SLIST_EMPTY(&kpcbhead)) { - SLIST_REMOVE_HEAD(&kpcbhead, kpcbs); - } - - return; -} - - -// Get all open files including socket. -static int -psutil_get_files(void) { - size_t len; - size_t j; - int mib[6]; - char *buf; - off_t offset; - - mib[0] = CTL_KERN; - mib[1] = KERN_FILE2; - mib[2] = KERN_FILE_BYFILE; - mib[3] = 0; - mib[4] = sizeof(struct kinfo_file); - mib[5] = 0; - - if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - return -1; - } - - offset = len % sizeof(off_t); - mib[5] = len / sizeof(struct kinfo_file); - - if ((buf = malloc(len + offset)) == NULL) { - PyErr_NoMemory(); - return -1; - } - - if (sysctl(mib, 6, buf + offset, &len, NULL, 0) == -1) { - free(buf); - PyErr_SetFromErrno(PyExc_OSError); - return -1; - } - - len /= sizeof(struct kinfo_file); - struct kinfo_file *ki = (struct kinfo_file *)(buf + offset); - - for (j = 0; j < len; j++) { - struct kif *kif = malloc(sizeof(struct kif)); - kif->kif = &ki[j]; - SLIST_INSERT_HEAD(&kihead, kif, kifs); - } - - /* - // debug - struct kif *k; - SLIST_FOREACH(k, &kihead, kifs) { - printf("%d\n", k->kif->ki_pid); - } - */ - - return 0; -} - - -// Get open sockets. -static int -psutil_get_sockets(const char *name) { - size_t namelen; - int mib[8]; - struct kinfo_pcb *pcb; - size_t len; - size_t j; - - memset(mib, 0, sizeof(mib)); - - if (sysctlnametomib(name, mib, &namelen) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - return -1; - } - - if (sysctl(mib, __arraycount(mib), NULL, &len, NULL, 0) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - return -1; - } - - if ((pcb = malloc(len)) == NULL) { - PyErr_NoMemory(); - return -1; - } - memset(pcb, 0, len); - - mib[6] = sizeof(*pcb); - mib[7] = len / sizeof(*pcb); - - if (sysctl(mib, __arraycount(mib), pcb, &len, NULL, 0) == -1) { - free(pcb); - PyErr_SetFromErrno(PyExc_OSError); - return -1; - } - - len /= sizeof(struct kinfo_pcb); - struct kinfo_pcb *kp = (struct kinfo_pcb *)pcb; - - for (j = 0; j < len; j++) { - struct kpcb *kpcb = malloc(sizeof(struct kpcb)); - kpcb->kpcb = &kp[j]; - SLIST_INSERT_HEAD(&kpcbhead, kpcb, kpcbs); - } - - /* - // debug - struct kif *k; - struct kpcb *k; - SLIST_FOREACH(k, &kpcbhead, kpcbs) { - printf("ki_type: %d\n", k->kpcb->ki_type); - printf("ki_family: %d\n", k->kpcb->ki_family); - } - */ - - return 0; -} - - -// Collect open file and connections. -static int -psutil_get_info(int aff) { - switch (aff) { - case INET: - if (psutil_get_sockets("net.inet.tcp.pcblist") != 0) - return -1; - if (psutil_get_sockets("net.inet.udp.pcblist") != 0) - return -1; - if (psutil_get_sockets("net.inet6.tcp6.pcblist") != 0) - return -1; - if (psutil_get_sockets("net.inet6.udp6.pcblist") != 0) - return -1; - break; - case INET4: - if (psutil_get_sockets("net.inet.tcp.pcblist") != 0) - return -1; - if (psutil_get_sockets("net.inet.udp.pcblist") != 0) - return -1; - break; - case INET6: - if (psutil_get_sockets("net.inet6.tcp6.pcblist") != 0) - return -1; - if (psutil_get_sockets("net.inet6.udp6.pcblist") != 0) - return -1; - break; - case TCP: - if (psutil_get_sockets("net.inet.tcp.pcblist") != 0) - return -1; - if (psutil_get_sockets("net.inet6.tcp6.pcblist") != 0) - return -1; - break; - case TCP4: - if (psutil_get_sockets("net.inet.tcp.pcblist") != 0) - return -1; - break; - case TCP6: - if (psutil_get_sockets("net.inet6.tcp6.pcblist") != 0) - return -1; - break; - case UDP: - if (psutil_get_sockets("net.inet.udp.pcblist") != 0) - return -1; - if (psutil_get_sockets("net.inet6.udp6.pcblist") != 0) - return -1; - break; - case UDP4: - if (psutil_get_sockets("net.inet.udp.pcblist") != 0) - return -1; - break; - case UDP6: - if (psutil_get_sockets("net.inet6.udp6.pcblist") != 0) - return -1; - break; - case UNIX: - if (psutil_get_sockets("net.local.stream.pcblist") != 0) - return -1; - if (psutil_get_sockets("net.local.seqpacket.pcblist") != 0) - return -1; - if (psutil_get_sockets("net.local.dgram.pcblist") != 0) - return -1; - break; - case ALL: - if (psutil_get_sockets("net.inet.tcp.pcblist") != 0) - return -1; - if (psutil_get_sockets("net.inet.udp.pcblist") != 0) - return -1; - if (psutil_get_sockets("net.inet6.tcp6.pcblist") != 0) - return -1; - if (psutil_get_sockets("net.inet6.udp6.pcblist") != 0) - return -1; - if (psutil_get_sockets("net.local.stream.pcblist") != 0) - return -1; - if (psutil_get_sockets("net.local.seqpacket.pcblist") != 0) - return -1; - if (psutil_get_sockets("net.local.dgram.pcblist") != 0) - return -1; - break; - } - - return 0; -} - - -/* - * Return system-wide connections (unless a pid != -1 is passed). - */ -PyObject * -psutil_net_connections(PyObject *self, PyObject *args) { - char laddr[PATH_MAX]; - char raddr[PATH_MAX]; - int32_t lport; - int32_t rport; - int32_t status; - pid_t pid; - PyObject *py_tuple = NULL; - PyObject *py_laddr = NULL; - PyObject *py_raddr = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - psutil_kiflist_init(); - psutil_kpcblist_init(); - if (psutil_get_files() != 0) - goto error; - if (psutil_get_info(ALL) != 0) - goto error; - - struct kif *k; - SLIST_FOREACH(k, &kihead, kifs) { - struct kpcb *kp; - if ((pid != -1) && (k->kif->ki_pid != (unsigned int)pid)) - continue; - SLIST_FOREACH(kp, &kpcbhead, kpcbs) { - if (k->kif->ki_fdata != kp->kpcb->ki_sockaddr) - continue; - - // IPv4 or IPv6 - if ((kp->kpcb->ki_family == AF_INET) || - (kp->kpcb->ki_family == AF_INET6)) { - - if (kp->kpcb->ki_family == AF_INET) { - // IPv4 - struct sockaddr_in *sin_src = - (struct sockaddr_in *)&kp->kpcb->ki_src; - struct sockaddr_in *sin_dst = - (struct sockaddr_in *)&kp->kpcb->ki_dst; - // source addr and port - inet_ntop(AF_INET, &sin_src->sin_addr, laddr, - sizeof(laddr)); - lport = ntohs(sin_src->sin_port); - // remote addr and port - inet_ntop(AF_INET, &sin_dst->sin_addr, raddr, - sizeof(raddr)); - rport = ntohs(sin_dst->sin_port); - } - else { - // IPv6 - struct sockaddr_in6 *sin6_src = - (struct sockaddr_in6 *)&kp->kpcb->ki_src; - struct sockaddr_in6 *sin6_dst = - (struct sockaddr_in6 *)&kp->kpcb->ki_dst; - // local addr and port - inet_ntop(AF_INET6, &sin6_src->sin6_addr, laddr, - sizeof(laddr)); - lport = ntohs(sin6_src->sin6_port); - // remote addr and port - inet_ntop(AF_INET6, &sin6_dst->sin6_addr, raddr, - sizeof(raddr)); - rport = ntohs(sin6_dst->sin6_port); - } - - // status - if (kp->kpcb->ki_type == SOCK_STREAM) - status = kp->kpcb->ki_tstate; - else - status = PSUTIL_CONN_NONE; - - // build addr tuple - py_laddr = Py_BuildValue("(si)", laddr, lport); - if (! py_laddr) - goto error; - if (rport != 0) - py_raddr = Py_BuildValue("(si)", raddr, rport); - else - py_raddr = Py_BuildValue("()"); - if (! py_raddr) - goto error; - } - else if (kp->kpcb->ki_family == AF_UNIX) { - // UNIX sockets - struct sockaddr_un *sun_src = - (struct sockaddr_un *)&kp->kpcb->ki_src; - struct sockaddr_un *sun_dst = - (struct sockaddr_un *)&kp->kpcb->ki_dst; - strcpy(laddr, sun_src->sun_path); - strcpy(raddr, sun_dst->sun_path); - status = PSUTIL_CONN_NONE; - py_laddr = PyUnicode_DecodeFSDefault(laddr); - if (! py_laddr) - goto error; - py_raddr = PyUnicode_DecodeFSDefault(raddr); - if (! py_raddr) - goto error; - } - else { - continue; - } - - // append tuple to list - py_tuple = Py_BuildValue( - "(iiiOOii)", - k->kif->ki_fd, - kp->kpcb->ki_family, - kp->kpcb->ki_type, - py_laddr, - py_raddr, - status, - k->kif->ki_pid); - if (! py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_laddr); - Py_DECREF(py_raddr); - Py_DECREF(py_tuple); - } - } - - psutil_kiflist_clear(); - psutil_kpcblist_clear(); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_XDECREF(py_laddr); - Py_XDECREF(py_raddr); - return 0; -} diff --git a/ddtrace/vendor/psutil/arch/netbsd/socks.h b/ddtrace/vendor/psutil/arch/netbsd/socks.h deleted file mode 100644 index 9e6a97c0a8c..00000000000 --- a/ddtrace/vendor/psutil/arch/netbsd/socks.h +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright (c) 2009, Giampaolo Rodola'. - * Copyright (c) 2015, Ryo ONODERA. - * All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -PyObject *psutil_proc_connections(PyObject *, PyObject *); -PyObject *psutil_net_connections(PyObject *, PyObject *); diff --git a/ddtrace/vendor/psutil/arch/netbsd/specific.c b/ddtrace/vendor/psutil/arch/netbsd/specific.c deleted file mode 100644 index 25adffcd3bf..00000000000 --- a/ddtrace/vendor/psutil/arch/netbsd/specific.c +++ /dev/null @@ -1,684 +0,0 @@ -/* - * Copyright (c) 2009, Giampaolo Rodola', Landry Breuil. - * All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Platform-specific module methods for NetBSD. - */ - -#if defined(PSUTIL_NETBSD) - #define _KMEMUSER -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include // for swap_mem -#include -#include -// connection stuff -#include // for NI_MAXHOST -#include -#include // for CPUSTATES & CP_* -#define _KERNEL // for DTYPE_* -#include -#undef _KERNEL -#include // struct diskstats -#include -#include - -#include "specific.h" -#include "../../_psutil_common.h" -#include "../../_psutil_posix.h" - -#define PSUTIL_KPT2DOUBLE(t) (t ## _sec + t ## _usec / 1000000.0) -#define PSUTIL_TV2DOUBLE(t) ((t).tv_sec + (t).tv_usec / 1000000.0) - - -// ============================================================================ -// Utility functions -// ============================================================================ - - -int -psutil_kinfo_proc(pid_t pid, kinfo_proc *proc) { - // Fills a kinfo_proc struct based on process pid. - int ret; - int mib[6]; - size_t size = sizeof(kinfo_proc); - - mib[0] = CTL_KERN; - mib[1] = KERN_PROC2; - mib[2] = KERN_PROC_PID; - mib[3] = pid; - mib[4] = size; - mib[5] = 1; - - ret = sysctl((int*)mib, 6, proc, &size, NULL, 0); - if (ret == -1) { - PyErr_SetFromErrno(PyExc_OSError); - return -1; - } - // sysctl stores 0 in the size if we can't find the process information. - if (size == 0) { - NoSuchProcess(""); - return -1; - } - return 0; -} - - -struct kinfo_file * -kinfo_getfile(pid_t pid, int* cnt) { - // Mimic's FreeBSD kinfo_file call, taking a pid and a ptr to an - // int as arg and returns an array with cnt struct kinfo_file. - int mib[6]; - size_t len; - struct kinfo_file* kf; - mib[0] = CTL_KERN; - mib[1] = KERN_FILE2; - mib[2] = KERN_FILE_BYPID; - mib[3] = (int) pid; - mib[4] = sizeof(struct kinfo_file); - mib[5] = 0; - - // get the size of what would be returned - if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - if ((kf = malloc(len)) == NULL) { - PyErr_NoMemory(); - return NULL; - } - mib[5] = (int)(len / sizeof(struct kinfo_file)); - if (sysctl(mib, 6, kf, &len, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - *cnt = (int)(len / sizeof(struct kinfo_file)); - return kf; -} - -PyObject * -psutil_proc_cwd(PyObject *self, PyObject *args) { - long pid; - - char path[MAXPATHLEN]; - size_t pathlen = sizeof path; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - -#ifdef KERN_PROC_CWD - int name[] = { CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_CWD}; - if (sysctl(name, 4, path, &pathlen, NULL, 0) != 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } -#else - char *buf; - if (asprintf(&buf, "/proc/%d/cwd", (int)pid) < 0) { - PyErr_NoMemory(); - return NULL; - } - - ssize_t len = readlink(buf, path, sizeof(path) - 1); - free(buf); - if (len == -1) { - if (errno == ENOENT) - NoSuchProcess(""); - else - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - path[len] = '\0'; -#endif - - return PyUnicode_DecodeFSDefault(path); -} - - -// XXX: This is no longer used as per -// https://github.com/giampaolo/psutil/pull/557#issuecomment-171912820 -// Current implementation uses /proc instead. -// Left here just in case. -/* -PyObject * -psutil_proc_exe(PyObject *self, PyObject *args) { -#if __NetBSD_Version__ >= 799000000 - pid_t pid; - char pathname[MAXPATHLEN]; - int error; - int mib[4]; - int ret; - size_t size; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (pid == 0) { - // else returns ENOENT - return Py_BuildValue("s", ""); - } - - mib[0] = CTL_KERN; - mib[1] = KERN_PROC_ARGS; - mib[2] = pid; - mib[3] = KERN_PROC_PATHNAME; - - size = sizeof(pathname); - error = sysctl(mib, 4, NULL, &size, NULL, 0); - if (error == -1) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - error = sysctl(mib, 4, pathname, &size, NULL, 0); - if (error == -1) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - if (size == 0 || strlen(pathname) == 0) { - ret = psutil_pid_exists(pid); - if (ret == -1) - return NULL; - else if (ret == 0) - return NoSuchProcess(""); - else - strcpy(pathname, ""); - } - - return PyUnicode_DecodeFSDefault(pathname); -#else - return Py_BuildValue("s", ""); -#endif -} -*/ - -PyObject * -psutil_proc_num_threads(PyObject *self, PyObject *args) { - // Return number of threads used by process as a Python integer. - long pid; - kinfo_proc kp; - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (psutil_kinfo_proc(pid, &kp) == -1) - return NULL; - return Py_BuildValue("l", (long)kp.p_nlwps); -} - -PyObject * -psutil_proc_threads(PyObject *self, PyObject *args) { - pid_t pid; - int mib[5]; - int i, nlwps; - ssize_t st; - size_t size; - struct kinfo_lwp *kl = NULL; - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - - if (py_retlist == NULL) - return NULL; - if (! PyArg_ParseTuple(args, "l", &pid)) - goto error; - - mib[0] = CTL_KERN; - mib[1] = KERN_LWP; - mib[2] = pid; - mib[3] = sizeof(struct kinfo_lwp); - mib[4] = 0; - - st = sysctl(mib, 5, NULL, &size, NULL, 0); - if (st == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - if (size == 0) { - NoSuchProcess(""); - goto error; - } - - mib[4] = size / sizeof(size_t); - kl = malloc(size); - if (kl == NULL) { - PyErr_NoMemory(); - goto error; - } - - st = sysctl(mib, 5, kl, &size, NULL, 0); - if (st == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - if (size == 0) { - NoSuchProcess(""); - goto error; - } - - nlwps = (int)(size / sizeof(struct kinfo_lwp)); - for (i = 0; i < nlwps; i++) { - py_tuple = Py_BuildValue("idd", - (&kl[i])->l_lid, - PSUTIL_KPT2DOUBLE((&kl[i])->l_rtime), - PSUTIL_KPT2DOUBLE((&kl[i])->l_rtime)); - if (py_tuple == NULL) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_tuple); - } - free(kl); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (kl != NULL) - free(kl); - return NULL; -} - - -// ============================================================================ -// APIS -// ============================================================================ - -int -psutil_get_proc_list(kinfo_proc **procList, size_t *procCount) { - // Returns a list of all BSD processes on the system. This routine - // allocates the list and puts it in *procList and a count of the - // number of entries in *procCount. You are responsible for freeing - // this list (use "free" from System framework). - // On success, the function returns 0. - // On error, the function returns a BSD errno value. - kinfo_proc *result; - // Declaring name as const requires us to cast it when passing it to - // sysctl because the prototype doesn't include the const modifier. - char errbuf[_POSIX2_LINE_MAX]; - int cnt; - kvm_t *kd; - - assert( procList != NULL); - assert(*procList == NULL); - assert(procCount != NULL); - - kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf); - - if (kd == NULL) { - PyErr_Format( - PyExc_RuntimeError, "kvm_openfiles() syscall failed: %s", errbuf); - return errno; - } - - result = kvm_getproc2(kd, KERN_PROC_ALL, 0, sizeof(kinfo_proc), &cnt); - if (result == NULL) { - PyErr_Format(PyExc_RuntimeError, "kvm_getproc2() syscall failed"); - kvm_close(kd); - return errno; - } - - *procCount = (size_t)cnt; - - size_t mlen = cnt * sizeof(kinfo_proc); - - if ((*procList = malloc(mlen)) == NULL) { - PyErr_NoMemory(); - kvm_close(kd); - return errno; - } - - memcpy(*procList, result, mlen); - assert(*procList != NULL); - kvm_close(kd); - - return 0; -} - - -char * -psutil_get_cmd_args(pid_t pid, size_t *argsize) { - int mib[4]; - int st; - size_t len; - char *procargs; - - mib[0] = CTL_KERN; - mib[1] = KERN_PROC_ARGS; - mib[2] = pid; - mib[3] = KERN_PROC_ARGV; - len = 0; - - st = sysctl(mib, __arraycount(mib), NULL, &len, NULL, 0); - if (st == -1) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - procargs = (char *)malloc(len); - if (procargs == NULL) { - PyErr_NoMemory(); - return NULL; - } - st = sysctl(mib, __arraycount(mib), procargs, &len, NULL, 0); - if (st == -1) { - free(procargs); - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - *argsize = len; - return procargs; -} - - -// Return the command line as a python list object. -// XXX - most of the times sysctl() returns a truncated string. -// Also /proc/pid/cmdline behaves the same so it looks like this -// is a kernel bug. -PyObject * -psutil_get_cmdline(pid_t pid) { - char *argstr = NULL; - size_t pos = 0; - size_t argsize = 0; - PyObject *py_arg = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - if (pid == 0) - return py_retlist; - - argstr = psutil_get_cmd_args(pid, &argsize); - if (argstr == NULL) - goto error; - - // args are returned as a flattened string with \0 separators between - // arguments add each string to the list then step forward to the next - // separator - if (argsize > 0) { - while (pos < argsize) { - py_arg = PyUnicode_DecodeFSDefault(&argstr[pos]); - if (!py_arg) - goto error; - if (PyList_Append(py_retlist, py_arg)) - goto error; - Py_DECREF(py_arg); - pos = pos + strlen(&argstr[pos]) + 1; - } - } - - free(argstr); - return py_retlist; - -error: - Py_XDECREF(py_arg); - Py_DECREF(py_retlist); - if (argstr != NULL) - free(argstr); - return NULL; -} - - -/* - * Virtual memory stats, taken from: - * https://github.com/satterly/zabbix-stats/blob/master/src/libs/zbxsysinfo/ - * netbsd/memory.c - */ -PyObject * -psutil_virtual_mem(PyObject *self, PyObject *args) { - size_t size; - struct uvmexp_sysctl uv; - int mib[] = {CTL_VM, VM_UVMEXP2}; - long pagesize = getpagesize(); - - size = sizeof(uv); - if (sysctl(mib, 2, &uv, &size, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - return Py_BuildValue("KKKKKKKK", - (unsigned long long) uv.npages << uv.pageshift, // total - (unsigned long long) uv.free << uv.pageshift, // free - (unsigned long long) uv.active << uv.pageshift, // active - (unsigned long long) uv.inactive << uv.pageshift, // inactive - (unsigned long long) uv.wired << uv.pageshift, // wired - (unsigned long long) uv.filepages + uv.execpages * pagesize, // cached - // These are determined from /proc/meminfo in Python. - (unsigned long long) 0, // buffers - (unsigned long long) 0 // shared - ); -} - - -PyObject * -psutil_swap_mem(PyObject *self, PyObject *args) { - uint64_t swap_total, swap_free; - struct swapent *swdev; - int nswap, i; - - nswap = swapctl(SWAP_NSWAP, 0, 0); - if (nswap == 0) { - // This means there's no swap partition. - return Py_BuildValue("(iiiii)", 0, 0, 0, 0, 0); - } - - swdev = calloc(nswap, sizeof(*swdev)); - if (swdev == NULL) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - if (swapctl(SWAP_STATS, swdev, nswap) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - // Total things up. - swap_total = swap_free = 0; - for (i = 0; i < nswap; i++) { - if (swdev[i].se_flags & SWF_ENABLE) { - swap_total += swdev[i].se_nblks * DEV_BSIZE; - swap_free += (swdev[i].se_nblks - swdev[i].se_inuse) * DEV_BSIZE; - } - } - free(swdev); - - // Get swap in/out - unsigned int total; - size_t size = sizeof(total); - struct uvmexp_sysctl uv; - int mib[] = {CTL_VM, VM_UVMEXP2}; - long pagesize = getpagesize(); - size = sizeof(uv); - if (sysctl(mib, 2, &uv, &size, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - return Py_BuildValue("(LLLll)", - swap_total, - (swap_total - swap_free), - swap_free, - (long) uv.pgswapin * pagesize, // swap in - (long) uv.pgswapout * pagesize); // swap out - -error: - free(swdev); - return NULL; -} - - -PyObject * -psutil_proc_num_fds(PyObject *self, PyObject *args) { - long pid; - int cnt; - - struct kinfo_file *freep; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - errno = 0; - freep = kinfo_getfile(pid, &cnt); - if (freep == NULL) { - psutil_raise_for_pid(pid, "kinfo_getfile()"); - return NULL; - } - free(freep); - - return Py_BuildValue("i", cnt); -} - - -PyObject * -psutil_per_cpu_times(PyObject *self, PyObject *args) { - // XXX: why static? - int mib[3]; - int ncpu; - size_t len; - size_t size; - int i; - PyObject *py_cputime = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - // retrieve the number of cpus - mib[0] = CTL_HW; - mib[1] = HW_NCPU; - len = sizeof(ncpu); - if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - uint64_t cpu_time[CPUSTATES]; - - for (i = 0; i < ncpu; i++) { - // per-cpu info - mib[0] = CTL_KERN; - mib[1] = KERN_CP_TIME; - mib[2] = i; - size = sizeof(cpu_time); - if (sysctl(mib, 3, &cpu_time, &size, NULL, 0) == -1) { - warn("failed to get kern.cptime2"); - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - py_cputime = Py_BuildValue( - "(ddddd)", - (double)cpu_time[CP_USER] / CLOCKS_PER_SEC, - (double)cpu_time[CP_NICE] / CLOCKS_PER_SEC, - (double)cpu_time[CP_SYS] / CLOCKS_PER_SEC, - (double)cpu_time[CP_IDLE] / CLOCKS_PER_SEC, - (double)cpu_time[CP_INTR] / CLOCKS_PER_SEC); - if (!py_cputime) - goto error; - if (PyList_Append(py_retlist, py_cputime)) - goto error; - Py_DECREF(py_cputime); - } - - return py_retlist; - -error: - Py_XDECREF(py_cputime); - Py_DECREF(py_retlist); - return NULL; -} - - -PyObject * -psutil_disk_io_counters(PyObject *self, PyObject *args) { - int i, dk_ndrive, mib[3]; - size_t len; - struct io_sysctl *stats = NULL; - PyObject *py_disk_info = NULL; - PyObject *py_retdict = PyDict_New(); - - if (py_retdict == NULL) - return NULL; - mib[0] = CTL_HW; - mib[1] = HW_IOSTATS; - mib[2] = sizeof(struct io_sysctl); - len = 0; - if (sysctl(mib, 3, NULL, &len, NULL, 0) < 0) { - warn("can't get HW_IOSTATS"); - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - dk_ndrive = (int)(len / sizeof(struct io_sysctl)); - - stats = malloc(len); - if (stats == NULL) { - PyErr_NoMemory(); - goto error; - } - if (sysctl(mib, 3, stats, &len, NULL, 0) < 0 ) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (i = 0; i < dk_ndrive; i++) { - py_disk_info = Py_BuildValue( - "(KKKK)", - stats[i].rxfer, - stats[i].wxfer, - stats[i].rbytes, - stats[i].wbytes - ); - if (!py_disk_info) - goto error; - if (PyDict_SetItemString(py_retdict, stats[i].name, py_disk_info)) - goto error; - Py_DECREF(py_disk_info); - } - - free(stats); - return py_retdict; - -error: - Py_XDECREF(py_disk_info); - Py_DECREF(py_retdict); - if (stats != NULL) - free(stats); - return NULL; -} - - -PyObject * -psutil_cpu_stats(PyObject *self, PyObject *args) { - size_t size; - struct uvmexp_sysctl uv; - int uvmexp_mib[] = {CTL_VM, VM_UVMEXP2}; - - size = sizeof(uv); - if (sysctl(uvmexp_mib, 2, &uv, &size, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - return Py_BuildValue( - "IIIIIII", - uv.swtch, // ctx switches - uv.intrs, // interrupts - XXX always 0, will be determined via /proc - uv.softs, // soft interrupts - uv.syscalls, // syscalls - XXX always 0 - uv.traps, // traps - uv.faults, // faults - uv.forks // forks - ); -} diff --git a/ddtrace/vendor/psutil/arch/netbsd/specific.h b/ddtrace/vendor/psutil/arch/netbsd/specific.h deleted file mode 100644 index 391ed164a4c..00000000000 --- a/ddtrace/vendor/psutil/arch/netbsd/specific.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2009, Giampaolo Rodola', Landry Breuil. - * All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include - -typedef struct kinfo_proc2 kinfo_proc; - -int psutil_kinfo_proc(pid_t pid, kinfo_proc *proc); -struct kinfo_file * kinfo_getfile(pid_t pid, int* cnt); -int psutil_get_proc_list(kinfo_proc **procList, size_t *procCount); -char *psutil_get_cmd_args(pid_t pid, size_t *argsize); - -// -PyObject *psutil_get_cmdline(pid_t pid); -PyObject *psutil_proc_threads(PyObject *self, PyObject *args); -PyObject *psutil_virtual_mem(PyObject *self, PyObject *args); -PyObject *psutil_swap_mem(PyObject *self, PyObject *args); -PyObject *psutil_proc_num_fds(PyObject *self, PyObject *args); -PyObject *psutil_proc_connections(PyObject *self, PyObject *args); -PyObject *psutil_per_cpu_times(PyObject *self, PyObject *args); -PyObject* psutil_disk_io_counters(PyObject* self, PyObject* args); -PyObject* psutil_proc_exe(PyObject* self, PyObject* args); -PyObject* psutil_proc_num_threads(PyObject* self, PyObject* args); -PyObject* psutil_cpu_stats(PyObject* self, PyObject* args); -PyObject *psutil_proc_cwd(PyObject *self, PyObject *args); diff --git a/ddtrace/vendor/psutil/arch/openbsd/specific.c b/ddtrace/vendor/psutil/arch/openbsd/specific.c deleted file mode 100644 index 33ebdeecbaf..00000000000 --- a/ddtrace/vendor/psutil/arch/openbsd/specific.c +++ /dev/null @@ -1,791 +0,0 @@ -/* - * Copyright (c) 2009, Giampaolo Rodola', Landry Breuil. - * All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Platform-specific module methods for OpenBSD. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include // for VFS_* -#include // for swap_mem -#include // for vmtotal struct -#include -#include -// connection stuff -#include // for NI_MAXHOST -#include -#include // for CPUSTATES & CP_* -#define _KERNEL // for DTYPE_* -#include -#undef _KERNEL -#include // struct diskstats -#include // for inet_ntoa() -#include // for warn() & err() - -#include "../../_psutil_common.h" -#include "../../_psutil_posix.h" - -#define PSUTIL_KPT2DOUBLE(t) (t ## _sec + t ## _usec / 1000000.0) -// #define PSUTIL_TV2DOUBLE(t) ((t).tv_sec + (t).tv_usec / 1000000.0) - - -// ============================================================================ -// Utility functions -// ============================================================================ - -int -psutil_kinfo_proc(pid_t pid, struct kinfo_proc *proc) { - // Fills a kinfo_proc struct based on process pid. - int ret; - int mib[6]; - size_t size = sizeof(struct kinfo_proc); - - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID; - mib[3] = pid; - mib[4] = size; - mib[5] = 1; - - ret = sysctl((int*)mib, 6, proc, &size, NULL, 0); - if (ret == -1) { - PyErr_SetFromErrno(PyExc_OSError); - return -1; - } - // sysctl stores 0 in the size if we can't find the process information. - if (size == 0) { - NoSuchProcess(""); - return -1; - } - return 0; -} - - -struct kinfo_file * -kinfo_getfile(long pid, int* cnt) { - // Mimic's FreeBSD kinfo_file call, taking a pid and a ptr to an - // int as arg and returns an array with cnt struct kinfo_file. - int mib[6]; - size_t len; - struct kinfo_file* kf; - mib[0] = CTL_KERN; - mib[1] = KERN_FILE; - mib[2] = KERN_FILE_BYPID; - mib[3] = (int) pid; - mib[4] = sizeof(struct kinfo_file); - mib[5] = 0; - - /* get the size of what would be returned */ - if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - if ((kf = malloc(len)) == NULL) { - PyErr_NoMemory(); - return NULL; - } - mib[5] = (int)(len / sizeof(struct kinfo_file)); - if (sysctl(mib, 6, kf, &len, NULL, 0) < 0) { - free(kf); - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - *cnt = (int)(len / sizeof(struct kinfo_file)); - return kf; -} - - -// ============================================================================ -// APIS -// ============================================================================ - -int -psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount) { - // Returns a list of all BSD processes on the system. This routine - // allocates the list and puts it in *procList and a count of the - // number of entries in *procCount. You are responsible for freeing - // this list (use "free" from System framework). - // On success, the function returns 0. - // On error, the function returns a BSD errno value. - struct kinfo_proc *result; - // Declaring name as const requires us to cast it when passing it to - // sysctl because the prototype doesn't include the const modifier. - char errbuf[_POSIX2_LINE_MAX]; - int cnt; - kvm_t *kd; - - assert(procList != NULL); - assert(*procList == NULL); - assert(procCount != NULL); - - kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf); - - if (kd == NULL) { - return errno; - } - - result = kvm_getprocs(kd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), &cnt); - if (result == NULL) { - kvm_close(kd); - err(1, NULL); - return errno; - } - - *procCount = (size_t)cnt; - - size_t mlen = cnt * sizeof(struct kinfo_proc); - - if ((*procList = malloc(mlen)) == NULL) { - kvm_close(kd); - err(1, NULL); - return errno; - } - - memcpy(*procList, result, mlen); - assert(*procList != NULL); - kvm_close(kd); - - return 0; -} - - -char ** -_psutil_get_argv(long pid) { - static char **argv; - int argv_mib[] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_ARGV}; - size_t argv_size = 128; - // Loop and reallocate until we have enough space to fit argv. - for (;; argv_size *= 2) { - if (argv_size >= 8192) { - PyErr_SetString(PyExc_RuntimeError, - "can't allocate enough space for KERN_PROC_ARGV"); - return NULL; - } - if ((argv = realloc(argv, argv_size)) == NULL) - continue; - if (sysctl(argv_mib, 4, argv, &argv_size, NULL, 0) == 0) - return argv; - if (errno == ENOMEM) - continue; - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } -} - - -// returns the command line as a python list object -PyObject * -psutil_get_cmdline(long pid) { - static char **argv; - char **p; - PyObject *py_arg = NULL; - PyObject *py_retlist = Py_BuildValue("[]"); - - if (!py_retlist) - return NULL; - if (pid < 0) - return py_retlist; - - if ((argv = _psutil_get_argv(pid)) == NULL) - goto error; - - for (p = argv; *p != NULL; p++) { - py_arg = PyUnicode_DecodeFSDefault(*p); - if (!py_arg) - goto error; - if (PyList_Append(py_retlist, py_arg)) - goto error; - Py_DECREF(py_arg); - } - return py_retlist; - -error: - Py_XDECREF(py_arg); - Py_DECREF(py_retlist); - return NULL; -} - - -PyObject * -psutil_proc_threads(PyObject *self, PyObject *args) { - // OpenBSD reference: - // https://github.com/janmojzis/pstree/blob/master/proc_kvm.c - // Note: this requires root access, else it will fail trying - // to access /dev/kmem. - long pid; - kvm_t *kd = NULL; - int nentries, i; - char errbuf[4096]; - struct kinfo_proc *kp; - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - - if (py_retlist == NULL) - return NULL; - if (! PyArg_ParseTuple(args, "l", &pid)) - goto error; - - kd = kvm_openfiles(0, 0, 0, O_RDONLY, errbuf); - if (! kd) { - if (strstr(errbuf, "Permission denied") != NULL) - AccessDenied(""); - else - PyErr_Format(PyExc_RuntimeError, "kvm_openfiles() syscall failed"); - goto error; - } - - kp = kvm_getprocs( - kd, KERN_PROC_PID | KERN_PROC_SHOW_THREADS | KERN_PROC_KTHREAD, pid, - sizeof(*kp), &nentries); - if (! kp) { - if (strstr(errbuf, "Permission denied") != NULL) - AccessDenied(""); - else - PyErr_Format(PyExc_RuntimeError, "kvm_getprocs() syscall failed"); - goto error; - } - - for (i = 0; i < nentries; i++) { - if (kp[i].p_tid < 0) - continue; - if (kp[i].p_pid == pid) { - py_tuple = Py_BuildValue( - "Idd", - kp[i].p_tid, - PSUTIL_KPT2DOUBLE(kp[i].p_uutime), - PSUTIL_KPT2DOUBLE(kp[i].p_ustime)); - if (py_tuple == NULL) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_tuple); - } - } - - kvm_close(kd); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (kd != NULL) - kvm_close(kd); - return NULL; -} - - -PyObject * -psutil_virtual_mem(PyObject *self, PyObject *args) { - int64_t total_physmem; - int uvmexp_mib[] = {CTL_VM, VM_UVMEXP}; - int bcstats_mib[] = {CTL_VFS, VFS_GENERIC, VFS_BCACHESTAT}; - int physmem_mib[] = {CTL_HW, HW_PHYSMEM64}; - int vmmeter_mib[] = {CTL_VM, VM_METER}; - size_t size; - struct uvmexp uvmexp; - struct bcachestats bcstats; - struct vmtotal vmdata; - long pagesize = getpagesize(); - - size = sizeof(total_physmem); - if (sysctl(physmem_mib, 2, &total_physmem, &size, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - size = sizeof(uvmexp); - if (sysctl(uvmexp_mib, 2, &uvmexp, &size, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - size = sizeof(bcstats); - if (sysctl(bcstats_mib, 3, &bcstats, &size, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - size = sizeof(vmdata); - if (sysctl(vmmeter_mib, 2, &vmdata, &size, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - return Py_BuildValue("KKKKKKKK", - // Note: many programs calculate total memory as - // "uvmexp.npages * pagesize" but this is incorrect and does not - // match "sysctl | grep hw.physmem". - (unsigned long long) total_physmem, - (unsigned long long) uvmexp.free * pagesize, - (unsigned long long) uvmexp.active * pagesize, - (unsigned long long) uvmexp.inactive * pagesize, - (unsigned long long) uvmexp.wired * pagesize, - // this is how "top" determines it - (unsigned long long) bcstats.numbufpages * pagesize, // cached - (unsigned long long) 0, // buffers - (unsigned long long) vmdata.t_vmshr + vmdata.t_rmshr // shared - ); -} - - -PyObject * -psutil_swap_mem(PyObject *self, PyObject *args) { - uint64_t swap_total, swap_free; - struct swapent *swdev; - int nswap, i; - - if ((nswap = swapctl(SWAP_NSWAP, 0, 0)) == 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - if ((swdev = calloc(nswap, sizeof(*swdev))) == NULL) { - PyErr_NoMemory(); - return NULL; - } - - if (swapctl(SWAP_STATS, swdev, nswap) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - // Total things up. - swap_total = swap_free = 0; - for (i = 0; i < nswap; i++) { - if (swdev[i].se_flags & SWF_ENABLE) { - swap_free += (swdev[i].se_nblks - swdev[i].se_inuse); - swap_total += swdev[i].se_nblks; - } - } - - free(swdev); - return Py_BuildValue("(LLLII)", - swap_total * DEV_BSIZE, - (swap_total - swap_free) * DEV_BSIZE, - swap_free * DEV_BSIZE, - // swap in / swap out is not supported as the - // swapent struct does not provide any info - // about it. - 0, 0); - -error: - free(swdev); - return NULL; -} - - -PyObject * -psutil_proc_num_fds(PyObject *self, PyObject *args) { - long pid; - int cnt; - - struct kinfo_file *freep; - struct kinfo_proc kipp; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (psutil_kinfo_proc(pid, &kipp) == -1) - return NULL; - - errno = 0; - freep = kinfo_getfile(pid, &cnt); - if (freep == NULL) { - psutil_raise_for_pid(pid, "kinfo_getfile()"); - return NULL; - } - free(freep); - - return Py_BuildValue("i", cnt); -} - - -PyObject * -psutil_proc_cwd(PyObject *self, PyObject *args) { - // Reference: - // https://github.com/openbsd/src/blob/ - // 588f7f8c69786211f2d16865c552afb91b1c7cba/bin/ps/print.c#L191 - long pid; - struct kinfo_proc kp; - char path[MAXPATHLEN]; - size_t pathlen = sizeof path; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (psutil_kinfo_proc(pid, &kp) == -1) - return NULL; - - int name[] = { CTL_KERN, KERN_PROC_CWD, pid }; - if (sysctl(name, 3, path, &pathlen, NULL, 0) != 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - return PyUnicode_DecodeFSDefault(path); -} - - -// see sys/kern/kern_sysctl.c lines 1100 and -// usr.bin/fstat/fstat.c print_inet_details() -static char * -psutil_convert_ipv4(int family, uint32_t addr[4]) { - struct in_addr a; - memcpy(&a, addr, sizeof(a)); - return inet_ntoa(a); -} - - -static char * -psutil_inet6_addrstr(struct in6_addr *p) -{ - struct sockaddr_in6 sin6; - static char hbuf[NI_MAXHOST]; - const int niflags = NI_NUMERICHOST; - - memset(&sin6, 0, sizeof(sin6)); - sin6.sin6_family = AF_INET6; - sin6.sin6_len = sizeof(struct sockaddr_in6); - sin6.sin6_addr = *p; - if (IN6_IS_ADDR_LINKLOCAL(p) && - *(u_int16_t *)&sin6.sin6_addr.s6_addr[2] != 0) { - sin6.sin6_scope_id = - ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]); - sin6.sin6_addr.s6_addr[2] = sin6.sin6_addr.s6_addr[3] = 0; - } - - if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len, - hbuf, sizeof(hbuf), NULL, 0, niflags)) - return "invalid"; - - return hbuf; -} - - -/* - * List process connections. - * Note: there is no net_connections() on OpenBSD. The Python - * implementation will iterate over all processes and use this - * function. - * Note: local and remote paths cannot be determined for UNIX sockets. - */ -PyObject * -psutil_proc_connections(PyObject *self, PyObject *args) { - long pid; - int i; - int cnt; - struct kinfo_file *freep = NULL; - struct kinfo_file *kif; - char *tcplist = NULL; - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - PyObject *py_laddr = NULL; - PyObject *py_raddr = NULL; - PyObject *py_af_filter = NULL; - PyObject *py_type_filter = NULL; - PyObject *py_family = NULL; - PyObject *_type = NULL; - - if (py_retlist == NULL) - return NULL; - if (! PyArg_ParseTuple(args, "lOO", &pid, &py_af_filter, &py_type_filter)) - goto error; - if (!PySequence_Check(py_af_filter) || !PySequence_Check(py_type_filter)) { - PyErr_SetString(PyExc_TypeError, "arg 2 or 3 is not a sequence"); - goto error; - } - - errno = 0; - freep = kinfo_getfile(pid, &cnt); - if (freep == NULL) { - psutil_raise_for_pid(pid, "kinfo_getfile()"); - goto error; - } - - for (i = 0; i < cnt; i++) { - int state; - int lport; - int rport; - char addrbuf[NI_MAXHOST + 2]; - int inseq; - struct in6_addr laddr6; - py_tuple = NULL; - py_laddr = NULL; - py_raddr = NULL; - - kif = &freep[i]; - if (kif->f_type == DTYPE_SOCKET) { - // apply filters - py_family = PyLong_FromLong((long)kif->so_family); - inseq = PySequence_Contains(py_af_filter, py_family); - Py_DECREF(py_family); - if (inseq == 0) - continue; - _type = PyLong_FromLong((long)kif->so_type); - inseq = PySequence_Contains(py_type_filter, _type); - Py_DECREF(_type); - if (inseq == 0) - continue; - - // IPv4 / IPv6 socket - if ((kif->so_family == AF_INET) || (kif->so_family == AF_INET6)) { - // fill status - if (kif->so_type == SOCK_STREAM) - state = kif->t_state; - else - state = PSUTIL_CONN_NONE; - - // ports - lport = ntohs(kif->inp_lport); - rport = ntohs(kif->inp_fport); - - // local address, IPv4 - if (kif->so_family == AF_INET) { - py_laddr = Py_BuildValue( - "(si)", - psutil_convert_ipv4(kif->so_family, kif->inp_laddru), - lport); - if (!py_laddr) - goto error; - } - else { - // local address, IPv6 - memcpy(&laddr6, kif->inp_laddru, sizeof(laddr6)); - snprintf(addrbuf, sizeof(addrbuf), "%s", - psutil_inet6_addrstr(&laddr6)); - py_laddr = Py_BuildValue("(si)", addrbuf, lport); - if (!py_laddr) - goto error; - } - - if (rport != 0) { - // remote address, IPv4 - if (kif->so_family == AF_INET) { - py_raddr = Py_BuildValue( - "(si)", - psutil_convert_ipv4( - kif->so_family, kif->inp_faddru), - rport); - } - else { - // remote address, IPv6 - memcpy(&laddr6, kif->inp_faddru, sizeof(laddr6)); - snprintf(addrbuf, sizeof(addrbuf), "%s", - psutil_inet6_addrstr(&laddr6)); - py_raddr = Py_BuildValue("(si)", addrbuf, rport); - if (!py_raddr) - goto error; - } - } - else { - py_raddr = Py_BuildValue("()"); - } - - if (!py_raddr) - goto error; - py_tuple = Py_BuildValue( - "(iiiNNi)", - kif->fd_fd, - kif->so_family, - kif->so_type, - py_laddr, - py_raddr, - state); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_tuple); - } - // UNIX socket. - // XXX: local addr is supposed to be in "unp_path" but it - // always empty; also "fstat" command is not able to show - // UNIX socket paths. - else if (kif->so_family == AF_UNIX) { - py_tuple = Py_BuildValue( - "(iiissi)", - kif->fd_fd, - kif->so_family, - kif->so_type, - "", // laddr (kif->unp_path is empty) - "", // raddr - PSUTIL_CONN_NONE); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_tuple); - Py_INCREF(Py_None); - } - } - } - free(freep); - free(tcplist); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_XDECREF(py_laddr); - Py_XDECREF(py_raddr); - Py_DECREF(py_retlist); - if (freep != NULL) - free(freep); - if (tcplist != NULL) - free(tcplist); - return NULL; -} - - -PyObject * -psutil_per_cpu_times(PyObject *self, PyObject *args) { - int mib[3]; - int ncpu; - size_t len; - size_t size; - int i; - PyObject *py_retlist = PyList_New(0); - PyObject *py_cputime = NULL; - - if (py_retlist == NULL) - return NULL; - - - // retrieve the number of cpus - mib[0] = CTL_HW; - mib[1] = HW_NCPU; - len = sizeof(ncpu); - if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - uint64_t cpu_time[CPUSTATES]; - - for (i = 0; i < ncpu; i++) { - // per-cpu info - mib[0] = CTL_KERN; - mib[1] = KERN_CPTIME2; - mib[2] = i; - size = sizeof(cpu_time); - if (sysctl(mib, 3, &cpu_time, &size, NULL, 0) == -1) { - warn("failed to get kern.cptime2"); - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - py_cputime = Py_BuildValue( - "(ddddd)", - (double)cpu_time[CP_USER] / CLOCKS_PER_SEC, - (double)cpu_time[CP_NICE] / CLOCKS_PER_SEC, - (double)cpu_time[CP_SYS] / CLOCKS_PER_SEC, - (double)cpu_time[CP_IDLE] / CLOCKS_PER_SEC, - (double)cpu_time[CP_INTR] / CLOCKS_PER_SEC); - if (!py_cputime) - goto error; - if (PyList_Append(py_retlist, py_cputime)) - goto error; - Py_DECREF(py_cputime); - } - - return py_retlist; - -error: - Py_XDECREF(py_cputime); - Py_DECREF(py_retlist); - return NULL; -} - - -PyObject * -psutil_disk_io_counters(PyObject *self, PyObject *args) { - int i, dk_ndrive, mib[3]; - size_t len; - struct diskstats *stats = NULL; - - PyObject *py_retdict = PyDict_New(); - PyObject *py_disk_info = NULL; - if (py_retdict == NULL) - return NULL; - - mib[0] = CTL_HW; - mib[1] = HW_DISKSTATS; - len = 0; - if (sysctl(mib, 2, NULL, &len, NULL, 0) < 0) { - warn("can't get hw.diskstats size"); - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - dk_ndrive = (int)(len / sizeof(struct diskstats)); - - stats = malloc(len); - if (stats == NULL) { - warn("can't malloc"); - PyErr_NoMemory(); - goto error; - } - if (sysctl(mib, 2, stats, &len, NULL, 0) < 0 ) { - warn("could not read hw.diskstats"); - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (i = 0; i < dk_ndrive; i++) { - py_disk_info = Py_BuildValue( - "(KKKK)", - stats[i].ds_rxfer, // num reads - stats[i].ds_wxfer, // num writes - stats[i].ds_rbytes, // read bytes - stats[i].ds_wbytes // write bytes - ); - if (!py_disk_info) - goto error; - if (PyDict_SetItemString(py_retdict, stats[i].ds_name, py_disk_info)) - goto error; - Py_DECREF(py_disk_info); - } - - free(stats); - return py_retdict; - -error: - Py_XDECREF(py_disk_info); - Py_DECREF(py_retdict); - if (stats != NULL) - free(stats); - return NULL; -} - - -PyObject * -psutil_cpu_stats(PyObject *self, PyObject *args) { - size_t size; - struct uvmexp uv; - int uvmexp_mib[] = {CTL_VM, VM_UVMEXP}; - - size = sizeof(uv); - if (sysctl(uvmexp_mib, 2, &uv, &size, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - return Py_BuildValue( - "IIIIIII", - uv.swtch, // ctx switches - uv.intrs, // interrupts - XXX always 0, will be determined via /proc - uv.softs, // soft interrupts - uv.syscalls, // syscalls - XXX always 0 - uv.traps, // traps - uv.faults, // faults - uv.forks // forks - ); -} diff --git a/ddtrace/vendor/psutil/arch/openbsd/specific.h b/ddtrace/vendor/psutil/arch/openbsd/specific.h deleted file mode 100644 index 4f870268d61..00000000000 --- a/ddtrace/vendor/psutil/arch/openbsd/specific.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2009, Giampaolo Rodola', Landry Breuil. - * All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include - -typedef struct kinfo_proc kinfo_proc; - -int psutil_kinfo_proc(pid_t pid, struct kinfo_proc *proc); -struct kinfo_file * kinfo_getfile(long pid, int* cnt); -int psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount); -char **_psutil_get_argv(long pid); -PyObject * psutil_get_cmdline(long pid); - -// -PyObject *psutil_proc_threads(PyObject *self, PyObject *args); -PyObject *psutil_virtual_mem(PyObject *self, PyObject *args); -PyObject *psutil_swap_mem(PyObject *self, PyObject *args); -PyObject *psutil_proc_num_fds(PyObject *self, PyObject *args); -PyObject *psutil_proc_cwd(PyObject *self, PyObject *args); -PyObject *psutil_proc_connections(PyObject *self, PyObject *args); -PyObject *psutil_per_cpu_times(PyObject *self, PyObject *args); -PyObject* psutil_disk_io_counters(PyObject* self, PyObject* args); -PyObject* psutil_cpu_stats(PyObject* self, PyObject* args); diff --git a/ddtrace/vendor/psutil/arch/osx/process_info.c b/ddtrace/vendor/psutil/arch/osx/process_info.c deleted file mode 100644 index d21c048edb3..00000000000 --- a/ddtrace/vendor/psutil/arch/osx/process_info.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, 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. - * - * Helper functions related to fetching process information. - * Used by _psutil_osx module methods. - */ - - -#include -#include -#include -#include // for INT_MAX -#include -#include -#include -#include -#include -#include - -#include "process_info.h" -#include "../../_psutil_common.h" -#include "../../_psutil_posix.h" - -/* - * Returns a list of all BSD processes on the system. This routine - * allocates the list and puts it in *procList and a count of the - * number of entries in *procCount. You are responsible for freeing - * this list (use "free" from System framework). - * On success, the function returns 0. - * On error, the function returns a BSD errno value. - */ -int -psutil_get_proc_list(kinfo_proc **procList, size_t *procCount) { - int mib3[3] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; - size_t size, size2; - void *ptr; - int err; - int lim = 8; // some limit - - assert( procList != NULL); - assert(*procList == NULL); - assert(procCount != NULL); - - *procCount = 0; - - /* - * We start by calling sysctl with ptr == NULL and size == 0. - * That will succeed, and set size to the appropriate length. - * We then allocate a buffer of at least that size and call - * sysctl with that buffer. If that succeeds, we're done. - * If that call fails with ENOMEM, we throw the buffer away - * and try again. - * Note that the loop calls sysctl with NULL again. This is - * is necessary because the ENOMEM failure case sets size to - * the amount of data returned, not the amount of data that - * could have been returned. - */ - while (lim-- > 0) { - size = 0; - if (sysctl((int *)mib3, 3, NULL, &size, NULL, 0) == -1) { - PyErr_SetFromOSErrnoWithSyscall("sysctl(KERN_PROC_ALL)"); - return 1; - } - size2 = size + (size >> 3); // add some - if (size2 > size) { - ptr = malloc(size2); - if (ptr == NULL) - ptr = malloc(size); - else - size = size2; - } - else { - ptr = malloc(size); - } - if (ptr == NULL) { - PyErr_NoMemory(); - return 1; - } - - if (sysctl((int *)mib3, 3, ptr, &size, NULL, 0) == -1) { - err = errno; - free(ptr); - if (err != ENOMEM) { - PyErr_SetFromOSErrnoWithSyscall("sysctl(KERN_PROC_ALL)"); - return 1; - } - } - else { - *procList = (kinfo_proc *)ptr; - *procCount = size / sizeof(kinfo_proc); - if (procCount <= 0) { - PyErr_Format(PyExc_RuntimeError, "no PIDs found"); - return 1; - } - return 0; // success - } - } - - PyErr_Format(PyExc_RuntimeError, "couldn't collect PIDs list"); - return 1; -} - - -// Read the maximum argument size for processes -int -psutil_get_argmax() { - int argmax; - int mib[] = { CTL_KERN, KERN_ARGMAX }; - size_t size = sizeof(argmax); - - if (sysctl(mib, 2, &argmax, &size, NULL, 0) == 0) - return argmax; - PyErr_SetFromOSErrnoWithSyscall("sysctl(KERN_ARGMAX)"); - return 0; -} - - -// Return 1 if pid refers to a zombie process else 0. -int -psutil_is_zombie(long pid) { - struct kinfo_proc kp; - - if (psutil_get_kinfo_proc(pid, &kp) == -1) - return 0; - return (kp.kp_proc.p_stat == SZOMB) ? 1 : 0; -} - - - -// return process args as a python list -PyObject * -psutil_get_cmdline(long pid) { - int mib[3]; - int nargs; - size_t len; - char *procargs = NULL; - char *arg_ptr; - char *arg_end; - char *curr_arg; - size_t argmax; - - PyObject *py_arg = NULL; - PyObject *py_retlist = NULL; - - // special case for PID 0 (kernel_task) where cmdline cannot be fetched - if (pid == 0) - return Py_BuildValue("[]"); - - // read argmax and allocate memory for argument space. - argmax = psutil_get_argmax(); - if (! argmax) - goto error; - - procargs = (char *)malloc(argmax); - if (NULL == procargs) { - PyErr_NoMemory(); - goto error; - } - - // read argument space - mib[0] = CTL_KERN; - mib[1] = KERN_PROCARGS2; - mib[2] = (pid_t)pid; - if (sysctl(mib, 3, procargs, &argmax, NULL, 0) < 0) { - // In case of zombie process we'll get EINVAL. We translate it - // to NSP and _psosx.py will translate it to ZP. - if ((errno == EINVAL) && (psutil_pid_exists(pid))) - NoSuchProcess(""); - else - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - arg_end = &procargs[argmax]; - // copy the number of arguments to nargs - memcpy(&nargs, procargs, sizeof(nargs)); - - arg_ptr = procargs + sizeof(nargs); - len = strlen(arg_ptr); - arg_ptr += len + 1; - - if (arg_ptr == arg_end) { - free(procargs); - return Py_BuildValue("[]"); - } - - // skip ahead to the first argument - for (; arg_ptr < arg_end; arg_ptr++) { - if (*arg_ptr != '\0') - break; - } - - // iterate through arguments - curr_arg = arg_ptr; - py_retlist = Py_BuildValue("[]"); - if (!py_retlist) - goto error; - while (arg_ptr < arg_end && nargs > 0) { - if (*arg_ptr++ == '\0') { - py_arg = PyUnicode_DecodeFSDefault(curr_arg); - if (! py_arg) - goto error; - if (PyList_Append(py_retlist, py_arg)) - goto error; - Py_DECREF(py_arg); - // iterate to next arg and decrement # of args - curr_arg = arg_ptr; - nargs--; - } - } - - free(procargs); - return py_retlist; - -error: - Py_XDECREF(py_arg); - Py_XDECREF(py_retlist); - if (procargs != NULL) - free(procargs); - return NULL; -} - - -// return process environment as a python string -PyObject * -psutil_get_environ(long pid) { - int mib[3]; - int nargs; - char *procargs = NULL; - char *procenv = NULL; - char *arg_ptr; - char *arg_end; - char *env_start; - size_t argmax; - PyObject *py_ret = NULL; - - // special case for PID 0 (kernel_task) where cmdline cannot be fetched - if (pid == 0) - goto empty; - - // read argmax and allocate memory for argument space. - argmax = psutil_get_argmax(); - if (! argmax) - goto error; - - procargs = (char *)malloc(argmax); - if (NULL == procargs) { - PyErr_NoMemory(); - goto error; - } - - // read argument space - mib[0] = CTL_KERN; - mib[1] = KERN_PROCARGS2; - mib[2] = (pid_t)pid; - if (sysctl(mib, 3, procargs, &argmax, NULL, 0) < 0) { - // In case of zombie process we'll get EINVAL. We translate it - // to NSP and _psosx.py will translate it to ZP. - if ((errno == EINVAL) && (psutil_pid_exists(pid))) - NoSuchProcess(""); - else - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - arg_end = &procargs[argmax]; - // copy the number of arguments to nargs - memcpy(&nargs, procargs, sizeof(nargs)); - - // skip executable path - arg_ptr = procargs + sizeof(nargs); - arg_ptr = memchr(arg_ptr, '\0', arg_end - arg_ptr); - - if (arg_ptr == NULL || arg_ptr == arg_end) - goto empty; - - // skip ahead to the first argument - for (; arg_ptr < arg_end; arg_ptr++) { - if (*arg_ptr != '\0') - break; - } - - // iterate through arguments - while (arg_ptr < arg_end && nargs > 0) { - if (*arg_ptr++ == '\0') - nargs--; - } - - // build an environment variable block - env_start = arg_ptr; - - procenv = calloc(1, arg_end - arg_ptr); - if (procenv == NULL) { - PyErr_NoMemory(); - goto error; - } - - while (*arg_ptr != '\0' && arg_ptr < arg_end) { - char *s = memchr(arg_ptr + 1, '\0', arg_end - arg_ptr); - - if (s == NULL) - break; - - memcpy(procenv + (arg_ptr - env_start), arg_ptr, s - arg_ptr); - - arg_ptr = s + 1; - } - - py_ret = PyUnicode_DecodeFSDefaultAndSize( - procenv, arg_ptr - env_start + 1); - if (!py_ret) { - // XXX: don't want to free() this as per: - // https://github.com/giampaolo/psutil/issues/926 - // It sucks but not sure what else to do. - procargs = NULL; - goto error; - } - - free(procargs); - free(procenv); - - return py_ret; - -empty: - if (procargs != NULL) - free(procargs); - return Py_BuildValue("s", ""); - -error: - Py_XDECREF(py_ret); - if (procargs != NULL) - free(procargs); - if (procenv != NULL) - free(procargs); - return NULL; -} - - -int -psutil_get_kinfo_proc(long pid, struct kinfo_proc *kp) { - int mib[4]; - size_t len; - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID; - mib[3] = (pid_t)pid; - - // fetch the info with sysctl() - len = sizeof(struct kinfo_proc); - - // now read the data from sysctl - if (sysctl(mib, 4, kp, &len, NULL, 0) == -1) { - // raise an exception and throw errno as the error - PyErr_SetFromErrno(PyExc_OSError); - return -1; - } - - // sysctl succeeds but len is zero, happens when process has gone away - if (len == 0) { - NoSuchProcess(""); - return -1; - } - return 0; -} - - -/* - * A wrapper around proc_pidinfo(). - * Returns 0 on failure (and Python exception gets already set). - */ -int -psutil_proc_pidinfo(long pid, int flavor, uint64_t arg, void *pti, int size) { - errno = 0; - int ret = proc_pidinfo((int)pid, flavor, arg, pti, size); - if ((ret <= 0) || ((unsigned long)ret < sizeof(pti))) { - psutil_raise_for_pid(pid, "proc_pidinfo()"); - return 0; - } - return ret; -} diff --git a/ddtrace/vendor/psutil/arch/osx/process_info.h b/ddtrace/vendor/psutil/arch/osx/process_info.h deleted file mode 100644 index bd7ffa89caf..00000000000 --- a/ddtrace/vendor/psutil/arch/osx/process_info.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, 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. - */ - -#include - -typedef struct kinfo_proc kinfo_proc; - -int psutil_get_argmax(void); -int psutil_is_zombie(long pid); -int psutil_get_kinfo_proc(long pid, struct kinfo_proc *kp); -int psutil_get_proc_list(kinfo_proc **procList, size_t *procCount); -int psutil_proc_pidinfo( - long pid, int flavor, uint64_t arg, void *pti, int size); -PyObject* psutil_get_cmdline(long pid); -PyObject* psutil_get_environ(long pid); diff --git a/ddtrace/vendor/psutil/arch/solaris/environ.c b/ddtrace/vendor/psutil/arch/solaris/environ.c deleted file mode 100644 index 1af4c129344..00000000000 --- a/ddtrace/vendor/psutil/arch/solaris/environ.c +++ /dev/null @@ -1,405 +0,0 @@ -/* - * Copyright (c) 2009, Giampaolo Rodola', Oleksii Shevchuk. - * All rights reserved. Use of this source code is governed by a BSD-style - * license that can be found in the LICENSE file. - * - * Functions specific for Process.environ(). - */ - -#define NEW_MIB_COMPLIANT 1 -#define _STRUCTURED_PROC 1 - -#include - -#if !defined(_LP64) && _FILE_OFFSET_BITS == 64 -# undef _FILE_OFFSET_BITS -# undef _LARGEFILE64_SOURCE -#endif - -#include -#include -#include -#include - -#include "environ.h" - - -#define STRING_SEARCH_BUF_SIZE 512 - - -/* - * Open address space of specified process and return file descriptor. - * @param pid a pid of process. - * @param procfs_path a path to mounted procfs filesystem. - * @return file descriptor or -1 in case of error. - */ -static int -open_address_space(pid_t pid, const char *procfs_path) { - int fd; - char proc_path[PATH_MAX]; - - snprintf(proc_path, PATH_MAX, "%s/%i/as", procfs_path, pid); - fd = open(proc_path, O_RDONLY); - if (fd < 0) - PyErr_SetFromErrno(PyExc_OSError); - - return fd; -} - - -/* - * Read chunk of data by offset to specified buffer of the same size. - * @param fd a file descriptor. - * @param offset an required offset in file. - * @param buf a buffer where to store result. - * @param buf_size a size of buffer where data will be stored. - * @return amount of bytes stored to the buffer or -1 in case of - * error. - */ -static int -read_offt(int fd, off_t offset, char *buf, size_t buf_size) { - size_t to_read = buf_size; - size_t stored = 0; - int r; - - while (to_read) { - r = pread(fd, buf + stored, to_read, offset + stored); - if (r < 0) - goto error; - else if (r == 0) - break; - - to_read -= r; - stored += r; - } - - return stored; - - error: - PyErr_SetFromErrno(PyExc_OSError); - return -1; -} - - -/* - * Read null-terminated string from file descriptor starting from - * specified offset. - * @param fd a file descriptor of opened address space. - * @param offset an offset in specified file descriptor. - * @return allocated null-terminated string or NULL in case of error. -*/ -static char * -read_cstring_offt(int fd, off_t offset) { - int r; - int i = 0; - off_t end = offset; - size_t len; - char buf[STRING_SEARCH_BUF_SIZE]; - char *result = NULL; - - if (lseek(fd, offset, SEEK_SET) == (off_t)-1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - // Search end of string - for (;;) { - r = read(fd, buf, sizeof(buf)); - if (r == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - else if (r == 0) { - break; - } - else { - for (i=0; i= 0 && count) - *count = env_count; - - if (env_count > 0) - result = read_cstrings_block( - as, info.pr_envp, ptr_size, env_count); - - close(as); - return result; -} - - -/* - * Free array of cstrings. - * @param array an array of cstrings returned by psutil_read_raw_env, - * psutil_read_raw_args or any other function. - * @param count a count of strings in the passed array - */ -void -psutil_free_cstrings_array(char **array, size_t count) { - int i; - - if (!array) - return; - for (i=0; i -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ifaddrs.h" - -#define MAX(x,y) ((x)>(y)?(x):(y)) -#define SIZE(p) MAX((p).ss_len,sizeof(p)) - - -static struct sockaddr * -sa_dup (struct sockaddr_storage *sa1) -{ - struct sockaddr *sa2; - size_t sz = sizeof(struct sockaddr_storage); - sa2 = (struct sockaddr *) calloc(1,sz); - memcpy(sa2,sa1,sz); - return(sa2); -} - - -void freeifaddrs (struct ifaddrs *ifp) -{ - if (NULL == ifp) return; - free(ifp->ifa_name); - free(ifp->ifa_addr); - free(ifp->ifa_netmask); - free(ifp->ifa_dstaddr); - freeifaddrs(ifp->ifa_next); - free(ifp); -} - - -int getifaddrs (struct ifaddrs **ifap) -{ - int sd = -1; - char *ccp, *ecp; - struct lifconf ifc; - struct lifreq *ifr; - struct lifnum lifn; - struct ifaddrs *cifa = NULL; /* current */ - struct ifaddrs *pifa = NULL; /* previous */ - const size_t IFREQSZ = sizeof(struct lifreq); - - sd = socket(AF_INET, SOCK_STREAM, 0); - if (sd < 0) - goto error; - - ifc.lifc_buf = NULL; - *ifap = NULL; - /* find how much memory to allocate for the SIOCGLIFCONF call */ - lifn.lifn_family = AF_UNSPEC; - lifn.lifn_flags = 0; - if (ioctl(sd, SIOCGLIFNUM, &lifn) < 0) - goto error; - - /* Sun and Apple code likes to pad the interface count here in case interfaces - * are coming up between calls */ - lifn.lifn_count += 4; - - ifc.lifc_family = AF_UNSPEC; - ifc.lifc_len = lifn.lifn_count * sizeof(struct lifreq); - ifc.lifc_buf = calloc(1, ifc.lifc_len); - if (ioctl(sd, SIOCGLIFCONF, &ifc) < 0) - goto error; - - ccp = (char *)ifc.lifc_req; - ecp = ccp + ifc.lifc_len; - - while (ccp < ecp) { - - ifr = (struct lifreq *) ccp; - cifa = (struct ifaddrs *) calloc(1, sizeof(struct ifaddrs)); - cifa->ifa_next = NULL; - cifa->ifa_name = strdup(ifr->lifr_name); - - if (pifa == NULL) *ifap = cifa; /* first one */ - else pifa->ifa_next = cifa; - - if (ioctl(sd, SIOCGLIFADDR, ifr, IFREQSZ) < 0) - goto error; - cifa->ifa_addr = sa_dup(&ifr->lifr_addr); - - if (ioctl(sd, SIOCGLIFNETMASK, ifr, IFREQSZ) < 0) - goto error; - cifa->ifa_netmask = sa_dup(&ifr->lifr_addr); - - cifa->ifa_flags = 0; - cifa->ifa_dstaddr = NULL; - - if (0 == ioctl(sd, SIOCGLIFFLAGS, ifr)) /* optional */ - cifa->ifa_flags = ifr->lifr_flags; - - if (ioctl(sd, SIOCGLIFDSTADDR, ifr, IFREQSZ) < 0) { - if (0 == ioctl(sd, SIOCGLIFBRDADDR, ifr, IFREQSZ)) - cifa->ifa_dstaddr = sa_dup(&ifr->lifr_addr); - } - else cifa->ifa_dstaddr = sa_dup(&ifr->lifr_addr); - - pifa = cifa; - ccp += IFREQSZ; - } - free(ifc.lifc_buf); - close(sd); - return 0; -error: - if (ifc.lifc_buf != NULL) - free(ifc.lifc_buf); - if (sd != -1) - close(sd); - freeifaddrs(*ifap); - return (-1); -} diff --git a/ddtrace/vendor/psutil/arch/solaris/v10/ifaddrs.h b/ddtrace/vendor/psutil/arch/solaris/v10/ifaddrs.h deleted file mode 100644 index 0953a9b99a0..00000000000 --- a/ddtrace/vendor/psutil/arch/solaris/v10/ifaddrs.h +++ /dev/null @@ -1,26 +0,0 @@ -/* Reference: https://lists.samba.org/archive/samba-technical/2009-February/063079.html */ - - -#ifndef __IFADDRS_H__ -#define __IFADDRS_H__ - -#include -#include - -#undef ifa_dstaddr -#undef ifa_broadaddr -#define ifa_broadaddr ifa_dstaddr - -struct ifaddrs { - struct ifaddrs *ifa_next; - char *ifa_name; - unsigned int ifa_flags; - struct sockaddr *ifa_addr; - struct sockaddr *ifa_netmask; - struct sockaddr *ifa_dstaddr; -}; - -extern int getifaddrs(struct ifaddrs **); -extern void freeifaddrs(struct ifaddrs *); - -#endif diff --git a/ddtrace/vendor/psutil/arch/windows/global.c b/ddtrace/vendor/psutil/arch/windows/global.c deleted file mode 100644 index 4d8526e31d6..00000000000 --- a/ddtrace/vendor/psutil/arch/windows/global.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * 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. - * - * This code is executed on import. It loads private/undocumented - * Windows APIs and sets Windows version constants so that they are - * available globally. - */ - -#include -#include -#include "ntextapi.h" -#include "global.h" - - -// Needed to make these globally visible. -int PSUTIL_WINVER; -SYSTEM_INFO PSUTIL_SYSTEM_INFO; - -#define NT_FACILITY_MASK 0xfff -#define NT_FACILITY_SHIFT 16 -#define NT_FACILITY(Status) \ - ((((ULONG)(Status)) >> NT_FACILITY_SHIFT) & NT_FACILITY_MASK) -#define NT_NTWIN32(status) (NT_FACILITY(Status) == FACILITY_WIN32) -#define WIN32_FROM_NTSTATUS(Status) (((ULONG)(Status)) & 0xffff) - - -// A wrapper around GetModuleHandle and GetProcAddress. -PVOID -psutil_GetProcAddress(LPCSTR libname, LPCSTR procname) { - HMODULE mod; - FARPROC addr; - - if ((mod = GetModuleHandleA(libname)) == NULL) { - PyErr_SetFromWindowsErrWithFilename(0, libname); - return NULL; - } - if ((addr = GetProcAddress(mod, procname)) == NULL) { - PyErr_SetFromWindowsErrWithFilename(0, procname); - return NULL; - } - return addr; -} - - -// A wrapper around LoadLibrary and GetProcAddress. -PVOID -psutil_GetProcAddressFromLib(LPCSTR libname, LPCSTR procname) { - HMODULE mod; - FARPROC addr; - - Py_BEGIN_ALLOW_THREADS - mod = LoadLibraryA(libname); - Py_END_ALLOW_THREADS - if (mod == NULL) { - PyErr_SetFromWindowsErrWithFilename(0, libname); - return NULL; - } - if ((addr = GetProcAddress(mod, procname)) == NULL) { - PyErr_SetFromWindowsErrWithFilename(0, procname); - FreeLibrary(mod); - return NULL; - } - // Causes crash. - // FreeLibrary(mod); - return addr; -} - - -/* - * Convert a NTSTATUS value to a Win32 error code and set the proper - * Python exception. - */ -PVOID -psutil_SetFromNTStatusErr(NTSTATUS Status, const char *syscall) { - ULONG err; - char fullmsg[1024]; - - if (NT_NTWIN32(Status)) - err = WIN32_FROM_NTSTATUS(Status); - else - err = psutil_RtlNtStatusToDosErrorNoTeb(Status); - // if (GetLastError() != 0) - // err = GetLastError(); - sprintf(fullmsg, "(originated from %s)", syscall); - return PyErr_SetFromWindowsErrWithFilename(err, fullmsg); -} - - -static int -psutil_loadlibs() { - /* - * Mandatory. - */ - psutil_NtQuerySystemInformation = psutil_GetProcAddressFromLib( - "ntdll.dll", "NtQuerySystemInformation"); - if (psutil_NtQuerySystemInformation == NULL) - return 1; - - psutil_NtQueryInformationProcess = psutil_GetProcAddress( - "ntdll.dll", "NtQueryInformationProcess"); - if (! psutil_NtQueryInformationProcess) - return 1; - - psutil_NtSetInformationProcess = psutil_GetProcAddress( - "ntdll.dll", "NtSetInformationProcess"); - if (! psutil_NtSetInformationProcess) - return 1; - - psutil_WinStationQueryInformationW = psutil_GetProcAddressFromLib( - "winsta.dll", "WinStationQueryInformationW"); - if (! psutil_WinStationQueryInformationW) - return 1; - - psutil_NtQueryObject = psutil_GetProcAddressFromLib( - "ntdll.dll", "NtQueryObject"); - if (! psutil_NtQueryObject) - return 1; - - psutil_rtlIpv4AddressToStringA = psutil_GetProcAddressFromLib( - "ntdll.dll", "RtlIpv4AddressToStringA"); - if (! psutil_rtlIpv4AddressToStringA) - return 1; - - // minimum requirement: Win XP SP3 - psutil_GetExtendedTcpTable = psutil_GetProcAddressFromLib( - "iphlpapi.dll", "GetExtendedTcpTable"); - if (! psutil_GetExtendedTcpTable) - return 1; - - // minimum requirement: Win XP SP3 - psutil_GetExtendedUdpTable = psutil_GetProcAddressFromLib( - "iphlpapi.dll", "GetExtendedUdpTable"); - if (! psutil_GetExtendedUdpTable) - return 1; - - psutil_RtlGetVersion = psutil_GetProcAddressFromLib( - "ntdll.dll", "RtlGetVersion"); - if (! psutil_RtlGetVersion) - return 1; - - psutil_NtSuspendProcess = psutil_GetProcAddressFromLib( - "ntdll", "NtSuspendProcess"); - if (! psutil_NtSuspendProcess) - return 1; - - psutil_NtResumeProcess = psutil_GetProcAddressFromLib( - "ntdll", "NtResumeProcess"); - if (! psutil_NtResumeProcess) - return 1; - - psutil_NtQueryVirtualMemory = psutil_GetProcAddressFromLib( - "ntdll", "NtQueryVirtualMemory"); - if (! psutil_NtQueryVirtualMemory) - return 1; - - psutil_RtlNtStatusToDosErrorNoTeb = psutil_GetProcAddressFromLib( - "ntdll", "RtlNtStatusToDosErrorNoTeb"); - if (! psutil_RtlNtStatusToDosErrorNoTeb) - return 1; - - /* - * Optional. - */ - // not available on Wine - psutil_rtlIpv6AddressToStringA = psutil_GetProcAddressFromLib( - "ntdll.dll", "RtlIpv6AddressToStringA"); - - // minimum requirement: Win Vista - psutil_GetTickCount64 = psutil_GetProcAddress( - "kernel32", "GetTickCount64"); - - // minimum requirement: Win 7 - psutil_GetActiveProcessorCount = psutil_GetProcAddress( - "kernel32", "GetActiveProcessorCount"); - - // minumum requirement: Win 7 - psutil_GetLogicalProcessorInformationEx = psutil_GetProcAddressFromLib( - "kernel32", "GetLogicalProcessorInformationEx"); - - PyErr_Clear(); - return 0; -} - - -static int -psutil_set_winver() { - RTL_OSVERSIONINFOEXW versionInfo; - ULONG maj; - ULONG min; - - versionInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW); - memset(&versionInfo, 0, sizeof(RTL_OSVERSIONINFOEXW)); - psutil_RtlGetVersion((PRTL_OSVERSIONINFOW)&versionInfo); - maj = versionInfo.dwMajorVersion; - min = versionInfo.dwMinorVersion; - if (maj == 5 && min == 1) - PSUTIL_WINVER = PSUTIL_WINDOWS_XP; - else if (maj == 5 && min == 2) - PSUTIL_WINVER = PSUTIL_WINDOWS_SERVER_2003; - else if (maj == 6 && min == 0) - PSUTIL_WINVER = PSUTIL_WINDOWS_VISTA; // or Server 2008 - else if (maj == 6 && min == 1) - PSUTIL_WINVER = PSUTIL_WINDOWS_7; - else if (maj == 6 && min == 2) - PSUTIL_WINVER = PSUTIL_WINDOWS_8; - else if (maj == 6 && min == 3) - PSUTIL_WINVER = PSUTIL_WINDOWS_8_1; - else if (maj == 10 && min == 0) - PSUTIL_WINVER = PSUTIL_WINDOWS_10; - else - PSUTIL_WINVER = PSUTIL_WINDOWS_NEW; - return 0; -} - - -static int -psutil_load_sysinfo() { - GetSystemInfo(&PSUTIL_SYSTEM_INFO); - return 0; -} - - -int -psutil_load_globals() { - if (psutil_loadlibs() != 0) - return 1; - if (psutil_set_winver() != 0) - return 1; - if (psutil_load_sysinfo() != 0) - return 1; - return 0; -} diff --git a/ddtrace/vendor/psutil/arch/windows/global.h b/ddtrace/vendor/psutil/arch/windows/global.h deleted file mode 100644 index 10ae640595d..00000000000 --- a/ddtrace/vendor/psutil/arch/windows/global.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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. - - * List of constants and objects that are globally available. - */ - -#include -#include "ntextapi.h" - -extern int PSUTIL_WINVER; -extern SYSTEM_INFO PSUTIL_SYSTEM_INFO; -#define PSUTIL_WINDOWS_XP 51 -#define PSUTIL_WINDOWS_SERVER_2003 52 -#define PSUTIL_WINDOWS_VISTA 60 -#define PSUTIL_WINDOWS_7 61 -#define PSUTIL_WINDOWS_8 62 -#define PSUTIL_WINDOWS_8_1 63 -#define PSUTIL_WINDOWS_10 100 -#define PSUTIL_WINDOWS_NEW MAXLONG - -int psutil_load_globals(); -PVOID psutil_GetProcAddress(LPCSTR libname, LPCSTR procname); -PVOID psutil_GetProcAddressFromLib(LPCSTR libname, LPCSTR procname); -PVOID psutil_SetFromNTStatusErr(NTSTATUS Status, const char *syscall); - -_NtQuerySystemInformation \ - psutil_NtQuerySystemInformation; - -_NtQueryInformationProcess \ - psutil_NtQueryInformationProcess; - -_NtSetInformationProcess - psutil_NtSetInformationProcess; - -_WinStationQueryInformationW \ - psutil_WinStationQueryInformationW; - -_RtlIpv4AddressToStringA \ - psutil_rtlIpv4AddressToStringA; - -_RtlIpv6AddressToStringA \ - psutil_rtlIpv6AddressToStringA; - -_GetExtendedTcpTable \ - psutil_GetExtendedTcpTable; - -_GetExtendedUdpTable \ - psutil_GetExtendedUdpTable; - -_GetActiveProcessorCount \ - psutil_GetActiveProcessorCount; - -_GetTickCount64 \ - psutil_GetTickCount64; - -_NtQueryObject \ - psutil_NtQueryObject; - -_GetLogicalProcessorInformationEx \ - psutil_GetLogicalProcessorInformationEx; - -_RtlGetVersion \ - psutil_RtlGetVersion; - -_NtSuspendProcess \ - psutil_NtSuspendProcess; - -_NtResumeProcess \ - psutil_NtResumeProcess; - -_NtQueryVirtualMemory \ - psutil_NtQueryVirtualMemory; - -_RtlNtStatusToDosErrorNoTeb \ - psutil_RtlNtStatusToDosErrorNoTeb; diff --git a/ddtrace/vendor/psutil/arch/windows/inet_ntop.c b/ddtrace/vendor/psutil/arch/windows/inet_ntop.c deleted file mode 100644 index 3db507b9ba0..00000000000 --- a/ddtrace/vendor/psutil/arch/windows/inet_ntop.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2009, Giampaolo Rodola', Jeff Tang. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include -#include "inet_ntop.h" - -// From: https://memset.wordpress.com/2010/10/09/inet_ntop-for-win32/ -PCSTR WSAAPI -inet_ntop(INT family, PVOID pAddr, PSTR stringBuf, size_t strBufSize) { - DWORD dwAddressLength = 0; - struct sockaddr_storage srcaddr; - struct sockaddr_in *srcaddr4 = (struct sockaddr_in*) &srcaddr; - struct sockaddr_in6 *srcaddr6 = (struct sockaddr_in6*) &srcaddr; - - memset(&srcaddr, 0, sizeof(struct sockaddr_storage)); - srcaddr.ss_family = family; - - if (family == AF_INET) { - dwAddressLength = sizeof(struct sockaddr_in); - memcpy(&(srcaddr4->sin_addr), pAddr, sizeof(struct in_addr)); - } - else if (family == AF_INET6) { - dwAddressLength = sizeof(struct sockaddr_in6); - memcpy(&(srcaddr6->sin6_addr), pAddr, sizeof(struct in6_addr)); - } - else { - PyErr_SetString(PyExc_ValueError, "invalid family"); - return NULL; - } - - if (WSAAddressToStringA( - (LPSOCKADDR) &srcaddr, - dwAddressLength, - 0, - stringBuf, - (LPDWORD) &strBufSize) != 0) - { - PyErr_SetExcFromWindowsErr(PyExc_OSError, WSAGetLastError()); - return NULL; - } - return stringBuf; -} diff --git a/ddtrace/vendor/psutil/arch/windows/inet_ntop.h b/ddtrace/vendor/psutil/arch/windows/inet_ntop.h deleted file mode 100644 index 2d86c26cf18..00000000000 --- a/ddtrace/vendor/psutil/arch/windows/inet_ntop.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (c) 2009, Giampaolo Rodola', Jeff Tang. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -// because of WSAAddressToStringA -#define _WINSOCK_DEPRECATED_NO_WARNINGS -#include - -PCSTR WSAAPI -inet_ntop( - __in INT Family, - __in const VOID * pAddr, - __out_ecount(StringBufSize) PSTR pStringBuf, - __in size_t StringBufSize -); diff --git a/ddtrace/vendor/psutil/arch/windows/ntextapi.h b/ddtrace/vendor/psutil/arch/windows/ntextapi.h deleted file mode 100644 index b6f23d99676..00000000000 --- a/ddtrace/vendor/psutil/arch/windows/ntextapi.h +++ /dev/null @@ -1,507 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, 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. - */ -#if !defined(__NTEXTAPI_H__) -#define __NTEXTAPI_H__ -#include -#include - -typedef LONG NTSTATUS; - -#define STATUS_INFO_LENGTH_MISMATCH 0xc0000004 -#define STATUS_BUFFER_TOO_SMALL 0xC0000023L -#define SystemExtendedHandleInformation 64 -#define MemoryWorkingSetInformation 0x1 -#define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L) - -/* - * ================================================================ - * Enums. - * ================================================================ - */ - -typedef enum _PROCESSINFOCLASS2 { - _ProcessBasicInformation, - ProcessQuotaLimits, - ProcessIoCounters, - ProcessVmCounters, - ProcessTimes, - ProcessBasePriority, - ProcessRaisePriority, - _ProcessDebugPort, - ProcessExceptionPort, - ProcessAccessToken, - ProcessLdtInformation, - ProcessLdtSize, - ProcessDefaultHardErrorMode, - ProcessIoPortHandlers, - ProcessPooledUsageAndLimits, - ProcessWorkingSetWatch, - ProcessUserModeIOPL, - ProcessEnableAlignmentFaultFixup, - ProcessPriorityClass, - ProcessWx86Information, - ProcessHandleCount, - ProcessAffinityMask, - ProcessPriorityBoost, - ProcessDeviceMap, - ProcessSessionInformation, - ProcessForegroundInformation, - _ProcessWow64Information, - /* added after XP+ */ - _ProcessImageFileName, - ProcessLUIDDeviceMapsEnabled, - _ProcessBreakOnTermination, - ProcessDebugObjectHandle, - ProcessDebugFlags, - ProcessHandleTracing, - ProcessIoPriority, - ProcessExecuteFlags, - ProcessResourceManagement, - ProcessCookie, - ProcessImageInformation, - MaxProcessInfoClass -} PROCESSINFOCLASS2; - -#define PROCESSINFOCLASS PROCESSINFOCLASS2 -#define ProcessBasicInformation _ProcessBasicInformation -#define ProcessWow64Information _ProcessWow64Information -#define ProcessDebugPort _ProcessDebugPort -#define ProcessImageFileName _ProcessImageFileName -#define ProcessBreakOnTermination _ProcessBreakOnTermination - -/* - * ================================================================ - * Structs. - * ================================================================ - */ - -typedef struct { - LARGE_INTEGER IdleTime; - LARGE_INTEGER KernelTime; - LARGE_INTEGER UserTime; - LARGE_INTEGER DpcTime; - LARGE_INTEGER InterruptTime; - ULONG InterruptCount; -} _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION; - -typedef struct { - LARGE_INTEGER IdleProcessTime; - LARGE_INTEGER IoReadTransferCount; - LARGE_INTEGER IoWriteTransferCount; - LARGE_INTEGER IoOtherTransferCount; - ULONG IoReadOperationCount; - ULONG IoWriteOperationCount; - ULONG IoOtherOperationCount; - ULONG AvailablePages; - ULONG CommittedPages; - ULONG CommitLimit; - ULONG PeakCommitment; - ULONG PageFaultCount; - ULONG CopyOnWriteCount; - ULONG TransitionCount; - ULONG CacheTransitionCount; - ULONG DemandZeroCount; - ULONG PageReadCount; - ULONG PageReadIoCount; - ULONG CacheReadCount; - ULONG CacheIoCount; - ULONG DirtyPagesWriteCount; - ULONG DirtyWriteIoCount; - ULONG MappedPagesWriteCount; - ULONG MappedWriteIoCount; - ULONG PagedPoolPages; - ULONG NonPagedPoolPages; - ULONG PagedPoolAllocs; - ULONG PagedPoolFrees; - ULONG NonPagedPoolAllocs; - ULONG NonPagedPoolFrees; - ULONG FreeSystemPtes; - ULONG ResidentSystemCodePage; - ULONG TotalSystemDriverPages; - ULONG TotalSystemCodePages; - ULONG NonPagedPoolLookasideHits; - ULONG PagedPoolLookasideHits; - ULONG AvailablePagedPoolPages; - ULONG ResidentSystemCachePage; - ULONG ResidentPagedPoolPage; - ULONG ResidentSystemDriverPage; - ULONG CcFastReadNoWait; - ULONG CcFastReadWait; - ULONG CcFastReadResourceMiss; - ULONG CcFastReadNotPossible; - ULONG CcFastMdlReadNoWait; - ULONG CcFastMdlReadWait; - ULONG CcFastMdlReadResourceMiss; - ULONG CcFastMdlReadNotPossible; - ULONG CcMapDataNoWait; - ULONG CcMapDataWait; - ULONG CcMapDataNoWaitMiss; - ULONG CcMapDataWaitMiss; - ULONG CcPinMappedDataCount; - ULONG CcPinReadNoWait; - ULONG CcPinReadWait; - ULONG CcPinReadNoWaitMiss; - ULONG CcPinReadWaitMiss; - ULONG CcCopyReadNoWait; - ULONG CcCopyReadWait; - ULONG CcCopyReadNoWaitMiss; - ULONG CcCopyReadWaitMiss; - ULONG CcMdlReadNoWait; - ULONG CcMdlReadWait; - ULONG CcMdlReadNoWaitMiss; - ULONG CcMdlReadWaitMiss; - ULONG CcReadAheadIos; - ULONG CcLazyWriteIos; - ULONG CcLazyWritePages; - ULONG CcDataFlushes; - ULONG CcDataPages; - ULONG ContextSwitches; - ULONG FirstLevelTbFills; - ULONG SecondLevelTbFills; - ULONG SystemCalls; -} _SYSTEM_PERFORMANCE_INFORMATION; - -typedef struct { - ULONG ContextSwitches; - ULONG DpcCount; - ULONG DpcRate; - ULONG TimeIncrement; - ULONG DpcBypassCount; - ULONG ApcBypassCount; -} _SYSTEM_INTERRUPT_INFORMATION; - -typedef enum _KTHREAD_STATE { - Initialized, - Ready, - Running, - Standby, - Terminated, - Waiting, - Transition, - DeferredReady, - GateWait, - MaximumThreadState -} KTHREAD_STATE, *PKTHREAD_STATE; - -typedef enum _KWAIT_REASON { - Executive, - FreePage, - PageIn, - PoolAllocation, - DelayExecution, - Suspended, - UserRequest, - WrExecutive, - WrFreePage, - WrPageIn, - WrPoolAllocation, - WrDelayExecution, - WrSuspended, - WrUserRequest, - WrEventPair, - WrQueue, - WrLpcReceive, - WrLpcReply, - WrVirtualMemory, - WrPageOut, - WrRendezvous, - WrKeyedEvent, - WrTerminated, - WrProcessInSwap, - WrCpuRateControl, - WrCalloutStack, - WrKernel, - WrResource, - WrPushLock, - WrMutex, - WrQuantumEnd, - WrDispatchInt, - WrPreempted, - WrYieldExecution, - WrFastMutex, - WrGuardedMutex, - WrRundown, - WrAlertByThreadId, - WrDeferredPreempt, - MaximumWaitReason -} KWAIT_REASON, *PKWAIT_REASON; - -typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX { - PVOID Object; - HANDLE UniqueProcessId; - HANDLE HandleValue; - ULONG GrantedAccess; - USHORT CreatorBackTraceIndex; - USHORT ObjectTypeIndex; - ULONG HandleAttributes; - ULONG Reserved; -} SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX; - -typedef struct _SYSTEM_HANDLE_INFORMATION_EX { - ULONG_PTR NumberOfHandles; - ULONG_PTR Reserved; - SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handles[1]; -} SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX; - -typedef struct _CLIENT_ID2 { - HANDLE UniqueProcess; - HANDLE UniqueThread; -} CLIENT_ID2, *PCLIENT_ID2; - -#define CLIENT_ID CLIENT_ID2 -#define PCLIENT_ID PCLIENT_ID2 - -typedef struct _SYSTEM_THREAD_INFORMATION2 { - LARGE_INTEGER KernelTime; - LARGE_INTEGER UserTime; - LARGE_INTEGER CreateTime; - ULONG WaitTime; - PVOID StartAddress; - CLIENT_ID ClientId; - LONG Priority; - LONG BasePriority; - ULONG ContextSwitches; - ULONG ThreadState; - KWAIT_REASON WaitReason; -} SYSTEM_THREAD_INFORMATION2, *PSYSTEM_THREAD_INFORMATION2; - -#define SYSTEM_THREAD_INFORMATION SYSTEM_THREAD_INFORMATION2 -#define PSYSTEM_THREAD_INFORMATION PSYSTEM_THREAD_INFORMATION2 - -typedef struct _TEB *PTEB; - -typedef struct _SYSTEM_EXTENDED_THREAD_INFORMATION { - SYSTEM_THREAD_INFORMATION ThreadInfo; - PVOID StackBase; - PVOID StackLimit; - PVOID Win32StartAddress; - PTEB TebBase; - ULONG_PTR Reserved2; - ULONG_PTR Reserved3; - ULONG_PTR Reserved4; -} SYSTEM_EXTENDED_THREAD_INFORMATION, *PSYSTEM_EXTENDED_THREAD_INFORMATION; - -typedef struct _SYSTEM_PROCESS_INFORMATION2 { - ULONG NextEntryOffset; - ULONG NumberOfThreads; - LARGE_INTEGER SpareLi1; - LARGE_INTEGER SpareLi2; - LARGE_INTEGER SpareLi3; - LARGE_INTEGER CreateTime; - LARGE_INTEGER UserTime; - LARGE_INTEGER KernelTime; - UNICODE_STRING ImageName; - LONG BasePriority; - HANDLE UniqueProcessId; - HANDLE InheritedFromUniqueProcessId; - ULONG HandleCount; - ULONG SessionId; - ULONG_PTR PageDirectoryBase; - SIZE_T PeakVirtualSize; - SIZE_T VirtualSize; - DWORD PageFaultCount; - SIZE_T PeakWorkingSetSize; - SIZE_T WorkingSetSize; - SIZE_T QuotaPeakPagedPoolUsage; - SIZE_T QuotaPagedPoolUsage; - SIZE_T QuotaPeakNonPagedPoolUsage; - SIZE_T QuotaNonPagedPoolUsage; - SIZE_T PagefileUsage; - SIZE_T PeakPagefileUsage; - SIZE_T PrivatePageCount; - LARGE_INTEGER ReadOperationCount; - LARGE_INTEGER WriteOperationCount; - LARGE_INTEGER OtherOperationCount; - LARGE_INTEGER ReadTransferCount; - LARGE_INTEGER WriteTransferCount; - LARGE_INTEGER OtherTransferCount; - SYSTEM_THREAD_INFORMATION Threads[1]; -} SYSTEM_PROCESS_INFORMATION2, *PSYSTEM_PROCESS_INFORMATION2; - -#define SYSTEM_PROCESS_INFORMATION SYSTEM_PROCESS_INFORMATION2 -#define PSYSTEM_PROCESS_INFORMATION PSYSTEM_PROCESS_INFORMATION2 - -typedef struct _PROCESSOR_POWER_INFORMATION { - ULONG Number; - ULONG MaxMhz; - ULONG CurrentMhz; - ULONG MhzLimit; - ULONG MaxIdleState; - ULONG CurrentIdleState; -} PROCESSOR_POWER_INFORMATION, *PPROCESSOR_POWER_INFORMATION; - -#ifndef __IPHLPAPI_H__ -typedef struct in6_addr { - union { - UCHAR Byte[16]; - USHORT Word[8]; - } u; -} IN6_ADDR, *PIN6_ADDR, FAR *LPIN6_ADDR; -#endif - -// http://msdn.microsoft.com/en-us/library/aa813741(VS.85).aspx -typedef struct { - BYTE Reserved1[16]; - PVOID Reserved2[5]; - UNICODE_STRING CurrentDirectoryPath; - PVOID CurrentDirectoryHandle; - UNICODE_STRING DllPath; - UNICODE_STRING ImagePathName; - UNICODE_STRING CommandLine; - LPCWSTR env; -} RTL_USER_PROCESS_PARAMETERS_, *PRTL_USER_PROCESS_PARAMETERS_; - -typedef struct _WINSTATION_INFO { - BYTE Reserved1[72]; - ULONG SessionId; - BYTE Reserved2[4]; - FILETIME ConnectTime; - FILETIME DisconnectTime; - FILETIME LastInputTime; - FILETIME LoginTime; - BYTE Reserved3[1096]; - FILETIME CurrentTime; -} WINSTATION_INFO, *PWINSTATION_INFO; - -#if (_WIN32_WINNT < 0x0601) // Windows < 7 (Vista and XP) -typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX { - LOGICAL_PROCESSOR_RELATIONSHIP Relationship; - DWORD Size; - _ANONYMOUS_UNION - union { - PROCESSOR_RELATIONSHIP Processor; - NUMA_NODE_RELATIONSHIP NumaNode; - CACHE_RELATIONSHIP Cache; - GROUP_RELATIONSHIP Group; - } DUMMYUNIONNAME; -} SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, *PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX; -#endif - -typedef struct _MEMORY_WORKING_SET_BLOCK { - ULONG_PTR Protection : 5; - ULONG_PTR ShareCount : 3; - ULONG_PTR Shared : 1; - ULONG_PTR Node : 3; -#ifdef _WIN64 - ULONG_PTR VirtualPage : 52; -#else - ULONG VirtualPage : 20; -#endif -} MEMORY_WORKING_SET_BLOCK, *PMEMORY_WORKING_SET_BLOCK; - -typedef struct _MEMORY_WORKING_SET_INFORMATION { - ULONG_PTR NumberOfEntries; - MEMORY_WORKING_SET_BLOCK WorkingSetInfo[1]; -} MEMORY_WORKING_SET_INFORMATION, *PMEMORY_WORKING_SET_INFORMATION; - -typedef struct _PSUTIL_PROCESS_WS_COUNTERS { - SIZE_T NumberOfPages; - SIZE_T NumberOfPrivatePages; - SIZE_T NumberOfSharedPages; - SIZE_T NumberOfShareablePages; -} PSUTIL_PROCESS_WS_COUNTERS, *PPSUTIL_PROCESS_WS_COUNTERS; - -/* - * ================================================================ - * Type defs for modules loaded at runtime. - * ================================================================ - */ - -typedef BOOL (WINAPI *_GetLogicalProcessorInformationEx)( - LOGICAL_PROCESSOR_RELATIONSHIP relationship, - PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX Buffer, - PDWORD ReturnLength); - -typedef BOOLEAN (WINAPI * _WinStationQueryInformationW)( - HANDLE ServerHandle, - ULONG SessionId, - WINSTATIONINFOCLASS WinStationInformationClass, - PVOID pWinStationInformation, - ULONG WinStationInformationLength, - PULONG pReturnLength); - -typedef NTSTATUS (NTAPI *_NtQueryInformationProcess)( - HANDLE ProcessHandle, - DWORD ProcessInformationClass, - PVOID ProcessInformation, - DWORD ProcessInformationLength, - PDWORD ReturnLength); - -typedef NTSTATUS (NTAPI *_NtQuerySystemInformation)( - ULONG SystemInformationClass, - PVOID SystemInformation, - ULONG SystemInformationLength, - PULONG ReturnLength); - -typedef NTSTATUS (NTAPI *_NtSetInformationProcess)( - HANDLE ProcessHandle, - DWORD ProcessInformationClass, - PVOID ProcessInformation, - DWORD ProcessInformationLength); - -typedef PSTR (NTAPI * _RtlIpv4AddressToStringA)( - struct in_addr *Addr, - PSTR S); - -typedef PSTR (NTAPI * _RtlIpv6AddressToStringA)( - struct in6_addr *Addr, - PSTR P); - -typedef DWORD (WINAPI * _GetExtendedTcpTable)( - PVOID pTcpTable, - PDWORD pdwSize, - BOOL bOrder, - ULONG ulAf, - TCP_TABLE_CLASS TableClass, - ULONG Reserved); - -typedef DWORD (WINAPI * _GetExtendedUdpTable)( - PVOID pUdpTable, - PDWORD pdwSize, - BOOL bOrder, - ULONG ulAf, - UDP_TABLE_CLASS TableClass, - ULONG Reserved); - -typedef DWORD (CALLBACK *_GetActiveProcessorCount)( - WORD GroupNumber); - -typedef ULONGLONG (CALLBACK *_GetTickCount64)( - void); - -typedef NTSTATUS (NTAPI *_NtQueryObject)( - HANDLE Handle, - OBJECT_INFORMATION_CLASS ObjectInformationClass, - PVOID ObjectInformation, - ULONG ObjectInformationLength, - PULONG ReturnLength); - -typedef NTSTATUS (WINAPI *_RtlGetVersion) ( - PRTL_OSVERSIONINFOW lpVersionInformation -); - -typedef NTSTATUS (WINAPI *_NtResumeProcess) ( - HANDLE hProcess -); - -typedef NTSTATUS (WINAPI *_NtSuspendProcess) ( - HANDLE hProcess -); - -typedef NTSTATUS (NTAPI *_NtQueryVirtualMemory) ( - HANDLE ProcessHandle, - PVOID BaseAddress, - int MemoryInformationClass, - PVOID MemoryInformation, - SIZE_T MemoryInformationLength, - PSIZE_T ReturnLength -); - -typedef ULONG (WINAPI *_RtlNtStatusToDosErrorNoTeb) ( - NTSTATUS status -); - -#endif // __NTEXTAPI_H__ diff --git a/ddtrace/vendor/psutil/arch/windows/process_handles.c b/ddtrace/vendor/psutil/arch/windows/process_handles.c deleted file mode 100644 index 5966669e280..00000000000 --- a/ddtrace/vendor/psutil/arch/windows/process_handles.c +++ /dev/null @@ -1,513 +0,0 @@ -/* - * 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. - * - */ - -#include -#include -#include -#include "ntextapi.h" -#include "global.h" -#include "process_handles.h" -#include "process_info.h" -#include "../../_psutil_common.h" - -CRITICAL_SECTION g_cs; -BOOL g_initialized = FALSE; -NTSTATUS g_status; -HANDLE g_hFile = NULL; -HANDLE g_hEvtStart = NULL; -HANDLE g_hEvtFinish = NULL; -HANDLE g_hThread = NULL; -PUNICODE_STRING g_pNameBuffer = NULL; -ULONG g_dwSize = 0; -ULONG g_dwLength = 0; - - -#define ObjectNameInformation 1 -#define NTQO_TIMEOUT 100 - - -static VOID -psutil_get_open_files_init(BOOL threaded) { - if (g_initialized == TRUE) - return; - - // Create events for signalling work between threads - if (threaded == TRUE) { - g_hEvtStart = CreateEvent(NULL, FALSE, FALSE, NULL); - g_hEvtFinish = CreateEvent(NULL, FALSE, FALSE, NULL); - InitializeCriticalSection(&g_cs); - } - - g_initialized = TRUE; -} - - -static DWORD WINAPI -psutil_wait_thread(LPVOID lpvParam) { - // Loop infinitely waiting for work - while (TRUE) { - WaitForSingleObject(g_hEvtStart, INFINITE); - - // TODO: return code not checked - g_status = psutil_NtQueryObject( - g_hFile, - ObjectNameInformation, - g_pNameBuffer, - g_dwSize, - &g_dwLength); - SetEvent(g_hEvtFinish); - } -} - - -static DWORD -psutil_create_thread() { - DWORD dwWait = 0; - - if (g_hThread == NULL) - g_hThread = CreateThread( - NULL, - 0, - psutil_wait_thread, - NULL, - 0, - NULL); - if (g_hThread == NULL) - return GetLastError(); - - // Signal the worker thread to start - SetEvent(g_hEvtStart); - - // Wait for the worker thread to finish - dwWait = WaitForSingleObject(g_hEvtFinish, NTQO_TIMEOUT); - - // If the thread hangs, kill it and cleanup - if (dwWait == WAIT_TIMEOUT) { - SuspendThread(g_hThread); - TerminateThread(g_hThread, 1); - WaitForSingleObject(g_hThread, INFINITE); - CloseHandle(g_hThread); - - g_hThread = NULL; - } - - return dwWait; -} - - -static PyObject * -psutil_get_open_files_ntqueryobject(long dwPid, HANDLE hProcess) { - NTSTATUS status; - PSYSTEM_HANDLE_INFORMATION_EX pHandleInfo = NULL; - DWORD dwInfoSize = 0x10000; - DWORD dwRet = 0; - PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX hHandle = NULL; - DWORD i = 0; - BOOLEAN error = FALSE; - DWORD dwWait = 0; - PyObject* py_retlist = NULL; - PyObject* py_path = NULL; - - if (g_initialized == FALSE) - psutil_get_open_files_init(TRUE); - - // Due to the use of global variables, ensure only 1 call - // to psutil_get_open_files() is running - EnterCriticalSection(&g_cs); - - if (g_hEvtStart == NULL || - g_hEvtFinish == NULL) - - { - PyErr_SetFromWindowsErr(0); - error = TRUE; - goto cleanup; - } - - // Py_BuildValue raises an exception if NULL is returned - py_retlist = PyList_New(0); - if (py_retlist == NULL) { - error = TRUE; - goto cleanup; - } - - do { - if (pHandleInfo != NULL) { - HeapFree(GetProcessHeap(), 0, pHandleInfo); - pHandleInfo = NULL; - } - - // NtQuerySystemInformation won't give us the correct buffer size, - // so we guess by doubling the buffer size. - dwInfoSize *= 2; - pHandleInfo = HeapAlloc(GetProcessHeap(), - HEAP_ZERO_MEMORY, - dwInfoSize); - - if (pHandleInfo == NULL) { - PyErr_NoMemory(); - error = TRUE; - goto cleanup; - } - } while ((status = psutil_NtQuerySystemInformation( - SystemExtendedHandleInformation, - pHandleInfo, - dwInfoSize, - &dwRet)) == STATUS_INFO_LENGTH_MISMATCH); - - // NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH - if (! NT_SUCCESS(status)) { - psutil_SetFromNTStatusErr( - status, "NtQuerySystemInformation(SystemExtendedHandleInformation)"); - error = TRUE; - goto cleanup; - } - - for (i = 0; i < pHandleInfo->NumberOfHandles; i++) { - hHandle = &pHandleInfo->Handles[i]; - - // Check if this hHandle belongs to the PID the user specified. - if (hHandle->UniqueProcessId != (ULONG_PTR)dwPid) - goto loop_cleanup; - - if (!DuplicateHandle(hProcess, - (HANDLE)hHandle->HandleValue, - GetCurrentProcess(), - &g_hFile, - 0, - TRUE, - DUPLICATE_SAME_ACCESS)) - { - /* - printf("[%d] DuplicateHandle (%#x): %#x \n", - dwPid, - hHandle->HandleValue, - GetLastError()); - */ - goto loop_cleanup; - } - - // Guess buffer size is MAX_PATH + 1 - g_dwLength = (MAX_PATH+1) * sizeof(WCHAR); - - do { - // Release any previously allocated buffer - if (g_pNameBuffer != NULL) { - HeapFree(GetProcessHeap(), 0, g_pNameBuffer); - g_pNameBuffer = NULL; - g_dwSize = 0; - } - - // NtQueryObject puts the required buffer size in g_dwLength - // WinXP edge case puts g_dwLength == 0, just skip this handle - if (g_dwLength == 0) - goto loop_cleanup; - - g_dwSize = g_dwLength; - if (g_dwSize > 0) { - g_pNameBuffer = HeapAlloc(GetProcessHeap(), - HEAP_ZERO_MEMORY, - g_dwSize); - - if (g_pNameBuffer == NULL) - goto loop_cleanup; - } - - dwWait = psutil_create_thread(); - - // If the call does not return, skip this handle - if (dwWait != WAIT_OBJECT_0) - goto loop_cleanup; - - } while (g_status == STATUS_INFO_LENGTH_MISMATCH); - - // NtQueryObject stopped returning STATUS_INFO_LENGTH_MISMATCH - if (!NT_SUCCESS(g_status)) - goto loop_cleanup; - - // Convert to PyUnicode and append it to the return list - if (g_pNameBuffer->Length > 0) { - /* - printf("[%d] Filename (%#x) %#d bytes: %S\n", - dwPid, - hHandle->HandleValue, - g_pNameBuffer->Length, - g_pNameBuffer->Buffer); - */ - - py_path = PyUnicode_FromWideChar(g_pNameBuffer->Buffer, - g_pNameBuffer->Length/2); - if (py_path == NULL) { - /* - printf("[%d] PyUnicode_FromWideChar (%#x): %#x \n", - dwPid, - hHandle->HandleValue, - GetLastError()); - */ - error = TRUE; - goto loop_cleanup; - } - - if (PyList_Append(py_retlist, py_path)) { - /* - printf("[%d] PyList_Append (%#x): %#x \n", - dwPid, - hHandle->HandleValue, - GetLastError()); - */ - error = TRUE; - goto loop_cleanup; - } - } - -loop_cleanup: - Py_XDECREF(py_path); - py_path = NULL; - - if (g_pNameBuffer != NULL) - HeapFree(GetProcessHeap(), 0, g_pNameBuffer); - g_pNameBuffer = NULL; - g_dwSize = 0; - g_dwLength = 0; - - if (g_hFile != NULL) - CloseHandle(g_hFile); - g_hFile = NULL; -} - -cleanup: - if (g_pNameBuffer != NULL) - HeapFree(GetProcessHeap(), 0, g_pNameBuffer); - g_pNameBuffer = NULL; - g_dwSize = 0; - g_dwLength = 0; - - if (g_hFile != NULL) - CloseHandle(g_hFile); - g_hFile = NULL; - - if (pHandleInfo != NULL) - HeapFree(GetProcessHeap(), 0, pHandleInfo); - pHandleInfo = NULL; - - if (error) { - Py_XDECREF(py_retlist); - py_retlist = NULL; - } - - LeaveCriticalSection(&g_cs); - - return py_retlist; -} - - -static PyObject * -psutil_get_open_files_getmappedfilename(long dwPid, HANDLE hProcess) { - NTSTATUS status; - PSYSTEM_HANDLE_INFORMATION_EX pHandleInfo = NULL; - DWORD dwInfoSize = 0x10000; - DWORD dwRet = 0; - PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX hHandle = NULL; - HANDLE hFile = NULL; - HANDLE hMap = NULL; - DWORD i = 0; - BOOLEAN error = FALSE; - PyObject* py_retlist = NULL; - PyObject* py_path = NULL; - ULONG dwSize = 0; - LPVOID pMem = NULL; - wchar_t pszFilename[MAX_PATH+1]; - - if (g_initialized == FALSE) - psutil_get_open_files_init(FALSE); - - // Py_BuildValue raises an exception if NULL is returned - py_retlist = PyList_New(0); - if (py_retlist == NULL) { - error = TRUE; - goto cleanup; - } - - do { - if (pHandleInfo != NULL) { - HeapFree(GetProcessHeap(), 0, pHandleInfo); - pHandleInfo = NULL; - } - - // NtQuerySystemInformation won't give us the correct buffer size, - // so we guess by doubling the buffer size. - dwInfoSize *= 2; - pHandleInfo = HeapAlloc(GetProcessHeap(), - HEAP_ZERO_MEMORY, - dwInfoSize); - - if (pHandleInfo == NULL) { - PyErr_NoMemory(); - error = TRUE; - goto cleanup; - } - } while ((status = psutil_NtQuerySystemInformation( - SystemExtendedHandleInformation, - pHandleInfo, - dwInfoSize, - &dwRet)) == STATUS_INFO_LENGTH_MISMATCH); - - // NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH - if (! NT_SUCCESS(status)) { - psutil_SetFromNTStatusErr( - status, "NtQuerySystemInformation(SystemExtendedHandleInformation)"); - error = TRUE; - goto cleanup; - } - - for (i = 0; i < pHandleInfo->NumberOfHandles; i++) { - hHandle = &pHandleInfo->Handles[i]; - - // Check if this hHandle belongs to the PID the user specified. - if (hHandle->UniqueProcessId != (ULONG_PTR)dwPid) - goto loop_cleanup; - - if (!DuplicateHandle(hProcess, - (HANDLE)hHandle->HandleValue, - GetCurrentProcess(), - &hFile, - 0, - TRUE, - DUPLICATE_SAME_ACCESS)) - { - /* - printf("[%d] DuplicateHandle (%#x): %#x \n", - dwPid, - hHandle->HandleValue, - GetLastError()); - */ - goto loop_cleanup; - } - - hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); - if (hMap == NULL) { - /* - printf("[%d] CreateFileMapping (%#x): %#x \n", - dwPid, - hHandle->HandleValue, - GetLastError()); - */ - goto loop_cleanup; - } - - pMem = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 1); - - if (pMem == NULL) { - /* - printf("[%d] MapViewOfFile (%#x): %#x \n", - dwPid, - hHandle->HandleValue, - GetLastError()); - */ - goto loop_cleanup; - } - - dwSize = GetMappedFileName( - GetCurrentProcess(), pMem, (LPSTR)pszFilename, MAX_PATH); - if (dwSize == 0) { - /* - printf("[%d] GetMappedFileName (%#x): %#x \n", - dwPid, - hHandle->HandleValue, - GetLastError()); - */ - goto loop_cleanup; - } - - pszFilename[dwSize] = '\0'; - /* - printf("[%d] Filename (%#x) %#d bytes: %S\n", - dwPid, - hHandle->HandleValue, - dwSize, - pszFilename); - */ - - py_path = PyUnicode_FromWideChar(pszFilename, dwSize); - if (py_path == NULL) { - /* - printf("[%d] PyUnicode_FromStringAndSize (%#x): %#x \n", - dwPid, - hHandle->HandleValue, - GetLastError()); - */ - error = TRUE; - goto loop_cleanup; - } - - if (PyList_Append(py_retlist, py_path)) { - /* - printf("[%d] PyList_Append (%#x): %#x \n", - dwPid, - hHandle->HandleValue, - GetLastError()); - */ - error = TRUE; - goto loop_cleanup; - } - -loop_cleanup: - Py_XDECREF(py_path); - py_path = NULL; - - if (pMem != NULL) - UnmapViewOfFile(pMem); - pMem = NULL; - - if (hMap != NULL) - CloseHandle(hMap); - hMap = NULL; - - if (hFile != NULL) - CloseHandle(hFile); - hFile = NULL; - - dwSize = 0; - } - -cleanup: - if (pMem != NULL) - UnmapViewOfFile(pMem); - pMem = NULL; - - if (hMap != NULL) - CloseHandle(hMap); - hMap = NULL; - - if (hFile != NULL) - CloseHandle(hFile); - hFile = NULL; - - if (pHandleInfo != NULL) - HeapFree(GetProcessHeap(), 0, pHandleInfo); - pHandleInfo = NULL; - - if (error) { - Py_XDECREF(py_retlist); - py_retlist = NULL; - } - - return py_retlist; -} - - -/* - * The public function. - */ -PyObject * -psutil_get_open_files(long dwPid, HANDLE hProcess) { - // Threaded version only works for Vista+ - if (PSUTIL_WINVER >= PSUTIL_WINDOWS_VISTA) - return psutil_get_open_files_ntqueryobject(dwPid, hProcess); - else - return psutil_get_open_files_getmappedfilename(dwPid, hProcess); -} diff --git a/ddtrace/vendor/psutil/arch/windows/process_handles.h b/ddtrace/vendor/psutil/arch/windows/process_handles.h deleted file mode 100644 index 342ce8fd26a..00000000000 --- a/ddtrace/vendor/psutil/arch/windows/process_handles.h +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, 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. - */ - -#include -#include - -PyObject* psutil_get_open_files(long pid, HANDLE processHandle); diff --git a/ddtrace/vendor/psutil/arch/windows/process_info.c b/ddtrace/vendor/psutil/arch/windows/process_info.c deleted file mode 100644 index 5ea5f765c0c..00000000000 --- a/ddtrace/vendor/psutil/arch/windows/process_info.c +++ /dev/null @@ -1,1027 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, 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. - * - * Helper functions related to fetching process information. Used by - * _psutil_windows module methods. - */ - -#include -#include -#include -#include - -#include "ntextapi.h" -#include "global.h" -#include "security.h" -#include "process_info.h" -#include "../../_psutil_common.h" - - -// ==================================================================== -// Helper structures to access the memory correctly. -// Some of these might also be defined in the winternl.h header file -// but unfortunately not in a usable way. -// ==================================================================== - -// https://msdn.microsoft.com/en-us/library/aa813706(v=vs.85).aspx -#ifdef _WIN64 -typedef struct { - BYTE Reserved1[2]; - BYTE BeingDebugged; - BYTE Reserved2[21]; - PVOID LoaderData; - PRTL_USER_PROCESS_PARAMETERS_ ProcessParameters; - /* More fields ... */ -} PEB_; -#else -typedef struct { - BYTE Reserved1[2]; - BYTE BeingDebugged; - BYTE Reserved2[1]; - PVOID Reserved3[2]; - PVOID Ldr; - PRTL_USER_PROCESS_PARAMETERS_ ProcessParameters; - /* More fields ... */ -} PEB_; -#endif - -#ifdef _WIN64 -/* When we are a 64 bit process accessing a 32 bit (WoW64) process we need to - use the 32 bit structure layout. */ -typedef struct { - USHORT Length; - USHORT MaxLength; - DWORD Buffer; -} UNICODE_STRING32; - -typedef struct { - BYTE Reserved1[16]; - DWORD Reserved2[5]; - UNICODE_STRING32 CurrentDirectoryPath; - DWORD CurrentDirectoryHandle; - UNICODE_STRING32 DllPath; - UNICODE_STRING32 ImagePathName; - UNICODE_STRING32 CommandLine; - DWORD env; -} RTL_USER_PROCESS_PARAMETERS32; - -typedef struct { - BYTE Reserved1[2]; - BYTE BeingDebugged; - BYTE Reserved2[1]; - DWORD Reserved3[2]; - DWORD Ldr; - DWORD ProcessParameters; - /* More fields ... */ -} PEB32; -#else -/* When we are a 32 bit (WoW64) process accessing a 64 bit process we need to - use the 64 bit structure layout and a special function to read its memory. - */ -typedef NTSTATUS (NTAPI *_NtWow64ReadVirtualMemory64)( - HANDLE ProcessHandle, - PVOID64 BaseAddress, - PVOID Buffer, - ULONG64 Size, - PULONG64 NumberOfBytesRead); - -typedef struct { - PVOID Reserved1[2]; - PVOID64 PebBaseAddress; - PVOID Reserved2[4]; - PVOID UniqueProcessId[2]; - PVOID Reserved3[2]; -} PROCESS_BASIC_INFORMATION64; - -typedef struct { - USHORT Length; - USHORT MaxLength; - PVOID64 Buffer; -} UNICODE_STRING64; - -typedef struct { - BYTE Reserved1[16]; - PVOID64 Reserved2[5]; - UNICODE_STRING64 CurrentDirectoryPath; - PVOID64 CurrentDirectoryHandle; - UNICODE_STRING64 DllPath; - UNICODE_STRING64 ImagePathName; - UNICODE_STRING64 CommandLine; - PVOID64 env; -} RTL_USER_PROCESS_PARAMETERS64; - -typedef struct { - BYTE Reserved1[2]; - BYTE BeingDebugged; - BYTE Reserved2[21]; - PVOID64 LoaderData; - PVOID64 ProcessParameters; - /* More fields ... */ -} PEB64; -#endif - - -#define PSUTIL_FIRST_PROCESS(Processes) ( \ - (PSYSTEM_PROCESS_INFORMATION)(Processes)) -#define PSUTIL_NEXT_PROCESS(Process) ( \ - ((PSYSTEM_PROCESS_INFORMATION)(Process))->NextEntryOffset ? \ - (PSYSTEM_PROCESS_INFORMATION)((PCHAR)(Process) + \ - ((PSYSTEM_PROCESS_INFORMATION)(Process))->NextEntryOffset) : NULL) - - -// ==================================================================== -// Process and PIDs utiilties. -// ==================================================================== - - -#define STATUS_BUFFER_OVERFLOW ((NTSTATUS)0x80000005L) - -/* - * Return 1 if PID exists, 0 if not, -1 on error. - */ -int -psutil_pid_in_pids(DWORD pid) { - DWORD *proclist = NULL; - DWORD numberOfReturnedPIDs; - DWORD i; - - proclist = psutil_get_pids(&numberOfReturnedPIDs); - if (proclist == NULL) - return -1; - for (i = 0; i < numberOfReturnedPIDs; i++) { - if (proclist[i] == pid) { - free(proclist); - return 1; - } - } - free(proclist); - return 0; -} - - -/* - * Given a process HANDLE checks whether it's actually running. - * Returns: - * - 1: running - * - 0: not running - * - -1: WindowsError - * - -2: AssertionError - */ -int -psutil_is_phandle_running(HANDLE hProcess, DWORD pid) { - DWORD processExitCode = 0; - - if (hProcess == NULL) { - if (GetLastError() == ERROR_INVALID_PARAMETER) { - // Yeah, this is the actual error code in case of - // "no such process". - if (! psutil_assert_pid_not_exists( - pid, "iphr: OpenProcess() -> ERROR_INVALID_PARAMETER")) { - return -2; - } - return 0; - } - return -1; - } - - if (GetExitCodeProcess(hProcess, &processExitCode)) { - // XXX - maybe STILL_ACTIVE is not fully reliable as per: - // http://stackoverflow.com/questions/1591342/#comment47830782_1591379 - if (processExitCode == STILL_ACTIVE) { - if (! psutil_assert_pid_exists( - pid, "iphr: GetExitCodeProcess() -> STILL_ACTIVE")) { - return -2; - } - return 1; - } - else { - // We can't be sure so we look into pids. - if (psutil_pid_in_pids(pid) == 1) { - return 1; - } - else { - CloseHandle(hProcess); - return 0; - } - } - } - - CloseHandle(hProcess); - if (! psutil_assert_pid_not_exists( pid, "iphr: exit fun")) { - return -2; - } - return -1; -} - - -/* - * Given a process HANDLE checks whether it's actually running and if - * it does return it, else return NULL with the proper Python exception - * set. - */ -HANDLE -psutil_check_phandle(HANDLE hProcess, DWORD pid) { - int ret = psutil_is_phandle_running(hProcess, pid); - if (ret == 1) { - return hProcess; - } - else if (ret == 0) { - return NoSuchProcess(""); - } - else if (ret == -1) { - if (GetLastError() == ERROR_ACCESS_DENIED) - return PyErr_SetFromWindowsErr(0); - else - return PyErr_SetFromOSErrnoWithSyscall("OpenProcess"); - } - else { - return NULL; - } -} - - -/* - * A wrapper around OpenProcess setting NSP exception if process - * no longer exists. - * "pid" is the process pid, "dwDesiredAccess" is the first argument - * exptected by OpenProcess. - * Return a process handle or NULL. - */ -HANDLE -psutil_handle_from_pid(DWORD pid, DWORD access) { - HANDLE hProcess; - - if (pid == 0) { - // otherwise we'd get NoSuchProcess - return AccessDenied(""); - } - // needed for GetExitCodeProcess - access |= PROCESS_QUERY_LIMITED_INFORMATION; - hProcess = OpenProcess(access, FALSE, pid); - return psutil_check_phandle(hProcess, pid); -} - - -DWORD * -psutil_get_pids(DWORD *numberOfReturnedPIDs) { - // Win32 SDK says the only way to know if our process array - // wasn't large enough is to check the returned size and make - // sure that it doesn't match the size of the array. - // If it does we allocate a larger array and try again - - // Stores the actual array - DWORD *procArray = NULL; - DWORD procArrayByteSz; - int procArraySz = 0; - - // Stores the byte size of the returned array from enumprocesses - DWORD enumReturnSz = 0; - - do { - procArraySz += 1024; - if (procArray != NULL) - free(procArray); - procArrayByteSz = procArraySz * sizeof(DWORD); - procArray = malloc(procArrayByteSz); - if (procArray == NULL) { - PyErr_NoMemory(); - return NULL; - } - if (! EnumProcesses(procArray, procArrayByteSz, &enumReturnSz)) { - free(procArray); - PyErr_SetFromWindowsErr(0); - return NULL; - } - } while (enumReturnSz == procArraySz * sizeof(DWORD)); - - // The number of elements is the returned size / size of each element - *numberOfReturnedPIDs = enumReturnSz / sizeof(DWORD); - - return procArray; -} - - -int -psutil_assert_pid_exists(DWORD pid, char *err) { - if (PSUTIL_TESTING) { - if (psutil_pid_in_pids(pid) == 0) { - PyErr_SetString(PyExc_AssertionError, err); - return 0; - } - } - return 1; -} - - -int -psutil_assert_pid_not_exists(DWORD pid, char *err) { - if (PSUTIL_TESTING) { - if (psutil_pid_in_pids(pid) == 1) { - PyErr_SetString(PyExc_AssertionError, err); - return 0; - } - } - return 1; -} - - -/* -/* Check for PID existance by using OpenProcess() + GetExitCodeProcess. -/* Returns: - * 1: pid exists - * 0: it doesn't - * -1: error - */ -int -psutil_pid_is_running(DWORD pid) { - HANDLE hProcess; - DWORD exitCode; - DWORD err; - - // Special case for PID 0 System Idle Process - if (pid == 0) - return 1; - if (pid < 0) - return 0; - hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid); - if (NULL == hProcess) { - err = GetLastError(); - // Yeah, this is the actual error code in case of "no such process". - if (err == ERROR_INVALID_PARAMETER) { - if (! psutil_assert_pid_not_exists( - pid, "pir: OpenProcess() -> INVALID_PARAMETER")) { - return -1; - } - return 0; - } - // Access denied obviously means there's a process to deny access to. - else if (err == ERROR_ACCESS_DENIED) { - if (! psutil_assert_pid_exists( - pid, "pir: OpenProcess() ACCESS_DENIED")) { - return -1; - } - return 1; - } - // Be strict and raise an exception; the caller is supposed - // to take -1 into account. - else { - PyErr_SetFromOSErrnoWithSyscall("OpenProcess(PROCESS_VM_READ)"); - return -1; - } - } - - if (GetExitCodeProcess(hProcess, &exitCode)) { - CloseHandle(hProcess); - // XXX - maybe STILL_ACTIVE is not fully reliable as per: - // http://stackoverflow.com/questions/1591342/#comment47830782_1591379 - if (exitCode == STILL_ACTIVE) { - if (! psutil_assert_pid_exists( - pid, "pir: GetExitCodeProcess() -> STILL_ACTIVE")) { - return -1; - } - return 1; - } - // We can't be sure so we look into pids. - else { - return psutil_pid_in_pids(pid); - } - } - else { - err = GetLastError(); - CloseHandle(hProcess); - // Same as for OpenProcess, assume access denied means there's - // a process to deny access to. - if (err == ERROR_ACCESS_DENIED) { - if (! psutil_assert_pid_exists( - pid, "pir: GetExitCodeProcess() -> ERROR_ACCESS_DENIED")) { - return -1; - } - return 1; - } - else { - PyErr_SetFromOSErrnoWithSyscall("GetExitCodeProcess"); - return -1; - } - } -} - - -/* Given a pointer into a process's memory, figure out how much data can be - * read from it. */ -static int -psutil_get_process_region_size(HANDLE hProcess, LPCVOID src, SIZE_T *psize) { - MEMORY_BASIC_INFORMATION info; - - if (!VirtualQueryEx(hProcess, src, &info, sizeof(info))) { - PyErr_SetFromOSErrnoWithSyscall("VirtualQueryEx"); - return -1; - } - - *psize = info.RegionSize - ((char*)src - (char*)info.BaseAddress); - return 0; -} - - -enum psutil_process_data_kind { - KIND_CMDLINE, - KIND_CWD, - KIND_ENVIRON, -}; - -/* Get data from the process with the given pid. The data is returned in the - pdata output member as a nul terminated string which must be freed on - success. - - On success 0 is returned. On error the output parameter is not touched, -1 - is returned, and an appropriate Python exception is set. */ -static int -psutil_get_process_data(long pid, - enum psutil_process_data_kind kind, - WCHAR **pdata, - SIZE_T *psize) { - /* This function is quite complex because there are several cases to be - considered: - - Two cases are really simple: we (i.e. the python interpreter) and the - target process are both 32 bit or both 64 bit. In that case the memory - layout of the structures matches up and all is well. - - When we are 64 bit and the target process is 32 bit we need to use - custom 32 bit versions of the structures. - - When we are 32 bit and the target process is 64 bit we need to use - custom 64 bit version of the structures. Also we need to use separate - Wow64 functions to get the information. - - A few helper structs are defined above so that the compiler can handle - calculating the correct offsets. - - Additional help also came from the following sources: - - https://github.com/kohsuke/winp and - http://wj32.org/wp/2009/01/24/howto-get-the-command-line-of-processes/ - http://stackoverflow.com/a/14012919 - http://www.drdobbs.com/embracing-64-bit-windows/184401966 - */ - _NtQueryInformationProcess NtQueryInformationProcess = NULL; -#ifndef _WIN64 - static _NtQueryInformationProcess NtWow64QueryInformationProcess64 = NULL; - static _NtWow64ReadVirtualMemory64 NtWow64ReadVirtualMemory64 = NULL; -#endif - HANDLE hProcess = NULL; - LPCVOID src; - SIZE_T size; - WCHAR *buffer = NULL; -#ifdef _WIN64 - LPVOID ppeb32 = NULL; -#else - PVOID64 src64; - BOOL weAreWow64; - BOOL theyAreWow64; -#endif - DWORD access = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ; - NTSTATUS status; - - hProcess = psutil_handle_from_pid(pid, access); - if (hProcess == NULL) - return -1; - -#ifdef _WIN64 - /* 64 bit case. Check if the target is a 32 bit process running in WoW64 - * mode. */ - status = psutil_NtQueryInformationProcess( - hProcess, - ProcessWow64Information, - &ppeb32, - sizeof(LPVOID), - NULL); - - if (!NT_SUCCESS(status)) { - psutil_SetFromNTStatusErr( - status, "NtQueryInformationProcess(ProcessWow64Information)"); - goto error; - } - - if (ppeb32 != NULL) { - /* We are 64 bit. Target process is 32 bit running in WoW64 mode. */ - PEB32 peb32; - RTL_USER_PROCESS_PARAMETERS32 procParameters32; - - // read PEB - if (!ReadProcessMemory(hProcess, ppeb32, &peb32, sizeof(peb32), NULL)) { - // May fail with ERROR_PARTIAL_COPY, see: - // https://github.com/giampaolo/psutil/issues/875 - PyErr_SetFromWindowsErr(0); - goto error; - } - - // read process parameters - if (!ReadProcessMemory(hProcess, - UlongToPtr(peb32.ProcessParameters), - &procParameters32, - sizeof(procParameters32), - NULL)) - { - // May fail with ERROR_PARTIAL_COPY, see: - // https://github.com/giampaolo/psutil/issues/875 - PyErr_SetFromWindowsErr(0); - goto error; - } - - switch (kind) { - case KIND_CMDLINE: - src = UlongToPtr(procParameters32.CommandLine.Buffer), - size = procParameters32.CommandLine.Length; - break; - case KIND_CWD: - src = UlongToPtr(procParameters32.CurrentDirectoryPath.Buffer); - size = procParameters32.CurrentDirectoryPath.Length; - break; - case KIND_ENVIRON: - src = UlongToPtr(procParameters32.env); - break; - } - } else -#else - /* 32 bit case. Check if the target is also 32 bit. */ - if (!IsWow64Process(GetCurrentProcess(), &weAreWow64) || - !IsWow64Process(hProcess, &theyAreWow64)) { - PyErr_SetFromOSErrnoWithSyscall("IsWow64Process"); - goto error; - } - - if (weAreWow64 && !theyAreWow64) { - /* We are 32 bit running in WoW64 mode. Target process is 64 bit. */ - PROCESS_BASIC_INFORMATION64 pbi64; - PEB64 peb64; - RTL_USER_PROCESS_PARAMETERS64 procParameters64; - - if (NtWow64QueryInformationProcess64 == NULL) { - NtWow64QueryInformationProcess64 = \ - psutil_GetProcAddressFromLib( - "ntdll.dll", "NtWow64QueryInformationProcess64"); - if (NtWow64QueryInformationProcess64 == NULL) { - PyErr_Clear(); - AccessDenied("can't query 64-bit process in 32-bit-WoW mode"); - goto error; - } - } - if (NtWow64ReadVirtualMemory64 == NULL) { - NtWow64ReadVirtualMemory64 = \ - psutil_GetProcAddressFromLib( - "ntdll.dll", "NtWow64ReadVirtualMemory64"); - if (NtWow64ReadVirtualMemory64 == NULL) { - PyErr_Clear(); - AccessDenied("can't query 64-bit process in 32-bit-WoW mode"); - goto error; - } - } - - status = NtWow64QueryInformationProcess64( - hProcess, - ProcessBasicInformation, - &pbi64, - sizeof(pbi64), - NULL); - if (!NT_SUCCESS(status)) { - psutil_SetFromNTStatusErr( - status, - "NtWow64QueryInformationProcess64(ProcessBasicInformation)" - ); - goto error; - } - - // read peb - status = NtWow64ReadVirtualMemory64( - hProcess, - pbi64.PebBaseAddress, - &peb64, - sizeof(peb64), - NULL); - if (!NT_SUCCESS(status)) { - psutil_SetFromNTStatusErr(status, "NtWow64ReadVirtualMemory64"); - goto error; - } - - // read process parameters - status = NtWow64ReadVirtualMemory64( - hProcess, - peb64.ProcessParameters, - &procParameters64, - sizeof(procParameters64), - NULL); - if (!NT_SUCCESS(status)) { - psutil_SetFromNTStatusErr( - status, - "NtWow64ReadVirtualMemory64(ProcessParameters)" - ); - goto error; - } - - switch (kind) { - case KIND_CMDLINE: - src64 = procParameters64.CommandLine.Buffer; - size = procParameters64.CommandLine.Length; - break; - case KIND_CWD: - src64 = procParameters64.CurrentDirectoryPath.Buffer, - size = procParameters64.CurrentDirectoryPath.Length; - break; - case KIND_ENVIRON: - src64 = procParameters64.env; - break; - } - } else -#endif - /* Target process is of the same bitness as us. */ - { - PROCESS_BASIC_INFORMATION pbi; - PEB_ peb; - RTL_USER_PROCESS_PARAMETERS_ procParameters; - - status = psutil_NtQueryInformationProcess( - hProcess, - ProcessBasicInformation, - &pbi, - sizeof(pbi), - NULL); - - if (!NT_SUCCESS(status)) { - psutil_SetFromNTStatusErr( - status, "NtQueryInformationProcess(ProcessBasicInformation)"); - goto error; - } - - - // read peb - if (!ReadProcessMemory(hProcess, - pbi.PebBaseAddress, - &peb, - sizeof(peb), - NULL)) - { - // May fail with ERROR_PARTIAL_COPY, see: - // https://github.com/giampaolo/psutil/issues/875 - PyErr_SetFromWindowsErr(0); - goto error; - } - - // read process parameters - if (!ReadProcessMemory(hProcess, - peb.ProcessParameters, - &procParameters, - sizeof(procParameters), - NULL)) - { - // May fail with ERROR_PARTIAL_COPY, see: - // https://github.com/giampaolo/psutil/issues/875 - PyErr_SetFromWindowsErr(0); - goto error; - } - - switch (kind) { - case KIND_CMDLINE: - src = procParameters.CommandLine.Buffer; - size = procParameters.CommandLine.Length; - break; - case KIND_CWD: - src = procParameters.CurrentDirectoryPath.Buffer; - size = procParameters.CurrentDirectoryPath.Length; - break; - case KIND_ENVIRON: - src = procParameters.env; - break; - } - } - - if (kind == KIND_ENVIRON) { -#ifndef _WIN64 - if (weAreWow64 && !theyAreWow64) { - AccessDenied("can't query 64-bit process in 32-bit-WoW mode"); - goto error; - } - else -#endif - if (psutil_get_process_region_size(hProcess, src, &size) != 0) - goto error; - } - - buffer = calloc(size + 2, 1); - if (buffer == NULL) { - PyErr_NoMemory(); - goto error; - } - -#ifndef _WIN64 - if (weAreWow64 && !theyAreWow64) { - status = NtWow64ReadVirtualMemory64( - hProcess, - src64, - buffer, - size, - NULL); - if (!NT_SUCCESS(status)) { - psutil_SetFromNTStatusErr(status, "NtWow64ReadVirtualMemory64"); - goto error; - } - } else -#endif - if (!ReadProcessMemory(hProcess, src, buffer, size, NULL)) { - // May fail with ERROR_PARTIAL_COPY, see: - // https://github.com/giampaolo/psutil/issues/875 - PyErr_SetFromWindowsErr(0); - goto error; - } - - CloseHandle(hProcess); - - *pdata = buffer; - *psize = size; - - return 0; - -error: - if (hProcess != NULL) - CloseHandle(hProcess); - if (buffer != NULL) - free(buffer); - return -1; -} - - -/* - * Get process cmdline by using NtQueryInformationProcess. This is a - * method alternative to PEB which is less likely to result in - * AccessDenied. Requires Windows 8.1+. - */ -static int -psutil_cmdline_query_proc(long pid, WCHAR **pdata, SIZE_T *psize) { - HANDLE hProcess; - ULONG bufLen = 0; - NTSTATUS status; - char * buffer = NULL; - WCHAR * bufWchar = NULL; - PUNICODE_STRING tmp = NULL; - size_t size; - int ProcessCommandLineInformation = 60; - - if (PSUTIL_WINVER < PSUTIL_WINDOWS_8_1) { - PyErr_SetString( - PyExc_RuntimeError, "requires Windows 8.1+"); - goto error; - } - - hProcess = psutil_handle_from_pid(pid, PROCESS_QUERY_LIMITED_INFORMATION); - if (hProcess == NULL) - goto error; - - // get the right buf size - status = psutil_NtQueryInformationProcess( - hProcess, - ProcessCommandLineInformation, - NULL, - 0, - &bufLen); - - // 0xC0000225 == STATUS_NOT_FOUND, see: - // https://github.com/giampaolo/psutil/issues/1501 - if (status == 0xC0000225) { - AccessDenied("NtQueryInformationProcess(ProcessBasicInformation) -> " - "STATUS_NOT_FOUND translated into PermissionError"); - goto error; - } - - if (status != STATUS_BUFFER_OVERFLOW && \ - status != STATUS_BUFFER_TOO_SMALL && \ - status != STATUS_INFO_LENGTH_MISMATCH) { - psutil_SetFromNTStatusErr( - status, "NtQueryInformationProcess(ProcessBasicInformation)"); - goto error; - } - - // allocate memory - buffer = calloc(bufLen, 1); - if (buffer == NULL) { - PyErr_NoMemory(); - goto error; - } - - // get the cmdline - status = psutil_NtQueryInformationProcess( - hProcess, - ProcessCommandLineInformation, - buffer, - bufLen, - &bufLen - ); - if (!NT_SUCCESS(status)) { - psutil_SetFromNTStatusErr( - status, "NtQueryInformationProcess(ProcessCommandLineInformation)"); - goto error; - } - - // build the string - tmp = (PUNICODE_STRING)buffer; - size = wcslen(tmp->Buffer) + 1; - bufWchar = (WCHAR *)calloc(size, sizeof(WCHAR)); - if (bufWchar == NULL) { - PyErr_NoMemory(); - goto error; - } - wcscpy_s(bufWchar, size, tmp->Buffer); - *pdata = bufWchar; - *psize = size * sizeof(WCHAR); - free(buffer); - CloseHandle(hProcess); - return 0; - -error: - if (buffer != NULL) - free(buffer); - if (hProcess != NULL) - CloseHandle(hProcess); - return -1; -} - - -/* - * Return a Python list representing the arguments for the process - * with given pid or NULL on error. - */ -PyObject * -psutil_get_cmdline(long pid, int use_peb) { - PyObject *ret = NULL; - WCHAR *data = NULL; - SIZE_T size; - PyObject *py_retlist = NULL; - PyObject *py_unicode = NULL; - LPWSTR *szArglist = NULL; - int nArgs, i; - int func_ret; - - /* - Reading the PEB to get the cmdline seem to be the best method if - somebody has tampered with the parameters after creating the process. - For instance, create a process as suspended, patch the command line - in its PEB and unfreeze it. It requires more privileges than - NtQueryInformationProcess though (the fallback): - - https://github.com/giampaolo/psutil/pull/1398 - - https://blog.xpnsec.com/how-to-argue-like-cobalt-strike/ - */ - if (use_peb == 1) - func_ret = psutil_get_process_data(pid, KIND_CMDLINE, &data, &size); - else - func_ret = psutil_cmdline_query_proc(pid, &data, &size); - if (func_ret != 0) - goto out; - - // attempt to parse the command line using Win32 API - szArglist = CommandLineToArgvW(data, &nArgs); - if (szArglist == NULL) { - PyErr_SetFromOSErrnoWithSyscall("CommandLineToArgvW"); - goto out; - } - - // arglist parsed as array of UNICODE_STRING, so convert each to - // Python string object and add to arg list - py_retlist = PyList_New(nArgs); - if (py_retlist == NULL) - goto out; - for (i = 0; i < nArgs; i++) { - py_unicode = PyUnicode_FromWideChar(szArglist[i], - wcslen(szArglist[i])); - if (py_unicode == NULL) - goto out; - PyList_SET_ITEM(py_retlist, i, py_unicode); - py_unicode = NULL; - } - ret = py_retlist; - py_retlist = NULL; - -out: - if (szArglist != NULL) - LocalFree(szArglist); - if (data != NULL) - free(data); - Py_XDECREF(py_unicode); - Py_XDECREF(py_retlist); - return ret; -} - - -PyObject * -psutil_get_cwd(long pid) { - PyObject *ret = NULL; - WCHAR *data = NULL; - SIZE_T size; - - if (psutil_get_process_data(pid, KIND_CWD, &data, &size) != 0) - goto out; - - // convert wchar array to a Python unicode string - ret = PyUnicode_FromWideChar(data, wcslen(data)); - -out: - if (data != NULL) - free(data); - - return ret; -} - - -/* - * returns a Python string containing the environment variable data for the - * process with given pid or NULL on error. - */ -PyObject * -psutil_get_environ(long pid) { - PyObject *ret = NULL; - WCHAR *data = NULL; - SIZE_T size; - - if (psutil_get_process_data(pid, KIND_ENVIRON, &data, &size) != 0) - goto out; - - // convert wchar array to a Python unicode string - ret = PyUnicode_FromWideChar(data, size / 2); - -out: - if (data != NULL) - free(data); - return ret; -} - - -/* - * Given a process PID and a PSYSTEM_PROCESS_INFORMATION structure - * fills the structure with various process information by using - * NtQuerySystemInformation. - * We use this as a fallback when faster functions fail with access - * denied. This is slower because it iterates over all processes. - * On success return 1, else 0 with Python exception already set. - */ -int -psutil_get_proc_info(DWORD pid, PSYSTEM_PROCESS_INFORMATION *retProcess, - PVOID *retBuffer) { - static ULONG initialBufferSize = 0x4000; - NTSTATUS status; - PVOID buffer; - ULONG bufferSize; - PSYSTEM_PROCESS_INFORMATION process; - - bufferSize = initialBufferSize; - buffer = malloc(bufferSize); - if (buffer == NULL) { - PyErr_NoMemory(); - goto error; - } - - while (TRUE) { - status = psutil_NtQuerySystemInformation( - SystemProcessInformation, - buffer, - bufferSize, - &bufferSize); - if (status == STATUS_BUFFER_TOO_SMALL || - status == STATUS_INFO_LENGTH_MISMATCH) - { - free(buffer); - buffer = malloc(bufferSize); - if (buffer == NULL) { - PyErr_NoMemory(); - goto error; - } - } - else { - break; - } - } - - if (! NT_SUCCESS(status)) { - psutil_SetFromNTStatusErr( - status, "NtQuerySystemInformation(SystemProcessInformation)"); - goto error; - } - - if (bufferSize <= 0x20000) - initialBufferSize = bufferSize; - - process = PSUTIL_FIRST_PROCESS(buffer); - do { - if (process->UniqueProcessId == (HANDLE)pid) { - *retProcess = process; - *retBuffer = buffer; - return 1; - } - } while ( (process = PSUTIL_NEXT_PROCESS(process)) ); - - NoSuchProcess(""); - goto error; - -error: - if (buffer != NULL) - free(buffer); - return 0; -} diff --git a/ddtrace/vendor/psutil/arch/windows/process_info.h b/ddtrace/vendor/psutil/arch/windows/process_info.h deleted file mode 100644 index 4278c4df9e0..00000000000 --- a/ddtrace/vendor/psutil/arch/windows/process_info.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, 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. - */ - -#if !defined(__PROCESS_INFO_H) -#define __PROCESS_INFO_H - -#include -#include -#include "security.h" -#include "ntextapi.h" - -#define HANDLE_TO_PYNUM(handle) PyLong_FromUnsignedLong((unsigned long) handle) -#define PYNUM_TO_HANDLE(obj) ((HANDLE)PyLong_AsUnsignedLong(obj)) - -DWORD* psutil_get_pids(DWORD *numberOfReturnedPIDs); -HANDLE psutil_handle_from_pid(DWORD pid, DWORD dwDesiredAccess); -int psutil_pid_is_running(DWORD pid); -int psutil_get_proc_info(DWORD pid, PSYSTEM_PROCESS_INFORMATION *retProcess, - PVOID *retBuffer); - -int psutil_assert_pid_exists(DWORD pid, char *err); -int psutil_assert_pid_not_exists(DWORD pid, char *err); - -PyObject* psutil_get_cmdline(long pid, int use_peb); -PyObject* psutil_get_cwd(long pid); -PyObject* psutil_get_environ(long pid); - -#endif diff --git a/ddtrace/vendor/psutil/arch/windows/security.c b/ddtrace/vendor/psutil/arch/windows/security.c deleted file mode 100644 index 4e2c7435b22..00000000000 --- a/ddtrace/vendor/psutil/arch/windows/security.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, 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. - * - * Security related functions for Windows platform (Set privileges such as - * SE DEBUG). - */ - -#include -#include -#include "../../_psutil_common.h" - - -static BOOL -psutil_set_privilege(HANDLE hToken, LPCTSTR Privilege, BOOL bEnablePrivilege) { - TOKEN_PRIVILEGES tp; - LUID luid; - TOKEN_PRIVILEGES tpPrevious; - DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES); - - if (! LookupPrivilegeValue(NULL, Privilege, &luid)) { - PyErr_SetFromOSErrnoWithSyscall("LookupPrivilegeValue"); - return 1; - } - - // first pass. get current privilege setting - tp.PrivilegeCount = 1; - tp.Privileges[0].Luid = luid; - tp.Privileges[0].Attributes = 0; - - if (! AdjustTokenPrivileges( - hToken, - FALSE, - &tp, - sizeof(TOKEN_PRIVILEGES), - &tpPrevious, - &cbPrevious)) - { - PyErr_SetFromOSErrnoWithSyscall("AdjustTokenPrivileges"); - return 1; - } - - // Second pass. Set privilege based on previous setting. - tpPrevious.PrivilegeCount = 1; - tpPrevious.Privileges[0].Luid = luid; - - if (bEnablePrivilege) - tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED); - else - tpPrevious.Privileges[0].Attributes ^= - (SE_PRIVILEGE_ENABLED & tpPrevious.Privileges[0].Attributes); - - if (! AdjustTokenPrivileges( - hToken, - FALSE, - &tpPrevious, - cbPrevious, - NULL, - NULL)) - { - PyErr_SetFromOSErrnoWithSyscall("AdjustTokenPrivileges"); - return 1; - } - - return 0; -} - - -static HANDLE -psutil_get_thisproc_token() { - HANDLE hToken = NULL; - HANDLE me = GetCurrentProcess(); - - if (! OpenProcessToken( - me, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) - { - if (GetLastError() == ERROR_NO_TOKEN) - { - if (! ImpersonateSelf(SecurityImpersonation)) { - PyErr_SetFromOSErrnoWithSyscall("ImpersonateSelf"); - return NULL; - } - if (! OpenProcessToken( - me, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) - { - PyErr_SetFromOSErrnoWithSyscall("OpenProcessToken"); - return NULL; - } - } - else { - PyErr_SetFromOSErrnoWithSyscall("OpenProcessToken"); - return NULL; - } - } - - return hToken; -} - - -static void -psutil_print_err() { - char *msg = "psutil module couldn't set SE DEBUG mode for this process; " \ - "please file an issue against psutil bug tracker"; - psutil_debug(msg); - if (GetLastError() != ERROR_ACCESS_DENIED) - PyErr_WarnEx(PyExc_RuntimeWarning, msg, 1); - PyErr_Clear(); -} - - -/* - * Set this process in SE DEBUG mode so that we have more chances of - * querying processes owned by other users, including many owned by - * Administrator and Local System. - * https://docs.microsoft.com/windows-hardware/drivers/debugger/debug-privilege - * This is executed on module import and we don't crash on error. - */ -int -psutil_set_se_debug() { - HANDLE hToken; - int err = 1; - - if ((hToken = psutil_get_thisproc_token()) == NULL) { - // "return 1;" to get an exception - psutil_print_err(); - return 0; - } - - if (psutil_set_privilege(hToken, SE_DEBUG_NAME, TRUE) != 0) { - // "return 1;" to get an exception - psutil_print_err(); - } - - RevertToSelf(); - CloseHandle(hToken); - return 0; -} diff --git a/ddtrace/vendor/psutil/arch/windows/security.h b/ddtrace/vendor/psutil/arch/windows/security.h deleted file mode 100644 index 8d4ddb00d41..00000000000 --- a/ddtrace/vendor/psutil/arch/windows/security.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, 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. - * - * Security related functions for Windows platform (Set privileges such as - * SeDebug), as well as security helper functions. - */ - -#include - -int psutil_set_se_debug(); - diff --git a/ddtrace/vendor/psutil/arch/windows/services.c b/ddtrace/vendor/psutil/arch/windows/services.c deleted file mode 100644 index 92458494b4a..00000000000 --- a/ddtrace/vendor/psutil/arch/windows/services.c +++ /dev/null @@ -1,485 +0,0 @@ -/* - * 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. - */ - -#include -#include -#include - -#include "services.h" -#include "../../_psutil_common.h" - -// ================================================================== -// utils -// ================================================================== - -SC_HANDLE -psutil_get_service_handler(char *service_name, DWORD scm_access, DWORD access) -{ - ENUM_SERVICE_STATUS_PROCESSW *lpService = NULL; - SC_HANDLE sc = NULL; - SC_HANDLE hService = NULL; - - sc = OpenSCManager(NULL, NULL, scm_access); - if (sc == NULL) { - PyErr_SetFromOSErrnoWithSyscall("OpenSCManager"); - return NULL; - } - hService = OpenService(sc, service_name, access); - if (hService == NULL) { - PyErr_SetFromOSErrnoWithSyscall("OpenService"); - CloseServiceHandle(sc); - return NULL; - } - CloseServiceHandle(sc); - return hService; -} - - -// XXX - expose these as constants? -static const char * -get_startup_string(DWORD startup) { - switch (startup) { - case SERVICE_AUTO_START: - return "automatic"; - case SERVICE_DEMAND_START: - return "manual"; - case SERVICE_DISABLED: - return "disabled"; -/* - // drivers only (since we use EnumServicesStatusEx() with - // SERVICE_WIN32) - case SERVICE_BOOT_START: - return "boot-start"; - case SERVICE_SYSTEM_START: - return "system-start"; -*/ - default: - return "unknown"; - } -} - - -// XXX - expose these as constants? -static const char * -get_state_string(DWORD state) { - switch (state) { - case SERVICE_RUNNING: - return "running"; - case SERVICE_PAUSED: - return "paused"; - case SERVICE_START_PENDING: - return "start_pending"; - case SERVICE_PAUSE_PENDING: - return "pause_pending"; - case SERVICE_CONTINUE_PENDING: - return "continue_pending"; - case SERVICE_STOP_PENDING: - return "stop_pending"; - case SERVICE_STOPPED: - return "stopped"; - default: - return "unknown"; - } -} - - -// ================================================================== -// APIs -// ================================================================== - -/* - * Enumerate all services. - */ -PyObject * -psutil_winservice_enumerate(PyObject *self, PyObject *args) { - ENUM_SERVICE_STATUS_PROCESSW *lpService = NULL; - BOOL ok; - SC_HANDLE sc = NULL; - DWORD bytesNeeded = 0; - DWORD srvCount; - DWORD resumeHandle = 0; - DWORD dwBytes = 0; - DWORD i; - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - PyObject *py_name = NULL; - PyObject *py_display_name = NULL; - - if (py_retlist == NULL) - return NULL; - - sc = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE); - if (sc == NULL) { - PyErr_SetFromOSErrnoWithSyscall("OpenSCManager"); - return NULL; - } - - for (;;) { - ok = EnumServicesStatusExW( - sc, - SC_ENUM_PROCESS_INFO, - SERVICE_WIN32, // XXX - extend this to include drivers etc.? - SERVICE_STATE_ALL, - (LPBYTE)lpService, - dwBytes, - &bytesNeeded, - &srvCount, - &resumeHandle, - NULL); - if (ok || (GetLastError() != ERROR_MORE_DATA)) - break; - if (lpService) - free(lpService); - dwBytes = bytesNeeded; - lpService = (ENUM_SERVICE_STATUS_PROCESSW*)malloc(dwBytes); - } - - for (i = 0; i < srvCount; i++) { - // Get unicode name / display name. - py_name = NULL; - py_name = PyUnicode_FromWideChar( - lpService[i].lpServiceName, wcslen(lpService[i].lpServiceName)); - if (py_name == NULL) - goto error; - - py_display_name = NULL; - py_display_name = PyUnicode_FromWideChar( - lpService[i].lpDisplayName, wcslen(lpService[i].lpDisplayName)); - if (py_display_name == NULL) - goto error; - - // Construct the result. - py_tuple = Py_BuildValue("(OO)", py_name, py_display_name); - if (py_tuple == NULL) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_display_name); - Py_DECREF(py_name); - Py_DECREF(py_tuple); - } - - // Free resources. - CloseServiceHandle(sc); - free(lpService); - return py_retlist; - -error: - Py_DECREF(py_name); - Py_XDECREF(py_display_name); - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (sc != NULL) - CloseServiceHandle(sc); - if (lpService != NULL) - free(lpService); - return NULL; -} - - -/* - * Get service config information. Returns: - * - display_name - * - binpath - * - username - * - startup_type - */ -PyObject * -psutil_winservice_query_config(PyObject *self, PyObject *args) { - char *service_name; - SC_HANDLE hService = NULL; - BOOL ok; - DWORD bytesNeeded = 0; - DWORD resumeHandle = 0; - DWORD dwBytes = 0; - QUERY_SERVICE_CONFIGW *qsc = NULL; - PyObject *py_tuple = NULL; - PyObject *py_unicode_display_name = NULL; - PyObject *py_unicode_binpath = NULL; - PyObject *py_unicode_username = NULL; - - if (!PyArg_ParseTuple(args, "s", &service_name)) - return NULL; - hService = psutil_get_service_handler( - service_name, SC_MANAGER_ENUMERATE_SERVICE, SERVICE_QUERY_CONFIG); - if (hService == NULL) - goto error; - - // First call to QueryServiceConfigW() is necessary to get the - // right size. - bytesNeeded = 0; - QueryServiceConfigW(hService, NULL, 0, &bytesNeeded); - if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { - PyErr_SetFromOSErrnoWithSyscall("QueryServiceConfigW"); - goto error; - } - qsc = (QUERY_SERVICE_CONFIGW *)malloc(bytesNeeded); - ok = QueryServiceConfigW(hService, qsc, bytesNeeded, &bytesNeeded); - if (ok == 0) { - PyErr_SetFromOSErrnoWithSyscall("QueryServiceConfigW"); - goto error; - } - - // Get unicode display name. - py_unicode_display_name = PyUnicode_FromWideChar( - qsc->lpDisplayName, wcslen(qsc->lpDisplayName)); - if (py_unicode_display_name == NULL) - goto error; - - // Get unicode bin path. - py_unicode_binpath = PyUnicode_FromWideChar( - qsc->lpBinaryPathName, wcslen(qsc->lpBinaryPathName)); - if (py_unicode_binpath == NULL) - goto error; - - // Get unicode username. - py_unicode_username = PyUnicode_FromWideChar( - qsc->lpServiceStartName, wcslen(qsc->lpServiceStartName)); - if (py_unicode_username == NULL) - goto error; - - // Construct result tuple. - py_tuple = Py_BuildValue( - "(OOOs)", - py_unicode_display_name, - py_unicode_binpath, - py_unicode_username, - get_startup_string(qsc->dwStartType) // startup - ); - if (py_tuple == NULL) - goto error; - - // Free resources. - Py_DECREF(py_unicode_display_name); - Py_DECREF(py_unicode_binpath); - Py_DECREF(py_unicode_username); - free(qsc); - CloseServiceHandle(hService); - return py_tuple; - -error: - Py_XDECREF(py_unicode_display_name); - Py_XDECREF(py_unicode_binpath); - Py_XDECREF(py_unicode_username); - Py_XDECREF(py_tuple); - if (hService != NULL) - CloseServiceHandle(hService); - if (qsc != NULL) - free(qsc); - return NULL; -} - - -/* - * Get service status information. Returns: - * - status - * - pid - */ -PyObject * -psutil_winservice_query_status(PyObject *self, PyObject *args) { - char *service_name; - SC_HANDLE hService = NULL; - BOOL ok; - DWORD bytesNeeded = 0; - DWORD resumeHandle = 0; - DWORD dwBytes = 0; - SERVICE_STATUS_PROCESS *ssp = NULL; - PyObject *py_tuple = NULL; - - if (!PyArg_ParseTuple(args, "s", &service_name)) - return NULL; - hService = psutil_get_service_handler( - service_name, SC_MANAGER_ENUMERATE_SERVICE, SERVICE_QUERY_STATUS); - if (hService == NULL) - goto error; - - // First call to QueryServiceStatusEx() is necessary to get the - // right size. - QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, NULL, 0, - &bytesNeeded); - if (GetLastError() == ERROR_MUI_FILE_NOT_FOUND) { - // Also services.msc fails in the same manner, so we return an - // empty string. - CloseServiceHandle(hService); - return Py_BuildValue("s", ""); - } - if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { - PyErr_SetFromOSErrnoWithSyscall("QueryServiceStatusEx"); - goto error; - } - ssp = (SERVICE_STATUS_PROCESS *)HeapAlloc( - GetProcessHeap(), 0, bytesNeeded); - if (ssp == NULL) { - PyErr_NoMemory(); - goto error; - } - - // Actual call. - ok = QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)ssp, - bytesNeeded, &bytesNeeded); - if (ok == 0) { - PyErr_SetFromOSErrnoWithSyscall("QueryServiceStatusEx"); - goto error; - } - - py_tuple = Py_BuildValue( - "(sk)", - get_state_string(ssp->dwCurrentState), - ssp->dwProcessId - ); - if (py_tuple == NULL) - goto error; - - CloseServiceHandle(hService); - HeapFree(GetProcessHeap(), 0, ssp); - return py_tuple; - -error: - Py_XDECREF(py_tuple); - if (hService != NULL) - CloseServiceHandle(hService); - if (ssp != NULL) - HeapFree(GetProcessHeap(), 0, ssp); - return NULL; -} - - -/* - * Get service description. - */ -PyObject * -psutil_winservice_query_descr(PyObject *self, PyObject *args) { - ENUM_SERVICE_STATUS_PROCESSW *lpService = NULL; - BOOL ok; - DWORD bytesNeeded = 0; - DWORD resumeHandle = 0; - DWORD dwBytes = 0; - SC_HANDLE hService = NULL; - SERVICE_DESCRIPTIONW *scd = NULL; - char *service_name; - PyObject *py_retstr = NULL; - - if (!PyArg_ParseTuple(args, "s", &service_name)) - return NULL; - hService = psutil_get_service_handler( - service_name, SC_MANAGER_ENUMERATE_SERVICE, SERVICE_QUERY_CONFIG); - if (hService == NULL) - goto error; - - // This first call to QueryServiceConfig2W() is necessary in order - // to get the right size. - bytesNeeded = 0; - QueryServiceConfig2W(hService, SERVICE_CONFIG_DESCRIPTION, NULL, 0, - &bytesNeeded); - if (GetLastError() == ERROR_MUI_FILE_NOT_FOUND) { - // Also services.msc fails in the same manner, so we return an - // empty string. - CloseServiceHandle(hService); - return Py_BuildValue("s", ""); - } - if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { - PyErr_SetFromOSErrnoWithSyscall("QueryServiceConfig2W"); - goto error; - } - - scd = (SERVICE_DESCRIPTIONW *)malloc(bytesNeeded); - ok = QueryServiceConfig2W(hService, SERVICE_CONFIG_DESCRIPTION, - (LPBYTE)scd, bytesNeeded, &bytesNeeded); - if (ok == 0) { - PyErr_SetFromOSErrnoWithSyscall("QueryServiceConfig2W"); - goto error; - } - - if (scd->lpDescription == NULL) { - py_retstr = Py_BuildValue("s", ""); - } - else { - py_retstr = PyUnicode_FromWideChar( - scd->lpDescription, wcslen(scd->lpDescription)); - } - if (!py_retstr) - goto error; - - free(scd); - CloseServiceHandle(hService); - return py_retstr; - -error: - if (hService != NULL) - CloseServiceHandle(hService); - if (lpService != NULL) - free(lpService); - return NULL; -} - - -/* - * Start service. - * XXX - note: this is exposed but not used. - */ -PyObject * -psutil_winservice_start(PyObject *self, PyObject *args) { - char *service_name; - BOOL ok; - SC_HANDLE hService = NULL; - - if (!PyArg_ParseTuple(args, "s", &service_name)) - return NULL; - hService = psutil_get_service_handler( - service_name, SC_MANAGER_ALL_ACCESS, SERVICE_START); - if (hService == NULL) { - goto error; - } - ok = StartService(hService, 0, NULL); - if (ok == 0) { - PyErr_SetFromOSErrnoWithSyscall("StartService"); - goto error; - } - - Py_RETURN_NONE; - -error: - if (hService != NULL) - CloseServiceHandle(hService); - return NULL; -} - - -/* - * Stop service. - * XXX - note: this is exposed but not used. - */ -PyObject * -psutil_winservice_stop(PyObject *self, PyObject *args) { - char *service_name; - BOOL ok; - SC_HANDLE hService = NULL; - SERVICE_STATUS ssp; - - if (!PyArg_ParseTuple(args, "s", &service_name)) - return NULL; - hService = psutil_get_service_handler( - service_name, SC_MANAGER_ALL_ACCESS, SERVICE_STOP); - if (hService == NULL) - goto error; - - // Note: this can hang for 30 secs. - Py_BEGIN_ALLOW_THREADS - ok = ControlService(hService, SERVICE_CONTROL_STOP, &ssp); - Py_END_ALLOW_THREADS - if (ok == 0) { - PyErr_SetFromOSErrnoWithSyscall("ControlService"); - goto error; - } - - CloseServiceHandle(hService); - Py_RETURN_NONE; - -error: - if (hService != NULL) - CloseServiceHandle(hService); - return NULL; -} diff --git a/ddtrace/vendor/psutil/arch/windows/services.h b/ddtrace/vendor/psutil/arch/windows/services.h deleted file mode 100644 index 286ed232c90..00000000000 --- a/ddtrace/vendor/psutil/arch/windows/services.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * 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. - */ - -#include -#include - -SC_HANDLE psutil_get_service_handle( -char service_name, DWORD scm_access, DWORD access); -PyObject *psutil_winservice_enumerate(PyObject *self, PyObject *args); -PyObject *psutil_winservice_query_config(PyObject *self, PyObject *args); -PyObject *psutil_winservice_query_status(PyObject *self, PyObject *args); -PyObject *psutil_winservice_query_descr(PyObject *self, PyObject *args); -PyObject *psutil_winservice_start(PyObject *self, PyObject *args); -PyObject *psutil_winservice_stop(PyObject *self, PyObject *args); diff --git a/ddtrace/vendor/psutil/arch/windows/wmi.c b/ddtrace/vendor/psutil/arch/windows/wmi.c deleted file mode 100644 index f43d790c035..00000000000 --- a/ddtrace/vendor/psutil/arch/windows/wmi.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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. - * - * Functions related to the Windows Management Instrumentation API. - */ - -#include -#include -#include - -#include "../../_psutil_common.h" - - -// We use an exponentially weighted moving average, just like Unix systems do -// https://en.wikipedia.org/wiki/Load_(computing)#Unix-style_load_calculation -// -// These constants serve as the damping factor and are calculated with -// 1 / exp(sampling interval in seconds / window size in seconds) -// -// This formula comes from linux's include/linux/sched/loadavg.h -// https://github.com/torvalds/linux/blob/345671ea0f9258f410eb057b9ced9cefbbe5dc78/include/linux/sched/loadavg.h#L20-L23 -#define LOADAVG_FACTOR_1F 0.9200444146293232478931553241 -#define LOADAVG_FACTOR_5F 0.9834714538216174894737477501 -#define LOADAVG_FACTOR_15F 0.9944598480048967508795473394 -// The time interval in seconds between taking load counts, same as Linux -#define SAMPLING_INTERVAL 5 - -double load_avg_1m = 0; -double load_avg_5m = 0; -double load_avg_15m = 0; - - -VOID CALLBACK LoadAvgCallback(PVOID hCounter) { - PDH_FMT_COUNTERVALUE displayValue; - double currentLoad; - PDH_STATUS err; - - err = PdhGetFormattedCounterValue( - (PDH_HCOUNTER)hCounter, PDH_FMT_DOUBLE, 0, &displayValue); - // Skip updating the load if we can't get the value successfully - if (err != ERROR_SUCCESS) { - return; - } - currentLoad = displayValue.doubleValue; - - load_avg_1m = load_avg_1m * LOADAVG_FACTOR_1F + currentLoad * \ - (1.0 - LOADAVG_FACTOR_1F); - load_avg_5m = load_avg_5m * LOADAVG_FACTOR_5F + currentLoad * \ - (1.0 - LOADAVG_FACTOR_5F); - load_avg_15m = load_avg_15m * LOADAVG_FACTOR_15F + currentLoad * \ - (1.0 - LOADAVG_FACTOR_15F); -} - - -PyObject * -psutil_init_loadavg_counter(PyObject *self, PyObject *args) { - WCHAR *szCounterPath = L"\\System\\Processor Queue Length"; - PDH_STATUS s; - BOOL ret; - HQUERY hQuery; - HCOUNTER hCounter; - HANDLE event; - HANDLE waitHandle; - - if ((PdhOpenQueryW(NULL, 0, &hQuery)) != ERROR_SUCCESS) - goto error; - - s = PdhAddEnglishCounterW(hQuery, szCounterPath, 0, &hCounter); - if (s != ERROR_SUCCESS) - goto error; - - event = CreateEventW(NULL, FALSE, FALSE, L"LoadUpdateEvent"); - if (event == NULL) { - PyErr_SetFromWindowsErr(GetLastError()); - return NULL; - } - - s = PdhCollectQueryDataEx(hQuery, SAMPLING_INTERVAL, event); - if (s != ERROR_SUCCESS) - goto error; - - ret = RegisterWaitForSingleObject( - &waitHandle, - event, - (WAITORTIMERCALLBACK)LoadAvgCallback, - (PVOID) - hCounter, - INFINITE, - WT_EXECUTEDEFAULT); - - if (ret == 0) { - PyErr_SetFromWindowsErr(GetLastError()); - return NULL; - } - - Py_RETURN_NONE; - -error: - PyErr_SetExcFromWindowsErr(PyExc_OSError, 0); - return NULL; -} - - -/* - * Gets the emulated 1 minute, 5 minute and 15 minute load averages - * (processor queue length) for the system. - * `init_loadavg_counter` must be called before this function to engage the - * mechanism that records load values. - */ -PyObject * -psutil_get_loadavg(PyObject *self, PyObject *args) { - return Py_BuildValue("(ddd)", load_avg_1m, load_avg_5m, load_avg_15m); -} diff --git a/ddtrace/vendor/psutil/arch/windows/wmi.h b/ddtrace/vendor/psutil/arch/windows/wmi.h deleted file mode 100644 index 0210f2d699e..00000000000 --- a/ddtrace/vendor/psutil/arch/windows/wmi.h +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, 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. - */ - - - -#include - -PyObject* psutil_init_loadavg_counter(); -PyObject* psutil_get_loadavg(); diff --git a/ddtrace/vendor/psutil/setup.py b/ddtrace/vendor/psutil/setup.py deleted file mode 100644 index 21de235487c..00000000000 --- a/ddtrace/vendor/psutil/setup.py +++ /dev/null @@ -1,227 +0,0 @@ -__all__ = ["get_extensions"] - -import contextlib -import io -import os -import platform -from setuptools import Extension -import shutil -import sys -import tempfile - -POSIX = os.name == "posix" -WINDOWS = os.name == "nt" -LINUX = sys.platform.startswith("linux") -MACOS = sys.platform.startswith("darwin") -OSX = MACOS # deprecated alias -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", "solaris")) -AIX = sys.platform.startswith("aix") - - -@contextlib.contextmanager -def silenced_output(stream_name): - class DummyFile(io.BytesIO): - # see: https://github.com/giampaolo/psutil/issues/678 - errors = "ignore" - - def write(self, s): - pass - - orig = getattr(sys, stream_name) - try: - setattr(sys, stream_name, DummyFile()) - yield - finally: - setattr(sys, stream_name, orig) - - -def get_extensions(): - macros = [("PSUTIL_VERSION", 567)] - if POSIX: - macros.append(("PSUTIL_POSIX", 1)) - if BSD: - macros.append(("PSUTIL_BSD", 1)) - - sources = ["ddtrace/vendor/psutil/_psutil_common.c"] - if POSIX: - sources.append("ddtrace/vendor/psutil/_psutil_posix.c") - - if WINDOWS: - - def get_winver(): - win_maj, win_min = sys.getwindowsversion()[0:2] - return "0x0%s" % ((win_maj * 100) + win_min) - - if sys.getwindowsversion()[0] < 6: - msg = "this Windows version is too old (< Windows Vista); " - msg += "psutil 3.4.2 is the latest version which supports Windows " - msg += "2000, XP and 2003 server" - raise RuntimeError(msg) - - macros.append(("PSUTIL_WINDOWS", 1)) - macros.extend( - [ - # be nice to mingw, see: - # http://www.mingw.org/wiki/Use_more_recent_defined_functions - ("_WIN32_WINNT", get_winver()), - ("_AVAIL_WINVER_", get_winver()), - ("_CRT_SECURE_NO_WARNINGS", None), - # see: https://github.com/giampaolo/psutil/issues/348 - ("PSAPI_VERSION", 1), - ] - ) - - sources += [ - "ddtrace/vendor/psutil/_psutil_windows.c", - "ddtrace/vendor/psutil/arch/windows/process_info.c", - "ddtrace/vendor/psutil/arch/windows/process_handles.c", - "ddtrace/vendor/psutil/arch/windows/security.c", - "ddtrace/vendor/psutil/arch/windows/inet_ntop.c", - "ddtrace/vendor/psutil/arch/windows/services.c", - "ddtrace/vendor/psutil/arch/windows/global.c", - "ddtrace/vendor/psutil/arch/windows/wmi.c", - ] - ext = Extension( - "ddtrace.vendor.psutil._psutil_windows", - sources=sources, - define_macros=macros, - libraries=[ - "psapi", - "kernel32", - "advapi32", - "shell32", - "netapi32", - "wtsapi32", - "ws2_32", - "PowrProf", - "pdh", - ], - # extra_compile_args=["/Z7"], - # extra_link_args=["/DEBUG"] - ) - - elif MACOS: - macros.append(("PSUTIL_OSX", 1)) - sources += [ - "ddtrace/vendor/psutil/_psutil_osx.c", - "ddtrace/vendor/psutil/arch/osx/process_info.c", - ] - ext = Extension( - "ddtrace.vendor.psutil._psutil_osx", - sources=sources, - define_macros=macros, - extra_link_args=["-framework", "CoreFoundation", "-framework", "IOKit"], - ) - - elif FREEBSD: - macros.append(("PSUTIL_FREEBSD", 1)) - sources += [ - "ddtrace/vendor/psutil/_psutil_bsd.c", - "ddtrace/vendor/psutil/arch/freebsd/specific.c", - "ddtrace/vendor/psutil/arch/freebsd/sys_socks.c", - "ddtrace/vendor/psutil/arch/freebsd/proc_socks.c", - ] - ext = Extension( - "ddtrace.vendor.psutil._psutil_bsd", sources=sources, define_macros=macros, libraries=["devstat"], - ) - - elif OPENBSD: - macros.append(("PSUTIL_OPENBSD", 1)) - ext = Extension( - "ddtrace.vendor.psutil._psutil_bsd", - sources=sources + ["ddtrace/vendor/psutil/_psutil_bsd.c", "ddtrace/vendor/psutil/arch/openbsd/specific.c"], - define_macros=macros, - libraries=["kvm"], - ) - - elif NETBSD: - macros.append(("PSUTIL_NETBSD", 1)) - sources += [ - "ddtrace/vendor/psutil/_psutil_bsd.c", - "ddtrace/vendor/psutil/arch/netbsd/specific.c", - "ddtrace/vendor/psutil/arch/netbsd/socks.c", - ] - ext = Extension("ddtrace.vendor.psutil._psutil_bsd", sources=sources, define_macros=macros, libraries=["kvm"],) - - elif LINUX: - - def get_ethtool_macro(): - # see: https://github.com/giampaolo/ddtrace/vendor/psutil/issues/659 - from distutils.unixccompiler import UnixCCompiler - from distutils.errors import CompileError - - with tempfile.NamedTemporaryFile(suffix=".c", delete=False, mode="wt") as f: - f.write("#include ") - - output_dir = tempfile.mkdtemp() - try: - compiler = UnixCCompiler() - # https://github.com/giampaolo/ddtrace/vendor/psutil/pull/1568 - if os.getenv("CC"): - compiler.set_executable("compiler_so", os.getenv("CC")) - with silenced_output("stderr"): - with silenced_output("stdout"): - compiler.compile([f.name], output_dir=output_dir) - except CompileError: - return ("PSUTIL_ETHTOOL_MISSING_TYPES", 1) - else: - return None - finally: - os.remove(f.name) - shutil.rmtree(output_dir) - - macros.append(("PSUTIL_LINUX", 1)) - ETHTOOL_MACRO = get_ethtool_macro() - if ETHTOOL_MACRO is not None: - macros.append(ETHTOOL_MACRO) - ext = Extension( - "ddtrace.vendor.psutil._psutil_linux", - sources=sources + ["ddtrace/vendor/psutil/_psutil_linux.c"], - define_macros=macros, - ) - - elif SUNOS: - macros.append(("PSUTIL_SUNOS", 1)) - sources += [ - "ddtrace/vendor/psutil/_psutil_sunos.c", - "ddtrace/vendor/psutil/arch/solaris/v10/ifaddrs.c", - "ddtrace/vendor/psutil/arch/solaris/environ.c", - ] - ext = Extension( - "ddtrace.vendor.psutil._psutil_sunos", - sources=sources, - define_macros=macros, - libraries=["kstat", "nsl", "socket"], - ) - - elif AIX: - macros.append(("PSUTIL_AIX", 1)) - sources += [ - "ddtrace/vendor/psutil/_psutil_aix.c", - "ddtrace/vendor/psutil/arch/aix/net_connections.c", - "ddtrace/vendor/psutil/arch/aix/common.c", - "ddtrace/vendor/psutil/arch/aix/ifaddrs.c", - ] - ext = Extension( - "ddtrace.vendor.psutil._psutil_aix", sources=sources, libraries=["perfstat"], define_macros=macros, - ) - else: - raise RuntimeError("platform %s is not supported" % sys.platform) - - if POSIX: - posix_extension = Extension("ddtrace.vendor.psutil._psutil_posix", define_macros=macros, sources=sources) - if SUNOS: - posix_extension.libraries.append("socket") - if platform.release() == "5.10": - posix_extension.sources.append("ddtrace/vendor/psutil/arch/solaris/v10/ifaddrs.c") - posix_extension.define_macros.append(("PSUTIL_SUNOS10", 1)) - elif AIX: - posix_extension.sources.append("ddtrace/vendor/psutil/arch/aix/ifaddrs.c") - - return [ext, posix_extension] - else: - return [ext] diff --git a/ddtrace/vendor/wrapt/LICENSE b/ddtrace/vendor/wrapt/LICENSE deleted file mode 100644 index fa5e1558c14..00000000000 --- a/ddtrace/vendor/wrapt/LICENSE +++ /dev/null @@ -1,24 +0,0 @@ -Copyright (c) 2013-2022, Graham Dumpleton -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/ddtrace/vendor/wrapt/__init__.py b/ddtrace/vendor/wrapt/__init__.py deleted file mode 100644 index ee6539b774a..00000000000 --- a/ddtrace/vendor/wrapt/__init__.py +++ /dev/null @@ -1,27 +0,0 @@ -__version_info__ = ('1', '14', '1') -__version__ = '.'.join(__version_info__) - -from .wrappers import (ObjectProxy, CallableObjectProxy, FunctionWrapper, - BoundFunctionWrapper, WeakFunctionProxy, PartialCallableObjectProxy, - resolve_path, apply_patch, wrap_object, wrap_object_attribute, - function_wrapper, wrap_function_wrapper, patch_function_wrapper, - transient_function_wrapper) - -from .decorators import (adapter_factory, AdapterFactory, decorator, - synchronized) - -from .importer import (register_post_import_hook, when_imported, - notify_module_loaded, discover_post_import_hooks) - -# Import of inspect.getcallargs() included for backward compatibility. An -# implementation of this was previously bundled and made available here for -# Python <2.7. Avoid using this in future. - -from inspect import getcallargs - -# Variant of inspect.formatargspec() included here for forward compatibility. -# This is being done because Python 3.11 dropped inspect.formatargspec() but -# code for handling signature changing decorators relied on it. Exposing the -# bundled implementation here in case any user of wrapt was also needing it. - -from .arguments import formatargspec diff --git a/ddtrace/vendor/wrapt/_wrappers.c b/ddtrace/vendor/wrapt/_wrappers.c deleted file mode 100644 index 67c5d5e1afd..00000000000 --- a/ddtrace/vendor/wrapt/_wrappers.c +++ /dev/null @@ -1,3199 +0,0 @@ -/* ------------------------------------------------------------------------- */ - -#include "Python.h" - -#include "structmember.h" - -#ifndef PyVarObject_HEAD_INIT -#define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, -#endif - -/* ------------------------------------------------------------------------- */ - -typedef struct { - PyObject_HEAD - - PyObject *dict; - PyObject *wrapped; - PyObject *weakreflist; -} WraptObjectProxyObject; - -PyTypeObject WraptObjectProxy_Type; -PyTypeObject WraptCallableObjectProxy_Type; - -typedef struct { - WraptObjectProxyObject object_proxy; - - PyObject *args; - PyObject *kwargs; -} WraptPartialCallableObjectProxyObject; - -PyTypeObject WraptPartialCallableObjectProxy_Type; - -typedef struct { - WraptObjectProxyObject object_proxy; - - PyObject *instance; - PyObject *wrapper; - PyObject *enabled; - PyObject *binding; - PyObject *parent; -} WraptFunctionWrapperObject; - -PyTypeObject WraptFunctionWrapperBase_Type; -PyTypeObject WraptBoundFunctionWrapper_Type; -PyTypeObject WraptFunctionWrapper_Type; - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_new(PyTypeObject *type, - PyObject *args, PyObject *kwds) -{ - WraptObjectProxyObject *self; - - self = (WraptObjectProxyObject *)type->tp_alloc(type, 0); - - if (!self) - return NULL; - - self->dict = PyDict_New(); - self->wrapped = NULL; - self->weakreflist = NULL; - - return (PyObject *)self; -} - -/* ------------------------------------------------------------------------- */ - -static int WraptObjectProxy_raw_init(WraptObjectProxyObject *self, - PyObject *wrapped) -{ - static PyObject *module_str = NULL; - static PyObject *doc_str = NULL; - - PyObject *object = NULL; - - Py_INCREF(wrapped); - Py_XDECREF(self->wrapped); - self->wrapped = wrapped; - - if (!module_str) { -#if PY_MAJOR_VERSION >= 3 - module_str = PyUnicode_InternFromString("__module__"); -#else - module_str = PyString_InternFromString("__module__"); -#endif - } - - if (!doc_str) { -#if PY_MAJOR_VERSION >= 3 - doc_str = PyUnicode_InternFromString("__doc__"); -#else - doc_str = PyString_InternFromString("__doc__"); -#endif - } - - object = PyObject_GetAttr(wrapped, module_str); - - if (object) { - if (PyDict_SetItem(self->dict, module_str, object) == -1) { - Py_DECREF(object); - return -1; - } - Py_DECREF(object); - } - else - PyErr_Clear(); - - object = PyObject_GetAttr(wrapped, doc_str); - - if (object) { - if (PyDict_SetItem(self->dict, doc_str, object) == -1) { - Py_DECREF(object); - return -1; - } - Py_DECREF(object); - } - else - PyErr_Clear(); - - return 0; -} - -/* ------------------------------------------------------------------------- */ - -static int WraptObjectProxy_init(WraptObjectProxyObject *self, - PyObject *args, PyObject *kwds) -{ - PyObject *wrapped = NULL; - - static char *kwlist[] = { "wrapped", NULL }; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:ObjectProxy", - kwlist, &wrapped)) { - return -1; - } - - return WraptObjectProxy_raw_init(self, wrapped); -} - -/* ------------------------------------------------------------------------- */ - -static int WraptObjectProxy_traverse(WraptObjectProxyObject *self, - visitproc visit, void *arg) -{ - Py_VISIT(self->dict); - Py_VISIT(self->wrapped); - - return 0; -} - -/* ------------------------------------------------------------------------- */ - -static int WraptObjectProxy_clear(WraptObjectProxyObject *self) -{ - Py_CLEAR(self->dict); - Py_CLEAR(self->wrapped); - - return 0; -} - -/* ------------------------------------------------------------------------- */ - -static void WraptObjectProxy_dealloc(WraptObjectProxyObject *self) -{ - PyObject_GC_UnTrack(self); - - if (self->weakreflist != NULL) - PyObject_ClearWeakRefs((PyObject *)self); - - WraptObjectProxy_clear(self); - - Py_TYPE(self)->tp_free(self); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_repr(WraptObjectProxyObject *self) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromFormat("<%s at %p for %s at %p>", - Py_TYPE(self)->tp_name, self, - Py_TYPE(self->wrapped)->tp_name, self->wrapped); -#else - return PyString_FromFormat("<%s at %p for %s at %p>", - Py_TYPE(self)->tp_name, self, - Py_TYPE(self->wrapped)->tp_name, self->wrapped); -#endif -} - -/* ------------------------------------------------------------------------- */ - -#if PY_MAJOR_VERSION < 3 || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 3) -typedef long Py_hash_t; -#endif - -static Py_hash_t WraptObjectProxy_hash(WraptObjectProxyObject *self) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return -1; - } - - return PyObject_Hash(self->wrapped); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_str(WraptObjectProxyObject *self) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - return PyObject_Str(self->wrapped); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_add(PyObject *o1, PyObject *o2) -{ - if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o1)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o1 = ((WraptObjectProxyObject *)o1)->wrapped; - } - - if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o2)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o2 = ((WraptObjectProxyObject *)o2)->wrapped; - } - - return PyNumber_Add(o1, o2); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_subtract(PyObject *o1, PyObject *o2) -{ - if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o1)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o1 = ((WraptObjectProxyObject *)o1)->wrapped; - } - - if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o2)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o2 = ((WraptObjectProxyObject *)o2)->wrapped; - } - - - return PyNumber_Subtract(o1, o2); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_multiply(PyObject *o1, PyObject *o2) -{ - if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o1)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o1 = ((WraptObjectProxyObject *)o1)->wrapped; - } - - if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o2)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o2 = ((WraptObjectProxyObject *)o2)->wrapped; - } - - return PyNumber_Multiply(o1, o2); -} - -/* ------------------------------------------------------------------------- */ - -#if PY_MAJOR_VERSION < 3 -static PyObject *WraptObjectProxy_divide(PyObject *o1, PyObject *o2) -{ - if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o1)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o1 = ((WraptObjectProxyObject *)o1)->wrapped; - } - - if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o2)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o2 = ((WraptObjectProxyObject *)o2)->wrapped; - } - - return PyNumber_Divide(o1, o2); -} -#endif - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_remainder(PyObject *o1, PyObject *o2) -{ - if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o1)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o1 = ((WraptObjectProxyObject *)o1)->wrapped; - } - - if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o2)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o2 = ((WraptObjectProxyObject *)o2)->wrapped; - } - - return PyNumber_Remainder(o1, o2); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_divmod(PyObject *o1, PyObject *o2) -{ - if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o1)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o1 = ((WraptObjectProxyObject *)o1)->wrapped; - } - - if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o2)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o2 = ((WraptObjectProxyObject *)o2)->wrapped; - } - - return PyNumber_Divmod(o1, o2); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_power(PyObject *o1, PyObject *o2, - PyObject *modulo) -{ - if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o1)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o1 = ((WraptObjectProxyObject *)o1)->wrapped; - } - - if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o2)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o2 = ((WraptObjectProxyObject *)o2)->wrapped; - } - - return PyNumber_Power(o1, o2, modulo); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_negative(WraptObjectProxyObject *self) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - return PyNumber_Negative(self->wrapped); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_positive(WraptObjectProxyObject *self) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - return PyNumber_Positive(self->wrapped); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_absolute(WraptObjectProxyObject *self) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - return PyNumber_Absolute(self->wrapped); -} - -/* ------------------------------------------------------------------------- */ - -static int WraptObjectProxy_bool(WraptObjectProxyObject *self) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return -1; - } - - return PyObject_IsTrue(self->wrapped); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_invert(WraptObjectProxyObject *self) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - return PyNumber_Invert(self->wrapped); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_lshift(PyObject *o1, PyObject *o2) -{ - if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o1)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o1 = ((WraptObjectProxyObject *)o1)->wrapped; - } - - if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o2)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o2 = ((WraptObjectProxyObject *)o2)->wrapped; - } - - return PyNumber_Lshift(o1, o2); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_rshift(PyObject *o1, PyObject *o2) -{ - if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o1)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o1 = ((WraptObjectProxyObject *)o1)->wrapped; - } - - if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o2)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o2 = ((WraptObjectProxyObject *)o2)->wrapped; - } - - return PyNumber_Rshift(o1, o2); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_and(PyObject *o1, PyObject *o2) -{ - if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o1)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o1 = ((WraptObjectProxyObject *)o1)->wrapped; - } - - if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o2)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o2 = ((WraptObjectProxyObject *)o2)->wrapped; - } - - return PyNumber_And(o1, o2); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_xor(PyObject *o1, PyObject *o2) -{ - if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o1)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o1 = ((WraptObjectProxyObject *)o1)->wrapped; - } - - if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o2)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o2 = ((WraptObjectProxyObject *)o2)->wrapped; - } - - return PyNumber_Xor(o1, o2); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_or(PyObject *o1, PyObject *o2) -{ - if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o1)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o1 = ((WraptObjectProxyObject *)o1)->wrapped; - } - - if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o2)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o2 = ((WraptObjectProxyObject *)o2)->wrapped; - } - - return PyNumber_Or(o1, o2); -} - -/* ------------------------------------------------------------------------- */ - -#if PY_MAJOR_VERSION < 3 -static PyObject *WraptObjectProxy_int(WraptObjectProxyObject *self) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - return PyNumber_Int(self->wrapped); -} -#endif - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_long(WraptObjectProxyObject *self) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - return PyNumber_Long(self->wrapped); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_float(WraptObjectProxyObject *self) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - return PyNumber_Float(self->wrapped); -} - -/* ------------------------------------------------------------------------- */ - -#if PY_MAJOR_VERSION < 3 -static PyObject *WraptObjectProxy_oct(WraptObjectProxyObject *self) -{ - PyNumberMethods *nb; - - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - if ((nb = self->wrapped->ob_type->tp_as_number) == NULL || - nb->nb_oct == NULL) { - PyErr_SetString(PyExc_TypeError, - "oct() argument can't be converted to oct"); - return NULL; - } - - return (*nb->nb_oct)(self->wrapped); -} -#endif - -/* ------------------------------------------------------------------------- */ - -#if PY_MAJOR_VERSION < 3 -static PyObject *WraptObjectProxy_hex(WraptObjectProxyObject *self) -{ - PyNumberMethods *nb; - - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - if ((nb = self->wrapped->ob_type->tp_as_number) == NULL || - nb->nb_hex == NULL) { - PyErr_SetString(PyExc_TypeError, - "hex() argument can't be converted to hex"); - return NULL; - } - - return (*nb->nb_hex)(self->wrapped); -} -#endif - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_inplace_add(WraptObjectProxyObject *self, - PyObject *other) -{ - PyObject *object = NULL; - - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) - other = ((WraptObjectProxyObject *)other)->wrapped; - - object = PyNumber_InPlaceAdd(self->wrapped, other); - - if (!object) - return NULL; - - Py_DECREF(self->wrapped); - self->wrapped = object; - - Py_INCREF(self); - return (PyObject *)self; -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_inplace_subtract( - WraptObjectProxyObject *self, PyObject *other) -{ - PyObject *object = NULL; - - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) - other = ((WraptObjectProxyObject *)other)->wrapped; - - object = PyNumber_InPlaceSubtract(self->wrapped, other); - - if (!object) - return NULL; - - Py_DECREF(self->wrapped); - self->wrapped = object; - - Py_INCREF(self); - return (PyObject *)self; -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_inplace_multiply( - WraptObjectProxyObject *self, PyObject *other) -{ - PyObject *object = NULL; - - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) - other = ((WraptObjectProxyObject *)other)->wrapped; - - object = PyNumber_InPlaceMultiply(self->wrapped, other); - - if (!object) - return NULL; - - Py_DECREF(self->wrapped); - self->wrapped = object; - - Py_INCREF(self); - return (PyObject *)self; -} - -/* ------------------------------------------------------------------------- */ - -#if PY_MAJOR_VERSION < 3 -static PyObject *WraptObjectProxy_inplace_divide( - WraptObjectProxyObject *self, PyObject *other) -{ - PyObject *object = NULL; - - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) - other = ((WraptObjectProxyObject *)other)->wrapped; - - object = PyNumber_InPlaceDivide(self->wrapped, other); - - if (!object) - return NULL; - - Py_DECREF(self->wrapped); - self->wrapped = object; - - Py_INCREF(self); - return (PyObject *)self; -} -#endif - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_inplace_remainder( - WraptObjectProxyObject *self, PyObject *other) -{ - PyObject *object = NULL; - - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) - other = ((WraptObjectProxyObject *)other)->wrapped; - - object = PyNumber_InPlaceRemainder(self->wrapped, other); - - if (!object) - return NULL; - - Py_DECREF(self->wrapped); - self->wrapped = object; - - Py_INCREF(self); - return (PyObject *)self; -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_inplace_power(WraptObjectProxyObject *self, - PyObject *other, PyObject *modulo) -{ - PyObject *object = NULL; - - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) - other = ((WraptObjectProxyObject *)other)->wrapped; - - object = PyNumber_InPlacePower(self->wrapped, other, modulo); - - if (!object) - return NULL; - - Py_DECREF(self->wrapped); - self->wrapped = object; - - Py_INCREF(self); - return (PyObject *)self; -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_inplace_lshift(WraptObjectProxyObject *self, - PyObject *other) -{ - PyObject *object = NULL; - - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) - other = ((WraptObjectProxyObject *)other)->wrapped; - - object = PyNumber_InPlaceLshift(self->wrapped, other); - - if (!object) - return NULL; - - Py_DECREF(self->wrapped); - self->wrapped = object; - - Py_INCREF(self); - return (PyObject *)self; -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_inplace_rshift(WraptObjectProxyObject *self, - PyObject *other) -{ - PyObject *object = NULL; - - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) - other = ((WraptObjectProxyObject *)other)->wrapped; - - object = PyNumber_InPlaceRshift(self->wrapped, other); - - if (!object) - return NULL; - - Py_DECREF(self->wrapped); - self->wrapped = object; - - Py_INCREF(self); - return (PyObject *)self; -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_inplace_and(WraptObjectProxyObject *self, - PyObject *other) -{ - PyObject *object = NULL; - - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) - other = ((WraptObjectProxyObject *)other)->wrapped; - - object = PyNumber_InPlaceAnd(self->wrapped, other); - - if (!object) - return NULL; - - Py_DECREF(self->wrapped); - self->wrapped = object; - - Py_INCREF(self); - return (PyObject *)self; -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_inplace_xor(WraptObjectProxyObject *self, - PyObject *other) -{ - PyObject *object = NULL; - - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) - other = ((WraptObjectProxyObject *)other)->wrapped; - - object = PyNumber_InPlaceXor(self->wrapped, other); - - if (!object) - return NULL; - - Py_DECREF(self->wrapped); - self->wrapped = object; - - Py_INCREF(self); - return (PyObject *)self; -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_inplace_or(WraptObjectProxyObject *self, - PyObject *other) -{ - PyObject *object = NULL; - - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) - other = ((WraptObjectProxyObject *)other)->wrapped; - - object = PyNumber_InPlaceOr(self->wrapped, other); - - if (!object) - return NULL; - - Py_DECREF(self->wrapped); - self->wrapped = object; - - Py_INCREF(self); - return (PyObject *)self; -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_floor_divide(PyObject *o1, PyObject *o2) -{ - if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o1)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o1 = ((WraptObjectProxyObject *)o1)->wrapped; - } - - if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o2)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o2 = ((WraptObjectProxyObject *)o2)->wrapped; - } - - return PyNumber_FloorDivide(o1, o2); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_true_divide(PyObject *o1, PyObject *o2) -{ - if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o1)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o1 = ((WraptObjectProxyObject *)o1)->wrapped; - } - - if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) { - if (!((WraptObjectProxyObject *)o2)->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - o2 = ((WraptObjectProxyObject *)o2)->wrapped; - } - - return PyNumber_TrueDivide(o1, o2); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_inplace_floor_divide( - WraptObjectProxyObject *self, PyObject *other) -{ - PyObject *object = NULL; - - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) - other = ((WraptObjectProxyObject *)other)->wrapped; - - object = PyNumber_InPlaceFloorDivide(self->wrapped, other); - - if (!object) - return NULL; - - Py_DECREF(self->wrapped); - self->wrapped = object; - - Py_INCREF(self); - return (PyObject *)self; -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_inplace_true_divide( - WraptObjectProxyObject *self, PyObject *other) -{ - PyObject *object = NULL; - - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) - other = ((WraptObjectProxyObject *)other)->wrapped; - - object = PyNumber_InPlaceTrueDivide(self->wrapped, other); - - if (!object) - return NULL; - - Py_DECREF(self->wrapped); - self->wrapped = object; - - Py_INCREF(self); - return (PyObject *)self; -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_index(WraptObjectProxyObject *self) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - return PyNumber_Index(self->wrapped); -} - -/* ------------------------------------------------------------------------- */ - -static Py_ssize_t WraptObjectProxy_length(WraptObjectProxyObject *self) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return -1; - } - - return PyObject_Length(self->wrapped); -} - -/* ------------------------------------------------------------------------- */ - -static int WraptObjectProxy_contains(WraptObjectProxyObject *self, - PyObject *value) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return -1; - } - - return PySequence_Contains(self->wrapped, value); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_getitem(WraptObjectProxyObject *self, - PyObject *key) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - return PyObject_GetItem(self->wrapped, key); -} - -/* ------------------------------------------------------------------------- */ - -static int WraptObjectProxy_setitem(WraptObjectProxyObject *self, - PyObject *key, PyObject* value) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return -1; - } - - if (value == NULL) - return PyObject_DelItem(self->wrapped, key); - else - return PyObject_SetItem(self->wrapped, key, value); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_dir( - WraptObjectProxyObject *self, PyObject *args) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - return PyObject_Dir(self->wrapped); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_enter( - WraptObjectProxyObject *self, PyObject *args, PyObject *kwds) -{ - PyObject *method = NULL; - PyObject *result = NULL; - - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - method = PyObject_GetAttrString(self->wrapped, "__enter__"); - - if (!method) - return NULL; - - result = PyObject_Call(method, args, kwds); - - Py_DECREF(method); - - return result; -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_exit( - WraptObjectProxyObject *self, PyObject *args, PyObject *kwds) -{ - PyObject *method = NULL; - PyObject *result = NULL; - - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - method = PyObject_GetAttrString(self->wrapped, "__exit__"); - - if (!method) - return NULL; - - result = PyObject_Call(method, args, kwds); - - Py_DECREF(method); - - return result; -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_copy( - WraptObjectProxyObject *self, PyObject *args, PyObject *kwds) -{ - PyErr_SetString(PyExc_NotImplementedError, - "object proxy must define __copy__()"); - - return NULL; -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_deepcopy( - WraptObjectProxyObject *self, PyObject *args, PyObject *kwds) -{ - PyErr_SetString(PyExc_NotImplementedError, - "object proxy must define __deepcopy__()"); - - return NULL; -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_reduce( - WraptObjectProxyObject *self, PyObject *args, PyObject *kwds) -{ - PyErr_SetString(PyExc_NotImplementedError, - "object proxy must define __reduce_ex__()"); - - return NULL; -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_reduce_ex( - WraptObjectProxyObject *self, PyObject *args, PyObject *kwds) -{ - PyErr_SetString(PyExc_NotImplementedError, - "object proxy must define __reduce_ex__()"); - - return NULL; -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_bytes( - WraptObjectProxyObject *self, PyObject *args) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - return PyObject_Bytes(self->wrapped); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_reversed( - WraptObjectProxyObject *self, PyObject *args) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - return PyObject_CallFunctionObjArgs((PyObject *)&PyReversed_Type, - self->wrapped, NULL); -} - -/* ------------------------------------------------------------------------- */ - -#if PY_MAJOR_VERSION >= 3 -static PyObject *WraptObjectProxy_round( - WraptObjectProxyObject *self, PyObject *args) -{ - PyObject *module = NULL; - PyObject *dict = NULL; - PyObject *round = NULL; - - PyObject *result = NULL; - - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - module = PyImport_ImportModule("builtins"); - - if (!module) - return NULL; - - dict = PyModule_GetDict(module); - round = PyDict_GetItemString(dict, "round"); - - if (!round) { - Py_DECREF(module); - return NULL; - } - - Py_INCREF(round); - Py_DECREF(module); - - result = PyObject_CallFunctionObjArgs(round, self->wrapped, NULL); - - Py_DECREF(round); - - return result; -} -#endif - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_complex( - WraptObjectProxyObject *self, PyObject *args) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - return PyObject_CallFunctionObjArgs((PyObject *)&PyComplex_Type, - self->wrapped, NULL); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_mro_entries( - WraptObjectProxyObject *self, PyObject *args, PyObject *kwds) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - return Py_BuildValue("(O)", self->wrapped); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_get_name( - WraptObjectProxyObject *self) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - return PyObject_GetAttrString(self->wrapped, "__name__"); -} - -/* ------------------------------------------------------------------------- */ - -static int WraptObjectProxy_set_name(WraptObjectProxyObject *self, - PyObject *value) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return -1; - } - - return PyObject_SetAttrString(self->wrapped, "__name__", value); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_get_qualname( - WraptObjectProxyObject *self) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - return PyObject_GetAttrString(self->wrapped, "__qualname__"); -} - -/* ------------------------------------------------------------------------- */ - -static int WraptObjectProxy_set_qualname(WraptObjectProxyObject *self, - PyObject *value) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return -1; - } - - return PyObject_SetAttrString(self->wrapped, "__qualname__", value); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_get_module( - WraptObjectProxyObject *self) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - return PyObject_GetAttrString(self->wrapped, "__module__"); -} - -/* ------------------------------------------------------------------------- */ - -static int WraptObjectProxy_set_module(WraptObjectProxyObject *self, - PyObject *value) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return -1; - } - - if (PyObject_SetAttrString(self->wrapped, "__module__", value) == -1) - return -1; - - return PyDict_SetItemString(self->dict, "__module__", value); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_get_doc( - WraptObjectProxyObject *self) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - return PyObject_GetAttrString(self->wrapped, "__doc__"); -} - -/* ------------------------------------------------------------------------- */ - -static int WraptObjectProxy_set_doc(WraptObjectProxyObject *self, - PyObject *value) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return -1; - } - - if (PyObject_SetAttrString(self->wrapped, "__doc__", value) == -1) - return -1; - - return PyDict_SetItemString(self->dict, "__doc__", value); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_get_class( - WraptObjectProxyObject *self) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - return PyObject_GetAttrString(self->wrapped, "__class__"); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_get_annotations( - WraptObjectProxyObject *self) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - return PyObject_GetAttrString(self->wrapped, "__annotations__"); -} - -/* ------------------------------------------------------------------------- */ - -static int WraptObjectProxy_set_annotations(WraptObjectProxyObject *self, - PyObject *value) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return -1; - } - - return PyObject_SetAttrString(self->wrapped, "__annotations__", value); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_get_wrapped( - WraptObjectProxyObject *self) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - Py_INCREF(self->wrapped); - return self->wrapped; -} - -/* ------------------------------------------------------------------------- */ - -static int WraptObjectProxy_set_wrapped(WraptObjectProxyObject *self, - PyObject *value) -{ - if (!value) { - PyErr_SetString(PyExc_TypeError, "__wrapped__ must be an object"); - return -1; - } - - Py_INCREF(value); - Py_XDECREF(self->wrapped); - - self->wrapped = value; - - return 0; -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_getattro( - WraptObjectProxyObject *self, PyObject *name) -{ - PyObject *object = NULL; - PyObject *result = NULL; - - static PyObject *getattr_str = NULL; - - object = PyObject_GenericGetAttr((PyObject *)self, name); - - if (object) - return object; - - PyErr_Clear(); - - if (!getattr_str) { -#if PY_MAJOR_VERSION >= 3 - getattr_str = PyUnicode_InternFromString("__getattr__"); -#else - getattr_str = PyString_InternFromString("__getattr__"); -#endif - } - - object = PyObject_GenericGetAttr((PyObject *)self, getattr_str); - - if (!object) - return NULL; - - result = PyObject_CallFunctionObjArgs(object, name, NULL); - - Py_DECREF(object); - - return result; -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_getattr( - WraptObjectProxyObject *self, PyObject *args) -{ - PyObject *name = NULL; - -#if PY_MAJOR_VERSION >= 3 - if (!PyArg_ParseTuple(args, "U:__getattr__", &name)) - return NULL; -#else - if (!PyArg_ParseTuple(args, "S:__getattr__", &name)) - return NULL; -#endif - - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - return PyObject_GetAttr(self->wrapped, name); -} - -/* ------------------------------------------------------------------------- */ - -static int WraptObjectProxy_setattro( - WraptObjectProxyObject *self, PyObject *name, PyObject *value) -{ - static PyObject *self_str = NULL; - static PyObject *wrapped_str = NULL; - static PyObject *startswith_str = NULL; - - PyObject *match = NULL; - - if (!startswith_str) { -#if PY_MAJOR_VERSION >= 3 - startswith_str = PyUnicode_InternFromString("startswith"); -#else - startswith_str = PyString_InternFromString("startswith"); -#endif - } - - if (!self_str) { -#if PY_MAJOR_VERSION >= 3 - self_str = PyUnicode_InternFromString("_self_"); -#else - self_str = PyString_InternFromString("_self_"); -#endif - } - - match = PyObject_CallMethodObjArgs(name, startswith_str, self_str, NULL); - - if (match == Py_True) { - Py_DECREF(match); - - return PyObject_GenericSetAttr((PyObject *)self, name, value); - } - else if (!match) - PyErr_Clear(); - - Py_XDECREF(match); - - if (!wrapped_str) { -#if PY_MAJOR_VERSION >= 3 - wrapped_str = PyUnicode_InternFromString("__wrapped__"); -#else - wrapped_str = PyString_InternFromString("__wrapped__"); -#endif - } - - if (PyObject_HasAttr((PyObject *)Py_TYPE(self), name)) - return PyObject_GenericSetAttr((PyObject *)self, name, value); - - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return -1; - } - - return PyObject_SetAttr(self->wrapped, name, value); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_richcompare(WraptObjectProxyObject *self, - PyObject *other, int opcode) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - return PyObject_RichCompare(self->wrapped, other, opcode); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptObjectProxy_iter(WraptObjectProxyObject *self) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - return PyObject_GetIter(self->wrapped); -} - -/* ------------------------------------------------------------------------- */ - -static PyNumberMethods WraptObjectProxy_as_number = { - (binaryfunc)WraptObjectProxy_add, /*nb_add*/ - (binaryfunc)WraptObjectProxy_subtract, /*nb_subtract*/ - (binaryfunc)WraptObjectProxy_multiply, /*nb_multiply*/ -#if PY_MAJOR_VERSION < 3 - (binaryfunc)WraptObjectProxy_divide, /*nb_divide*/ -#endif - (binaryfunc)WraptObjectProxy_remainder, /*nb_remainder*/ - (binaryfunc)WraptObjectProxy_divmod, /*nb_divmod*/ - (ternaryfunc)WraptObjectProxy_power, /*nb_power*/ - (unaryfunc)WraptObjectProxy_negative, /*nb_negative*/ - (unaryfunc)WraptObjectProxy_positive, /*nb_positive*/ - (unaryfunc)WraptObjectProxy_absolute, /*nb_absolute*/ - (inquiry)WraptObjectProxy_bool, /*nb_nonzero/nb_bool*/ - (unaryfunc)WraptObjectProxy_invert, /*nb_invert*/ - (binaryfunc)WraptObjectProxy_lshift, /*nb_lshift*/ - (binaryfunc)WraptObjectProxy_rshift, /*nb_rshift*/ - (binaryfunc)WraptObjectProxy_and, /*nb_and*/ - (binaryfunc)WraptObjectProxy_xor, /*nb_xor*/ - (binaryfunc)WraptObjectProxy_or, /*nb_or*/ -#if PY_MAJOR_VERSION < 3 - 0, /*nb_coerce*/ -#endif -#if PY_MAJOR_VERSION < 3 - (unaryfunc)WraptObjectProxy_int, /*nb_int*/ - (unaryfunc)WraptObjectProxy_long, /*nb_long*/ -#else - (unaryfunc)WraptObjectProxy_long, /*nb_int*/ - 0, /*nb_long/nb_reserved*/ -#endif - (unaryfunc)WraptObjectProxy_float, /*nb_float*/ -#if PY_MAJOR_VERSION < 3 - (unaryfunc)WraptObjectProxy_oct, /*nb_oct*/ - (unaryfunc)WraptObjectProxy_hex, /*nb_hex*/ -#endif - (binaryfunc)WraptObjectProxy_inplace_add, /*nb_inplace_add*/ - (binaryfunc)WraptObjectProxy_inplace_subtract, /*nb_inplace_subtract*/ - (binaryfunc)WraptObjectProxy_inplace_multiply, /*nb_inplace_multiply*/ -#if PY_MAJOR_VERSION < 3 - (binaryfunc)WraptObjectProxy_inplace_divide, /*nb_inplace_divide*/ -#endif - (binaryfunc)WraptObjectProxy_inplace_remainder, /*nb_inplace_remainder*/ - (ternaryfunc)WraptObjectProxy_inplace_power, /*nb_inplace_power*/ - (binaryfunc)WraptObjectProxy_inplace_lshift, /*nb_inplace_lshift*/ - (binaryfunc)WraptObjectProxy_inplace_rshift, /*nb_inplace_rshift*/ - (binaryfunc)WraptObjectProxy_inplace_and, /*nb_inplace_and*/ - (binaryfunc)WraptObjectProxy_inplace_xor, /*nb_inplace_xor*/ - (binaryfunc)WraptObjectProxy_inplace_or, /*nb_inplace_or*/ - (binaryfunc)WraptObjectProxy_floor_divide, /*nb_floor_divide*/ - (binaryfunc)WraptObjectProxy_true_divide, /*nb_true_divide*/ - (binaryfunc)WraptObjectProxy_inplace_floor_divide, /*nb_inplace_floor_divide*/ - (binaryfunc)WraptObjectProxy_inplace_true_divide, /*nb_inplace_true_divide*/ - (unaryfunc)WraptObjectProxy_index, /*nb_index*/ -}; - -static PySequenceMethods WraptObjectProxy_as_sequence = { - (lenfunc)WraptObjectProxy_length, /*sq_length*/ - 0, /*sq_concat*/ - 0, /*sq_repeat*/ - 0, /*sq_item*/ - 0, /*sq_slice*/ - 0, /*sq_ass_item*/ - 0, /*sq_ass_slice*/ - (objobjproc)WraptObjectProxy_contains, /* sq_contains */ -}; - -static PyMappingMethods WraptObjectProxy_as_mapping = { - (lenfunc)WraptObjectProxy_length, /*mp_length*/ - (binaryfunc)WraptObjectProxy_getitem, /*mp_subscript*/ - (objobjargproc)WraptObjectProxy_setitem, /*mp_ass_subscript*/ -}; - -static PyMethodDef WraptObjectProxy_methods[] = { - { "__dir__", (PyCFunction)WraptObjectProxy_dir, METH_NOARGS, 0 }, - { "__enter__", (PyCFunction)WraptObjectProxy_enter, - METH_VARARGS | METH_KEYWORDS, 0 }, - { "__exit__", (PyCFunction)WraptObjectProxy_exit, - METH_VARARGS | METH_KEYWORDS, 0 }, - { "__copy__", (PyCFunction)WraptObjectProxy_copy, - METH_NOARGS, 0 }, - { "__deepcopy__", (PyCFunction)WraptObjectProxy_deepcopy, - METH_VARARGS | METH_KEYWORDS, 0 }, - { "__reduce__", (PyCFunction)WraptObjectProxy_reduce, - METH_NOARGS, 0 }, - { "__reduce_ex__", (PyCFunction)WraptObjectProxy_reduce_ex, - METH_VARARGS | METH_KEYWORDS, 0 }, - { "__getattr__", (PyCFunction)WraptObjectProxy_getattr, - METH_VARARGS , 0 }, - { "__bytes__", (PyCFunction)WraptObjectProxy_bytes, METH_NOARGS, 0 }, - { "__reversed__", (PyCFunction)WraptObjectProxy_reversed, METH_NOARGS, 0 }, -#if PY_MAJOR_VERSION >= 3 - { "__round__", (PyCFunction)WraptObjectProxy_round, METH_NOARGS, 0 }, -#endif - { "__complex__", (PyCFunction)WraptObjectProxy_complex, METH_NOARGS, 0 }, -#if PY_MAJOR_VERSION > 3 || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 7) - { "__mro_entries__", (PyCFunction)WraptObjectProxy_mro_entries, - METH_VARARGS | METH_KEYWORDS, 0 }, -#endif - { NULL, NULL }, -}; - -static PyGetSetDef WraptObjectProxy_getset[] = { - { "__name__", (getter)WraptObjectProxy_get_name, - (setter)WraptObjectProxy_set_name, 0 }, - { "__qualname__", (getter)WraptObjectProxy_get_qualname, - (setter)WraptObjectProxy_set_qualname, 0 }, - { "__module__", (getter)WraptObjectProxy_get_module, - (setter)WraptObjectProxy_set_module, 0 }, - { "__doc__", (getter)WraptObjectProxy_get_doc, - (setter)WraptObjectProxy_set_doc, 0 }, - { "__class__", (getter)WraptObjectProxy_get_class, - NULL, 0 }, - { "__annotations__", (getter)WraptObjectProxy_get_annotations, - (setter)WraptObjectProxy_set_annotations, 0 }, - { "__wrapped__", (getter)WraptObjectProxy_get_wrapped, - (setter)WraptObjectProxy_set_wrapped, 0 }, - { NULL }, -}; - -PyTypeObject WraptObjectProxy_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "ObjectProxy", /*tp_name*/ - sizeof(WraptObjectProxyObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)WraptObjectProxy_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - (unaryfunc)WraptObjectProxy_repr, /*tp_repr*/ - &WraptObjectProxy_as_number, /*tp_as_number*/ - &WraptObjectProxy_as_sequence, /*tp_as_sequence*/ - &WraptObjectProxy_as_mapping, /*tp_as_mapping*/ - (hashfunc)WraptObjectProxy_hash, /*tp_hash*/ - 0, /*tp_call*/ - (unaryfunc)WraptObjectProxy_str, /*tp_str*/ - (getattrofunc)WraptObjectProxy_getattro, /*tp_getattro*/ - (setattrofunc)WraptObjectProxy_setattro, /*tp_setattro*/ - 0, /*tp_as_buffer*/ -#if PY_MAJOR_VERSION < 3 - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ -#else - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_HAVE_GC, /*tp_flags*/ -#endif - 0, /*tp_doc*/ - (traverseproc)WraptObjectProxy_traverse, /*tp_traverse*/ - (inquiry)WraptObjectProxy_clear, /*tp_clear*/ - (richcmpfunc)WraptObjectProxy_richcompare, /*tp_richcompare*/ - offsetof(WraptObjectProxyObject, weakreflist), /*tp_weaklistoffset*/ - (getiterfunc)WraptObjectProxy_iter, /*tp_iter*/ - 0, /*tp_iternext*/ - WraptObjectProxy_methods, /*tp_methods*/ - 0, /*tp_members*/ - WraptObjectProxy_getset, /*tp_getset*/ - 0, /*tp_base*/ - 0, /*tp_dict*/ - 0, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - offsetof(WraptObjectProxyObject, dict), /*tp_dictoffset*/ - (initproc)WraptObjectProxy_init, /*tp_init*/ - PyType_GenericAlloc, /*tp_alloc*/ - WraptObjectProxy_new, /*tp_new*/ - PyObject_GC_Del, /*tp_free*/ - 0, /*tp_is_gc*/ -}; - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptCallableObjectProxy_call( - WraptObjectProxyObject *self, PyObject *args, PyObject *kwds) -{ - if (!self->wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - return PyObject_Call(self->wrapped, args, kwds); -} - -/* ------------------------------------------------------------------------- */; - -static PyGetSetDef WraptCallableObjectProxy_getset[] = { - { "__module__", (getter)WraptObjectProxy_get_module, - (setter)WraptObjectProxy_set_module, 0 }, - { "__doc__", (getter)WraptObjectProxy_get_doc, - (setter)WraptObjectProxy_set_doc, 0 }, - { NULL }, -}; - -PyTypeObject WraptCallableObjectProxy_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "CallableObjectProxy", /*tp_name*/ - sizeof(WraptObjectProxyObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - 0, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - (ternaryfunc)WraptCallableObjectProxy_call, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ -#if PY_MAJOR_VERSION < 3 - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ -#else - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ -#endif - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - offsetof(WraptObjectProxyObject, weakreflist), /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - 0, /*tp_methods*/ - 0, /*tp_members*/ - WraptCallableObjectProxy_getset, /*tp_getset*/ - 0, /*tp_base*/ - 0, /*tp_dict*/ - 0, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - 0, /*tp_dictoffset*/ - (initproc)WraptObjectProxy_init, /*tp_init*/ - 0, /*tp_alloc*/ - 0, /*tp_new*/ - 0, /*tp_free*/ - 0, /*tp_is_gc*/ -}; - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptPartialCallableObjectProxy_new(PyTypeObject *type, - PyObject *args, PyObject *kwds) -{ - WraptPartialCallableObjectProxyObject *self; - - self = (WraptPartialCallableObjectProxyObject *)WraptObjectProxy_new(type, - args, kwds); - - if (!self) - return NULL; - - self->args = NULL; - self->kwargs = NULL; - - return (PyObject *)self; -} - -/* ------------------------------------------------------------------------- */ - -static int WraptPartialCallableObjectProxy_raw_init( - WraptPartialCallableObjectProxyObject *self, - PyObject *wrapped, PyObject *args, PyObject *kwargs) -{ - int result = 0; - - result = WraptObjectProxy_raw_init((WraptObjectProxyObject *)self, - wrapped); - - if (result == 0) { - Py_INCREF(args); - Py_XDECREF(self->args); - self->args = args; - - Py_XINCREF(kwargs); - Py_XDECREF(self->kwargs); - self->kwargs = kwargs; - } - - return result; -} - -/* ------------------------------------------------------------------------- */ - -static int WraptPartialCallableObjectProxy_init( - WraptPartialCallableObjectProxyObject *self, PyObject *args, - PyObject *kwds) -{ - PyObject *wrapped = NULL; - PyObject *fnargs = NULL; - - int result = 0; - - if (!PyObject_Length(args)) { - PyErr_SetString(PyExc_TypeError, - "__init__ of partial needs an argument"); - return -1; - } - - if (PyObject_Length(args) < 1) { - PyErr_SetString(PyExc_TypeError, - "partial type takes at least one argument"); - return -1; - } - - wrapped = PyTuple_GetItem(args, 0); - - if (!PyCallable_Check(wrapped)) { - PyErr_SetString(PyExc_TypeError, - "the first argument must be callable"); - return -1; - } - - fnargs = PyTuple_GetSlice(args, 1, PyTuple_Size(args)); - - if (!fnargs) - return -1; - - result = WraptPartialCallableObjectProxy_raw_init(self, wrapped, - fnargs, kwds); - - Py_DECREF(fnargs); - - return result; -} - -/* ------------------------------------------------------------------------- */ - -static int WraptPartialCallableObjectProxy_traverse( - WraptPartialCallableObjectProxyObject *self, - visitproc visit, void *arg) -{ - WraptObjectProxy_traverse((WraptObjectProxyObject *)self, visit, arg); - - Py_VISIT(self->args); - Py_VISIT(self->kwargs); - - return 0; -} - -/* ------------------------------------------------------------------------- */ - -static int WraptPartialCallableObjectProxy_clear( - WraptPartialCallableObjectProxyObject *self) -{ - WraptObjectProxy_clear((WraptObjectProxyObject *)self); - - Py_CLEAR(self->args); - Py_CLEAR(self->kwargs); - - return 0; -} - -/* ------------------------------------------------------------------------- */ - -static void WraptPartialCallableObjectProxy_dealloc( - WraptPartialCallableObjectProxyObject *self) -{ - PyObject_GC_UnTrack(self); - - WraptPartialCallableObjectProxy_clear(self); - - WraptObjectProxy_dealloc((WraptObjectProxyObject *)self); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptPartialCallableObjectProxy_call( - WraptPartialCallableObjectProxyObject *self, PyObject *args, - PyObject *kwds) -{ - PyObject *fnargs = NULL; - PyObject *fnkwargs = NULL; - - PyObject *result = NULL; - - long i; - long offset; - - if (!self->object_proxy.wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - fnargs = PyTuple_New(PyTuple_Size(self->args)+PyTuple_Size(args)); - - for (i=0; iargs); i++) { - PyObject *item; - item = PyTuple_GetItem(self->args, i); - Py_INCREF(item); - PyTuple_SetItem(fnargs, i, item); - } - - offset = PyTuple_Size(self->args); - - for (i=0; ikwargs && PyDict_Update(fnkwargs, self->kwargs) == -1) { - Py_DECREF(fnargs); - Py_DECREF(fnkwargs); - return NULL; - } - - if (kwds && PyDict_Update(fnkwargs, kwds) == -1) { - Py_DECREF(fnargs); - Py_DECREF(fnkwargs); - return NULL; - } - - result = PyObject_Call(self->object_proxy.wrapped, - fnargs, fnkwargs); - - Py_DECREF(fnargs); - Py_DECREF(fnkwargs); - - return result; -} - -/* ------------------------------------------------------------------------- */; - -static PyGetSetDef WraptPartialCallableObjectProxy_getset[] = { - { "__module__", (getter)WraptObjectProxy_get_module, - (setter)WraptObjectProxy_set_module, 0 }, - { "__doc__", (getter)WraptObjectProxy_get_doc, - (setter)WraptObjectProxy_set_doc, 0 }, - { NULL }, -}; - -PyTypeObject WraptPartialCallableObjectProxy_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "PartialCallableObjectProxy", /*tp_name*/ - sizeof(WraptPartialCallableObjectProxyObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)WraptPartialCallableObjectProxy_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - (ternaryfunc)WraptPartialCallableObjectProxy_call, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ -#if PY_MAJOR_VERSION < 3 - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ -#else - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_HAVE_GC, /*tp_flags*/ -#endif - 0, /*tp_doc*/ - (traverseproc)WraptPartialCallableObjectProxy_traverse, /*tp_traverse*/ - (inquiry)WraptPartialCallableObjectProxy_clear, /*tp_clear*/ - 0, /*tp_richcompare*/ - offsetof(WraptObjectProxyObject, weakreflist), /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - 0, /*tp_methods*/ - 0, /*tp_members*/ - WraptPartialCallableObjectProxy_getset, /*tp_getset*/ - 0, /*tp_base*/ - 0, /*tp_dict*/ - 0, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - 0, /*tp_dictoffset*/ - (initproc)WraptPartialCallableObjectProxy_init, /*tp_init*/ - 0, /*tp_alloc*/ - WraptPartialCallableObjectProxy_new, /*tp_new*/ - 0, /*tp_free*/ - 0, /*tp_is_gc*/ -}; - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptFunctionWrapperBase_new(PyTypeObject *type, - PyObject *args, PyObject *kwds) -{ - WraptFunctionWrapperObject *self; - - self = (WraptFunctionWrapperObject *)WraptObjectProxy_new(type, - args, kwds); - - if (!self) - return NULL; - - self->instance = NULL; - self->wrapper = NULL; - self->enabled = NULL; - self->binding = NULL; - self->parent = NULL; - - return (PyObject *)self; -} - -/* ------------------------------------------------------------------------- */ - -static int WraptFunctionWrapperBase_raw_init(WraptFunctionWrapperObject *self, - PyObject *wrapped, PyObject *instance, PyObject *wrapper, - PyObject *enabled, PyObject *binding, PyObject *parent) -{ - int result = 0; - - result = WraptObjectProxy_raw_init((WraptObjectProxyObject *)self, - wrapped); - - if (result == 0) { - Py_INCREF(instance); - Py_XDECREF(self->instance); - self->instance = instance; - - Py_INCREF(wrapper); - Py_XDECREF(self->wrapper); - self->wrapper = wrapper; - - Py_INCREF(enabled); - Py_XDECREF(self->enabled); - self->enabled = enabled; - - Py_INCREF(binding); - Py_XDECREF(self->binding); - self->binding = binding; - - Py_INCREF(parent); - Py_XDECREF(self->parent); - self->parent = parent; - } - - return result; -} - -/* ------------------------------------------------------------------------- */ - -static int WraptFunctionWrapperBase_init(WraptFunctionWrapperObject *self, - PyObject *args, PyObject *kwds) -{ - PyObject *wrapped = NULL; - PyObject *instance = NULL; - PyObject *wrapper = NULL; - PyObject *enabled = Py_None; - PyObject *binding = NULL; - PyObject *parent = Py_None; - - static PyObject *function_str = NULL; - - static char *kwlist[] = { "wrapped", "instance", "wrapper", - "enabled", "binding", "parent", NULL }; - - if (!function_str) { -#if PY_MAJOR_VERSION >= 3 - function_str = PyUnicode_InternFromString("function"); -#else - function_str = PyString_InternFromString("function"); -#endif - } - - if (!PyArg_ParseTupleAndKeywords(args, kwds, - "OOO|OOO:FunctionWrapperBase", kwlist, &wrapped, &instance, - &wrapper, &enabled, &binding, &parent)) { - return -1; - } - - if (!binding) - binding = function_str; - - return WraptFunctionWrapperBase_raw_init(self, wrapped, instance, wrapper, - enabled, binding, parent); -} - -/* ------------------------------------------------------------------------- */ - -static int WraptFunctionWrapperBase_traverse(WraptFunctionWrapperObject *self, - visitproc visit, void *arg) -{ - WraptObjectProxy_traverse((WraptObjectProxyObject *)self, visit, arg); - - Py_VISIT(self->instance); - Py_VISIT(self->wrapper); - Py_VISIT(self->enabled); - Py_VISIT(self->binding); - Py_VISIT(self->parent); - - return 0; -} - -/* ------------------------------------------------------------------------- */ - -static int WraptFunctionWrapperBase_clear(WraptFunctionWrapperObject *self) -{ - WraptObjectProxy_clear((WraptObjectProxyObject *)self); - - Py_CLEAR(self->instance); - Py_CLEAR(self->wrapper); - Py_CLEAR(self->enabled); - Py_CLEAR(self->binding); - Py_CLEAR(self->parent); - - return 0; -} - -/* ------------------------------------------------------------------------- */ - -static void WraptFunctionWrapperBase_dealloc(WraptFunctionWrapperObject *self) -{ - PyObject_GC_UnTrack(self); - - WraptFunctionWrapperBase_clear(self); - - WraptObjectProxy_dealloc((WraptObjectProxyObject *)self); -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptFunctionWrapperBase_call( - WraptFunctionWrapperObject *self, PyObject *args, PyObject *kwds) -{ - PyObject *param_kwds = NULL; - - PyObject *result = NULL; - - static PyObject *function_str = NULL; - static PyObject *classmethod_str = NULL; - - if (!function_str) { -#if PY_MAJOR_VERSION >= 3 - function_str = PyUnicode_InternFromString("function"); - classmethod_str = PyUnicode_InternFromString("classmethod"); -#else - function_str = PyString_InternFromString("function"); - classmethod_str = PyString_InternFromString("classmethod"); -#endif - } - - if (self->enabled != Py_None) { - if (PyCallable_Check(self->enabled)) { - PyObject *object = NULL; - - object = PyObject_CallFunctionObjArgs(self->enabled, NULL); - - if (!object) - return NULL; - - if (PyObject_Not(object)) { - Py_DECREF(object); - return PyObject_Call(self->object_proxy.wrapped, args, kwds); - } - - Py_DECREF(object); - } - else if (PyObject_Not(self->enabled)) { - return PyObject_Call(self->object_proxy.wrapped, args, kwds); - } - } - - if (!kwds) { - param_kwds = PyDict_New(); - kwds = param_kwds; - } - - if ((self->instance == Py_None) && (self->binding == function_str || - PyObject_RichCompareBool(self->binding, function_str, - Py_EQ) == 1 || self->binding == classmethod_str || - PyObject_RichCompareBool(self->binding, classmethod_str, - Py_EQ) == 1)) { - - PyObject *instance = NULL; - - instance = PyObject_GetAttrString(self->object_proxy.wrapped, - "__self__"); - - if (instance) { - result = PyObject_CallFunctionObjArgs(self->wrapper, - self->object_proxy.wrapped, instance, args, kwds, NULL); - - Py_XDECREF(param_kwds); - - Py_DECREF(instance); - - return result; - } - else - PyErr_Clear(); - } - - result = PyObject_CallFunctionObjArgs(self->wrapper, - self->object_proxy.wrapped, self->instance, args, kwds, NULL); - - Py_XDECREF(param_kwds); - - return result; -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptFunctionWrapperBase_descr_get( - WraptFunctionWrapperObject *self, PyObject *obj, PyObject *type) -{ - PyObject *bound_type = NULL; - PyObject *descriptor = NULL; - PyObject *result = NULL; - - static PyObject *bound_type_str = NULL; - static PyObject *function_str = NULL; - - if (!bound_type_str) { -#if PY_MAJOR_VERSION >= 3 - bound_type_str = PyUnicode_InternFromString( - "__bound_function_wrapper__"); -#else - bound_type_str = PyString_InternFromString( - "__bound_function_wrapper__"); -#endif - } - - if (!function_str) { -#if PY_MAJOR_VERSION >= 3 - function_str = PyUnicode_InternFromString("function"); -#else - function_str = PyString_InternFromString("function"); -#endif - } - - if (self->parent == Py_None) { -#if PY_MAJOR_VERSION < 3 - if (PyObject_IsInstance(self->object_proxy.wrapped, - (PyObject *)&PyClass_Type) || PyObject_IsInstance( - self->object_proxy.wrapped, (PyObject *)&PyType_Type)) { - Py_INCREF(self); - return (PyObject *)self; - } -#else - if (PyObject_IsInstance(self->object_proxy.wrapped, - (PyObject *)&PyType_Type)) { - Py_INCREF(self); - return (PyObject *)self; - } -#endif - - if (Py_TYPE(self->object_proxy.wrapped)->tp_descr_get == NULL) { - PyErr_Format(PyExc_AttributeError, - "'%s' object has no attribute '__get__'", - Py_TYPE(self->object_proxy.wrapped)->tp_name); - return NULL; - } - - descriptor = (Py_TYPE(self->object_proxy.wrapped)->tp_descr_get)( - self->object_proxy.wrapped, obj, type); - - if (!descriptor) - return NULL; - - if (Py_TYPE(self) != &WraptFunctionWrapper_Type) { - bound_type = PyObject_GenericGetAttr((PyObject *)self, - bound_type_str); - - if (!bound_type) - PyErr_Clear(); - } - - if (obj == NULL) - obj = Py_None; - - result = PyObject_CallFunctionObjArgs(bound_type ? bound_type : - (PyObject *)&WraptBoundFunctionWrapper_Type, descriptor, - obj, self->wrapper, self->enabled, self->binding, - self, NULL); - - Py_XDECREF(bound_type); - Py_DECREF(descriptor); - - return result; - } - - if (self->instance == Py_None && (self->binding == function_str || - PyObject_RichCompareBool(self->binding, function_str, - Py_EQ) == 1)) { - - PyObject *wrapped = NULL; - - static PyObject *wrapped_str = NULL; - - if (!wrapped_str) { -#if PY_MAJOR_VERSION >= 3 - wrapped_str = PyUnicode_InternFromString("__wrapped__"); -#else - wrapped_str = PyString_InternFromString("__wrapped__"); -#endif - } - - wrapped = PyObject_GetAttr(self->parent, wrapped_str); - - if (!wrapped) - return NULL; - - if (Py_TYPE(wrapped)->tp_descr_get == NULL) { - PyErr_Format(PyExc_AttributeError, - "'%s' object has no attribute '__get__'", - Py_TYPE(wrapped)->tp_name); - Py_DECREF(wrapped); - return NULL; - } - - descriptor = (Py_TYPE(wrapped)->tp_descr_get)(wrapped, obj, type); - - Py_DECREF(wrapped); - - if (!descriptor) - return NULL; - - if (Py_TYPE(self->parent) != &WraptFunctionWrapper_Type) { - bound_type = PyObject_GenericGetAttr((PyObject *)self->parent, - bound_type_str); - - if (!bound_type) - PyErr_Clear(); - } - - if (obj == NULL) - obj = Py_None; - - result = PyObject_CallFunctionObjArgs(bound_type ? bound_type : - (PyObject *)&WraptBoundFunctionWrapper_Type, descriptor, - obj, self->wrapper, self->enabled, self->binding, - self->parent, NULL); - - Py_XDECREF(bound_type); - Py_DECREF(descriptor); - - return result; - } - - Py_INCREF(self); - return (PyObject *)self; -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptFunctionWrapperBase_set_name( - WraptFunctionWrapperObject *self, PyObject *args, PyObject *kwds) -{ - PyObject *method = NULL; - PyObject *result = NULL; - - if (!self->object_proxy.wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - method = PyObject_GetAttrString(self->object_proxy.wrapped, - "__set_name__"); - - if (!method) { - PyErr_Clear(); - Py_INCREF(Py_None); - return Py_None; - } - - result = PyObject_Call(method, args, kwds); - - Py_DECREF(method); - - return result; -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptFunctionWrapperBase_instancecheck( - WraptFunctionWrapperObject *self, PyObject *instance) -{ - PyObject *object = NULL; - PyObject *result = NULL; - - int check = 0; - - if (!self->object_proxy.wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - check = PyObject_IsInstance(instance, self->object_proxy.wrapped); - - if (check < 0) { - return NULL; - } - - result = check ? Py_True : Py_False; - - Py_INCREF(result); - return result; -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptFunctionWrapperBase_subclasscheck( - WraptFunctionWrapperObject *self, PyObject *args) -{ - PyObject *subclass = NULL; - PyObject *object = NULL; - PyObject *result = NULL; - - int check = 0; - - if (!self->object_proxy.wrapped) { - PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); - return NULL; - } - - if (!PyArg_ParseTuple(args, "O", &subclass)) - return NULL; - - object = PyObject_GetAttrString(subclass, "__wrapped__"); - - if (!object) - PyErr_Clear(); - - check = PyObject_IsSubclass(object ? object: subclass, - self->object_proxy.wrapped); - - Py_XDECREF(object); - - if (check == -1) - return NULL; - - result = check ? Py_True : Py_False; - - Py_INCREF(result); - - return result; -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptFunctionWrapperBase_get_self_instance( - WraptFunctionWrapperObject *self, void *closure) -{ - if (!self->instance) { - Py_INCREF(Py_None); - return Py_None; - } - - Py_INCREF(self->instance); - return self->instance; -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptFunctionWrapperBase_get_self_wrapper( - WraptFunctionWrapperObject *self, void *closure) -{ - if (!self->wrapper) { - Py_INCREF(Py_None); - return Py_None; - } - - Py_INCREF(self->wrapper); - return self->wrapper; -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptFunctionWrapperBase_get_self_enabled( - WraptFunctionWrapperObject *self, void *closure) -{ - if (!self->enabled) { - Py_INCREF(Py_None); - return Py_None; - } - - Py_INCREF(self->enabled); - return self->enabled; -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptFunctionWrapperBase_get_self_binding( - WraptFunctionWrapperObject *self, void *closure) -{ - if (!self->binding) { - Py_INCREF(Py_None); - return Py_None; - } - - Py_INCREF(self->binding); - return self->binding; -} - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptFunctionWrapperBase_get_self_parent( - WraptFunctionWrapperObject *self, void *closure) -{ - if (!self->parent) { - Py_INCREF(Py_None); - return Py_None; - } - - Py_INCREF(self->parent); - return self->parent; -} - -/* ------------------------------------------------------------------------- */; - -static PyMethodDef WraptFunctionWrapperBase_methods[] = { - { "__set_name__", (PyCFunction)WraptFunctionWrapperBase_set_name, - METH_VARARGS | METH_KEYWORDS, 0 }, - { "__instancecheck__", (PyCFunction)WraptFunctionWrapperBase_instancecheck, - METH_O, 0}, - { "__subclasscheck__", (PyCFunction)WraptFunctionWrapperBase_subclasscheck, - METH_VARARGS, 0 }, - { NULL, NULL }, -}; - -/* ------------------------------------------------------------------------- */; - -static PyGetSetDef WraptFunctionWrapperBase_getset[] = { - { "__module__", (getter)WraptObjectProxy_get_module, - (setter)WraptObjectProxy_set_module, 0 }, - { "__doc__", (getter)WraptObjectProxy_get_doc, - (setter)WraptObjectProxy_set_doc, 0 }, - { "_self_instance", (getter)WraptFunctionWrapperBase_get_self_instance, - NULL, 0 }, - { "_self_wrapper", (getter)WraptFunctionWrapperBase_get_self_wrapper, - NULL, 0 }, - { "_self_enabled", (getter)WraptFunctionWrapperBase_get_self_enabled, - NULL, 0 }, - { "_self_binding", (getter)WraptFunctionWrapperBase_get_self_binding, - NULL, 0 }, - { "_self_parent", (getter)WraptFunctionWrapperBase_get_self_parent, - NULL, 0 }, - { NULL }, -}; - -PyTypeObject WraptFunctionWrapperBase_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_FunctionWrapperBase", /*tp_name*/ - sizeof(WraptFunctionWrapperObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)WraptFunctionWrapperBase_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - (ternaryfunc)WraptFunctionWrapperBase_call, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ -#if PY_MAJOR_VERSION < 3 - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ -#else - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_HAVE_GC, /*tp_flags*/ -#endif - 0, /*tp_doc*/ - (traverseproc)WraptFunctionWrapperBase_traverse, /*tp_traverse*/ - (inquiry)WraptFunctionWrapperBase_clear, /*tp_clear*/ - 0, /*tp_richcompare*/ - offsetof(WraptObjectProxyObject, weakreflist), /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - WraptFunctionWrapperBase_methods, /*tp_methods*/ - 0, /*tp_members*/ - WraptFunctionWrapperBase_getset, /*tp_getset*/ - 0, /*tp_base*/ - 0, /*tp_dict*/ - (descrgetfunc)WraptFunctionWrapperBase_descr_get, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - 0, /*tp_dictoffset*/ - (initproc)WraptFunctionWrapperBase_init, /*tp_init*/ - 0, /*tp_alloc*/ - WraptFunctionWrapperBase_new, /*tp_new*/ - 0, /*tp_free*/ - 0, /*tp_is_gc*/ -}; - -/* ------------------------------------------------------------------------- */ - -static PyObject *WraptBoundFunctionWrapper_call( - WraptFunctionWrapperObject *self, PyObject *args, PyObject *kwds) -{ - PyObject *param_args = NULL; - PyObject *param_kwds = NULL; - - PyObject *wrapped = NULL; - PyObject *instance = NULL; - - PyObject *result = NULL; - - static PyObject *function_str = NULL; - - if (self->enabled != Py_None) { - if (PyCallable_Check(self->enabled)) { - PyObject *object = NULL; - - object = PyObject_CallFunctionObjArgs(self->enabled, NULL); - - if (!object) - return NULL; - - if (PyObject_Not(object)) { - Py_DECREF(object); - return PyObject_Call(self->object_proxy.wrapped, args, kwds); - } - - Py_DECREF(object); - } - else if (PyObject_Not(self->enabled)) { - return PyObject_Call(self->object_proxy.wrapped, args, kwds); - } - } - - if (!function_str) { -#if PY_MAJOR_VERSION >= 3 - function_str = PyUnicode_InternFromString("function"); -#else - function_str = PyString_InternFromString("function"); -#endif - } - - /* - * We need to do things different depending on whether we are likely - * wrapping an instance method vs a static method or class method. - */ - - if (self->binding == function_str || PyObject_RichCompareBool( - self->binding, function_str, Py_EQ) == 1) { - - if (self->instance == Py_None) { - /* - * This situation can occur where someone is calling the - * instancemethod via the class type and passing the - * instance as the first argument. We need to shift the args - * before making the call to the wrapper and effectively - * bind the instance to the wrapped function using a partial - * so the wrapper doesn't see anything as being different. - */ - - if (PyTuple_Size(args) == 0) { - PyErr_SetString(PyExc_TypeError, - "missing 1 required positional argument"); - return NULL; - } - - instance = PyTuple_GetItem(args, 0); - - if (!instance) - return NULL; - - wrapped = PyObject_CallFunctionObjArgs( - (PyObject *)&WraptPartialCallableObjectProxy_Type, - self->object_proxy.wrapped, instance, NULL); - - if (!wrapped) - return NULL; - - param_args = PyTuple_GetSlice(args, 1, PyTuple_Size(args)); - - if (!param_args) { - Py_DECREF(wrapped); - return NULL; - } - - args = param_args; - } - else - instance = self->instance; - - if (!wrapped) { - Py_INCREF(self->object_proxy.wrapped); - wrapped = self->object_proxy.wrapped; - } - - if (!kwds) { - param_kwds = PyDict_New(); - kwds = param_kwds; - } - - result = PyObject_CallFunctionObjArgs(self->wrapper, wrapped, - instance, args, kwds, NULL); - - Py_XDECREF(param_args); - Py_XDECREF(param_kwds); - Py_DECREF(wrapped); - - return result; - } - else { - /* - * As in this case we would be dealing with a classmethod or - * staticmethod, then _self_instance will only tell us whether - * when calling the classmethod or staticmethod they did it via - * an instance of the class it is bound to and not the case - * where done by the class type itself. We thus ignore - * _self_instance and use the __self__ attribute of the bound - * function instead. For a classmethod, this means instance will - * be the class type and for a staticmethod it will be None. - * This is probably the more useful thing we can pass through - * even though we loose knowledge of whether they were called on - * the instance vs the class type, as it reflects what they have - * available in the decoratored function. - */ - - instance = PyObject_GetAttrString(self->object_proxy.wrapped, - "__self__"); - - if (!instance) { - PyErr_Clear(); - Py_INCREF(Py_None); - instance = Py_None; - } - - if (!kwds) { - param_kwds = PyDict_New(); - kwds = param_kwds; - } - - result = PyObject_CallFunctionObjArgs(self->wrapper, - self->object_proxy.wrapped, instance, args, kwds, NULL); - - Py_XDECREF(param_kwds); - - Py_DECREF(instance); - - return result; - } -} - -/* ------------------------------------------------------------------------- */ - -static PyGetSetDef WraptBoundFunctionWrapper_getset[] = { - { "__module__", (getter)WraptObjectProxy_get_module, - (setter)WraptObjectProxy_set_module, 0 }, - { "__doc__", (getter)WraptObjectProxy_get_doc, - (setter)WraptObjectProxy_set_doc, 0 }, - { NULL }, -}; - -PyTypeObject WraptBoundFunctionWrapper_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "BoundFunctionWrapper", /*tp_name*/ - sizeof(WraptFunctionWrapperObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - 0, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - (ternaryfunc)WraptBoundFunctionWrapper_call, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ -#if PY_MAJOR_VERSION < 3 - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ -#else - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ -#endif - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - offsetof(WraptObjectProxyObject, weakreflist), /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - 0, /*tp_methods*/ - 0, /*tp_members*/ - WraptBoundFunctionWrapper_getset, /*tp_getset*/ - 0, /*tp_base*/ - 0, /*tp_dict*/ - 0, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - 0, /*tp_dictoffset*/ - 0, /*tp_init*/ - 0, /*tp_alloc*/ - 0, /*tp_new*/ - 0, /*tp_free*/ - 0, /*tp_is_gc*/ -}; - -/* ------------------------------------------------------------------------- */ - -static int WraptFunctionWrapper_init(WraptFunctionWrapperObject *self, - PyObject *args, PyObject *kwds) -{ - PyObject *wrapped = NULL; - PyObject *wrapper = NULL; - PyObject *enabled = Py_None; - PyObject *binding = NULL; - PyObject *instance = NULL; - - static PyObject *classmethod_str = NULL; - static PyObject *staticmethod_str = NULL; - static PyObject *function_str = NULL; - - int result = 0; - - static char *kwlist[] = { "wrapped", "wrapper", "enabled", NULL }; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|O:FunctionWrapper", - kwlist, &wrapped, &wrapper, &enabled)) { - return -1; - } - - if (!classmethod_str) { -#if PY_MAJOR_VERSION >= 3 - classmethod_str = PyUnicode_InternFromString("classmethod"); -#else - classmethod_str = PyString_InternFromString("classmethod"); -#endif - } - - if (!staticmethod_str) { -#if PY_MAJOR_VERSION >= 3 - staticmethod_str = PyUnicode_InternFromString("staticmethod"); -#else - staticmethod_str = PyString_InternFromString("staticmethod"); -#endif - } - - if (!function_str) { -#if PY_MAJOR_VERSION >= 3 - function_str = PyUnicode_InternFromString("function"); -#else - function_str = PyString_InternFromString("function"); -#endif - } - - if (PyObject_IsInstance(wrapped, (PyObject *)&PyClassMethod_Type)) { - binding = classmethod_str; - } - else if (PyObject_IsInstance(wrapped, (PyObject *)&PyStaticMethod_Type)) { - binding = staticmethod_str; - } - else if ((instance = PyObject_GetAttrString(wrapped, "__self__")) != 0) { -#if PY_MAJOR_VERSION < 3 - if (PyObject_IsInstance(instance, (PyObject *)&PyClass_Type) || - PyObject_IsInstance(instance, (PyObject *)&PyType_Type)) { - binding = classmethod_str; - } -#else - if (PyObject_IsInstance(instance, (PyObject *)&PyType_Type)) { - binding = classmethod_str; - } -#endif - else - binding = function_str; - - Py_DECREF(instance); - } - else { - PyErr_Clear(); - - binding = function_str; - } - - result = WraptFunctionWrapperBase_raw_init(self, wrapped, Py_None, - wrapper, enabled, binding, Py_None); - - return result; -} - -/* ------------------------------------------------------------------------- */ - -static PyGetSetDef WraptFunctionWrapper_getset[] = { - { "__module__", (getter)WraptObjectProxy_get_module, - (setter)WraptObjectProxy_set_module, 0 }, - { "__doc__", (getter)WraptObjectProxy_get_doc, - (setter)WraptObjectProxy_set_doc, 0 }, - { NULL }, -}; - -PyTypeObject WraptFunctionWrapper_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "FunctionWrapper", /*tp_name*/ - sizeof(WraptFunctionWrapperObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - 0, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ -#if PY_MAJOR_VERSION < 3 - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ -#else - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ -#endif - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - offsetof(WraptObjectProxyObject, weakreflist), /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - 0, /*tp_methods*/ - 0, /*tp_members*/ - WraptFunctionWrapper_getset, /*tp_getset*/ - 0, /*tp_base*/ - 0, /*tp_dict*/ - 0, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - 0, /*tp_dictoffset*/ - (initproc)WraptFunctionWrapper_init, /*tp_init*/ - 0, /*tp_alloc*/ - 0, /*tp_new*/ - 0, /*tp_free*/ - 0, /*tp_is_gc*/ -}; - -/* ------------------------------------------------------------------------- */ - -#if PY_MAJOR_VERSION >= 3 -static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, - "_wrappers", /* m_name */ - NULL, /* m_doc */ - -1, /* m_size */ - NULL, /* m_methods */ - NULL, /* m_reload */ - NULL, /* m_traverse */ - NULL, /* m_clear */ - NULL, /* m_free */ -}; -#endif - -static PyObject * -moduleinit(void) -{ - PyObject *module; - -#if PY_MAJOR_VERSION >= 3 - module = PyModule_Create(&moduledef); -#else - module = Py_InitModule3("_wrappers", NULL, NULL); -#endif - - if (module == NULL) - return NULL; - - if (PyType_Ready(&WraptObjectProxy_Type) < 0) - return NULL; - - /* Ensure that inheritance relationships specified. */ - - WraptCallableObjectProxy_Type.tp_base = &WraptObjectProxy_Type; - WraptPartialCallableObjectProxy_Type.tp_base = &WraptObjectProxy_Type; - WraptFunctionWrapperBase_Type.tp_base = &WraptObjectProxy_Type; - WraptBoundFunctionWrapper_Type.tp_base = &WraptFunctionWrapperBase_Type; - WraptFunctionWrapper_Type.tp_base = &WraptFunctionWrapperBase_Type; - - if (PyType_Ready(&WraptCallableObjectProxy_Type) < 0) - return NULL; - if (PyType_Ready(&WraptPartialCallableObjectProxy_Type) < 0) - return NULL; - if (PyType_Ready(&WraptFunctionWrapperBase_Type) < 0) - return NULL; - if (PyType_Ready(&WraptBoundFunctionWrapper_Type) < 0) - return NULL; - if (PyType_Ready(&WraptFunctionWrapper_Type) < 0) - return NULL; - - Py_INCREF(&WraptObjectProxy_Type); - PyModule_AddObject(module, "ObjectProxy", - (PyObject *)&WraptObjectProxy_Type); - Py_INCREF(&WraptCallableObjectProxy_Type); - PyModule_AddObject(module, "CallableObjectProxy", - (PyObject *)&WraptCallableObjectProxy_Type); - PyModule_AddObject(module, "PartialCallableObjectProxy", - (PyObject *)&WraptPartialCallableObjectProxy_Type); - Py_INCREF(&WraptFunctionWrapper_Type); - PyModule_AddObject(module, "FunctionWrapper", - (PyObject *)&WraptFunctionWrapper_Type); - - Py_INCREF(&WraptFunctionWrapperBase_Type); - PyModule_AddObject(module, "_FunctionWrapperBase", - (PyObject *)&WraptFunctionWrapperBase_Type); - Py_INCREF(&WraptBoundFunctionWrapper_Type); - PyModule_AddObject(module, "BoundFunctionWrapper", - (PyObject *)&WraptBoundFunctionWrapper_Type); - - return module; -} - -#if PY_MAJOR_VERSION < 3 -PyMODINIT_FUNC init_wrappers(void) -{ - moduleinit(); -} -#else -PyMODINIT_FUNC PyInit__wrappers(void) -{ - return moduleinit(); -} -#endif - -/* ------------------------------------------------------------------------- */ diff --git a/ddtrace/vendor/wrapt/arguments.py b/ddtrace/vendor/wrapt/arguments.py deleted file mode 100644 index 032bc059e00..00000000000 --- a/ddtrace/vendor/wrapt/arguments.py +++ /dev/null @@ -1,38 +0,0 @@ -# The inspect.formatargspec() function was dropped in Python 3.11 but we need -# need it for when constructing signature changing decorators based on result of -# inspect.getargspec() or inspect.getfullargspec(). The code here implements -# inspect.formatargspec() base on Parameter and Signature from inspect module, -# which were added in Python 3.6. Thanks to Cyril Jouve for the implementation. - -try: - from inspect import Parameter, Signature -except ImportError: - from inspect import formatargspec -else: - def formatargspec(args, varargs=None, varkw=None, defaults=None, - kwonlyargs=(), kwonlydefaults={}, annotations={}): - if kwonlydefaults is None: - kwonlydefaults = {} - ndefaults = len(defaults) if defaults else 0 - parameters = [ - Parameter( - arg, - Parameter.POSITIONAL_OR_KEYWORD, - default=defaults[i] if i >= 0 else Parameter.empty, - annotation=annotations.get(arg, Parameter.empty), - ) for i, arg in enumerate(args, ndefaults - len(args)) - ] - if varargs: - parameters.append(Parameter(varargs, Parameter.VAR_POSITIONAL)) - parameters.extend( - Parameter( - kwonlyarg, - Parameter.KEYWORD_ONLY, - default=kwonlydefaults.get(kwonlyarg, Parameter.empty), - annotation=annotations.get(kwonlyarg, Parameter.empty), - ) for kwonlyarg in kwonlyargs - ) - if varkw: - parameters.append(Parameter(varkw, Parameter.VAR_KEYWORD)) - return_annotation = annotations.get('return', Signature.empty) - return str(Signature(parameters, return_annotation=return_annotation)) \ No newline at end of file diff --git a/ddtrace/vendor/wrapt/decorators.py b/ddtrace/vendor/wrapt/decorators.py deleted file mode 100644 index c3f2547295a..00000000000 --- a/ddtrace/vendor/wrapt/decorators.py +++ /dev/null @@ -1,541 +0,0 @@ -"""This module implements decorators for implementing other decorators -as well as some commonly used decorators. - -""" - -import sys - -PY2 = sys.version_info[0] == 2 - -if PY2: - string_types = basestring, - - def exec_(_code_, _globs_=None, _locs_=None): - """Execute code in a namespace.""" - if _globs_ is None: - frame = sys._getframe(1) - _globs_ = frame.f_globals - if _locs_ is None: - _locs_ = frame.f_locals - del frame - elif _locs_ is None: - _locs_ = _globs_ - exec("""exec _code_ in _globs_, _locs_""") - -else: - string_types = str, - - import builtins - - exec_ = getattr(builtins, "exec") - del builtins - -from functools import partial -from inspect import isclass -from threading import Lock, RLock - -from .arguments import formatargspec - -try: - from inspect import signature -except ImportError: - pass - -from .wrappers import (FunctionWrapper, BoundFunctionWrapper, ObjectProxy, - CallableObjectProxy) - -# Adapter wrapper for the wrapped function which will overlay certain -# properties from the adapter function onto the wrapped function so that -# functions such as inspect.getargspec(), inspect.getfullargspec(), -# inspect.signature() and inspect.getsource() return the correct results -# one would expect. - -class _AdapterFunctionCode(CallableObjectProxy): - - def __init__(self, wrapped_code, adapter_code): - super(_AdapterFunctionCode, self).__init__(wrapped_code) - self._self_adapter_code = adapter_code - - @property - def co_argcount(self): - return self._self_adapter_code.co_argcount - - @property - def co_code(self): - return self._self_adapter_code.co_code - - @property - def co_flags(self): - return self._self_adapter_code.co_flags - - @property - def co_kwonlyargcount(self): - return self._self_adapter_code.co_kwonlyargcount - - @property - def co_varnames(self): - return self._self_adapter_code.co_varnames - -class _AdapterFunctionSurrogate(CallableObjectProxy): - - def __init__(self, wrapped, adapter): - super(_AdapterFunctionSurrogate, self).__init__(wrapped) - self._self_adapter = adapter - - @property - def __code__(self): - return _AdapterFunctionCode(self.__wrapped__.__code__, - self._self_adapter.__code__) - - @property - def __defaults__(self): - return self._self_adapter.__defaults__ - - @property - def __kwdefaults__(self): - return self._self_adapter.__kwdefaults__ - - @property - def __signature__(self): - if 'signature' not in globals(): - return self._self_adapter.__signature__ - else: - return signature(self._self_adapter) - - if PY2: - func_code = __code__ - func_defaults = __defaults__ - -class _BoundAdapterWrapper(BoundFunctionWrapper): - - @property - def __func__(self): - return _AdapterFunctionSurrogate(self.__wrapped__.__func__, - self._self_parent._self_adapter) - - @property - def __signature__(self): - if 'signature' not in globals(): - return self.__wrapped__.__signature__ - else: - return signature(self._self_parent._self_adapter) - - if PY2: - im_func = __func__ - -class AdapterWrapper(FunctionWrapper): - - __bound_function_wrapper__ = _BoundAdapterWrapper - - def __init__(self, *args, **kwargs): - adapter = kwargs.pop('adapter') - super(AdapterWrapper, self).__init__(*args, **kwargs) - self._self_surrogate = _AdapterFunctionSurrogate( - self.__wrapped__, adapter) - self._self_adapter = adapter - - @property - def __code__(self): - return self._self_surrogate.__code__ - - @property - def __defaults__(self): - return self._self_surrogate.__defaults__ - - @property - def __kwdefaults__(self): - return self._self_surrogate.__kwdefaults__ - - if PY2: - func_code = __code__ - func_defaults = __defaults__ - - @property - def __signature__(self): - return self._self_surrogate.__signature__ - -class AdapterFactory(object): - def __call__(self, wrapped): - raise NotImplementedError() - -class DelegatedAdapterFactory(AdapterFactory): - def __init__(self, factory): - super(DelegatedAdapterFactory, self).__init__() - self.factory = factory - def __call__(self, wrapped): - return self.factory(wrapped) - -adapter_factory = DelegatedAdapterFactory - -# Decorator for creating other decorators. This decorator and the -# wrappers which they use are designed to properly preserve any name -# attributes, function signatures etc, in addition to the wrappers -# themselves acting like a transparent proxy for the original wrapped -# function so the wrapper is effectively indistinguishable from the -# original wrapped function. - -def decorator(wrapper=None, enabled=None, adapter=None, proxy=FunctionWrapper): - # The decorator should be supplied with a single positional argument - # which is the wrapper function to be used to implement the - # decorator. This may be preceded by a step whereby the keyword - # arguments are supplied to customise the behaviour of the - # decorator. The 'adapter' argument is used to optionally denote a - # separate function which is notionally used by an adapter - # decorator. In that case parts of the function '__code__' and - # '__defaults__' attributes are used from the adapter function - # rather than those of the wrapped function. This allows for the - # argument specification from inspect.getfullargspec() and similar - # functions to be overridden with a prototype for a different - # function than what was wrapped. The 'enabled' argument provides a - # way to enable/disable the use of the decorator. If the type of - # 'enabled' is a boolean, then it is evaluated immediately and the - # wrapper not even applied if it is False. If not a boolean, it will - # be evaluated when the wrapper is called for an unbound wrapper, - # and when binding occurs for a bound wrapper. When being evaluated, - # if 'enabled' is callable it will be called to obtain the value to - # be checked. If False, the wrapper will not be called and instead - # the original wrapped function will be called directly instead. - # The 'proxy' argument provides a way of passing a custom version of - # the FunctionWrapper class used in decorating the function. - - if wrapper is not None: - # Helper function for creating wrapper of the appropriate - # time when we need it down below. - - def _build(wrapped, wrapper, enabled=None, adapter=None): - if adapter: - if isinstance(adapter, AdapterFactory): - adapter = adapter(wrapped) - - if not callable(adapter): - ns = {} - - # Check if the signature argument specification has - # annotations. If it does then we need to remember - # it but also drop it when attempting to manufacture - # a standin adapter function. This is necessary else - # it will try and look up any types referenced in - # the annotations in the empty namespace we use, - # which will fail. - - annotations = {} - - if not isinstance(adapter, string_types): - if len(adapter) == 7: - annotations = adapter[-1] - adapter = adapter[:-1] - adapter = formatargspec(*adapter) - - exec_('def adapter{}: pass'.format(adapter), ns, ns) - adapter = ns['adapter'] - - # Override the annotations for the manufactured - # adapter function so they match the original - # adapter signature argument specification. - - if annotations: - adapter.__annotations__ = annotations - - return AdapterWrapper(wrapped=wrapped, wrapper=wrapper, - enabled=enabled, adapter=adapter) - - return proxy(wrapped=wrapped, wrapper=wrapper, enabled=enabled) - - # The wrapper has been provided so return the final decorator. - # The decorator is itself one of our function wrappers so we - # can determine when it is applied to functions, instance methods - # or class methods. This allows us to bind the instance or class - # method so the appropriate self or cls attribute is supplied - # when it is finally called. - - def _wrapper(wrapped, instance, args, kwargs): - # We first check for the case where the decorator was applied - # to a class type. - # - # @decorator - # class mydecoratorclass(object): - # def __init__(self, arg=None): - # self.arg = arg - # def __call__(self, wrapped, instance, args, kwargs): - # return wrapped(*args, **kwargs) - # - # @mydecoratorclass(arg=1) - # def function(): - # pass - # - # In this case an instance of the class is to be used as the - # decorator wrapper function. If args was empty at this point, - # then it means that there were optional keyword arguments - # supplied to be used when creating an instance of the class - # to be used as the wrapper function. - - if instance is None and isclass(wrapped) and not args: - # We still need to be passed the target function to be - # wrapped as yet, so we need to return a further function - # to be able to capture it. - - def _capture(target_wrapped): - # Now have the target function to be wrapped and need - # to create an instance of the class which is to act - # as the decorator wrapper function. Before we do that, - # we need to first check that use of the decorator - # hadn't been disabled by a simple boolean. If it was, - # the target function to be wrapped is returned instead. - - _enabled = enabled - if type(_enabled) is bool: - if not _enabled: - return target_wrapped - _enabled = None - - # Now create an instance of the class which is to act - # as the decorator wrapper function. Any arguments had - # to be supplied as keyword only arguments so that is - # all we pass when creating it. - - target_wrapper = wrapped(**kwargs) - - # Finally build the wrapper itself and return it. - - return _build(target_wrapped, target_wrapper, - _enabled, adapter) - - return _capture - - # We should always have the target function to be wrapped at - # this point as the first (and only) value in args. - - target_wrapped = args[0] - - # Need to now check that use of the decorator hadn't been - # disabled by a simple boolean. If it was, then target - # function to be wrapped is returned instead. - - _enabled = enabled - if type(_enabled) is bool: - if not _enabled: - return target_wrapped - _enabled = None - - # We now need to build the wrapper, but there are a couple of - # different cases we need to consider. - - if instance is None: - if isclass(wrapped): - # In this case the decorator was applied to a class - # type but optional keyword arguments were not supplied - # for initialising an instance of the class to be used - # as the decorator wrapper function. - # - # @decorator - # class mydecoratorclass(object): - # def __init__(self, arg=None): - # self.arg = arg - # def __call__(self, wrapped, instance, - # args, kwargs): - # return wrapped(*args, **kwargs) - # - # @mydecoratorclass - # def function(): - # pass - # - # We still need to create an instance of the class to - # be used as the decorator wrapper function, but no - # arguments are pass. - - target_wrapper = wrapped() - - else: - # In this case the decorator was applied to a normal - # function, or possibly a static method of a class. - # - # @decorator - # def mydecoratorfuntion(wrapped, instance, - # args, kwargs): - # return wrapped(*args, **kwargs) - # - # @mydecoratorfunction - # def function(): - # pass - # - # That normal function becomes the decorator wrapper - # function. - - target_wrapper = wrapper - - else: - if isclass(instance): - # In this case the decorator was applied to a class - # method. - # - # class myclass(object): - # @decorator - # @classmethod - # def decoratorclassmethod(cls, wrapped, - # instance, args, kwargs): - # return wrapped(*args, **kwargs) - # - # instance = myclass() - # - # @instance.decoratorclassmethod - # def function(): - # pass - # - # This one is a bit strange because binding was actually - # performed on the wrapper created by our decorator - # factory. We need to apply that binding to the decorator - # wrapper function that the decorator factory - # was applied to. - - target_wrapper = wrapper.__get__(None, instance) - - else: - # In this case the decorator was applied to an instance - # method. - # - # class myclass(object): - # @decorator - # def decoratorclassmethod(self, wrapped, - # instance, args, kwargs): - # return wrapped(*args, **kwargs) - # - # instance = myclass() - # - # @instance.decoratorclassmethod - # def function(): - # pass - # - # This one is a bit strange because binding was actually - # performed on the wrapper created by our decorator - # factory. We need to apply that binding to the decorator - # wrapper function that the decorator factory - # was applied to. - - target_wrapper = wrapper.__get__(instance, type(instance)) - - # Finally build the wrapper itself and return it. - - return _build(target_wrapped, target_wrapper, _enabled, adapter) - - # We first return our magic function wrapper here so we can - # determine in what context the decorator factory was used. In - # other words, it is itself a universal decorator. The decorator - # function is used as the adapter so that linters see a signature - # corresponding to the decorator and not the wrapper it is being - # applied to. - - return _build(wrapper, _wrapper, adapter=decorator) - - else: - # The wrapper still has not been provided, so we are just - # collecting the optional keyword arguments. Return the - # decorator again wrapped in a partial using the collected - # arguments. - - return partial(decorator, enabled=enabled, adapter=adapter, - proxy=proxy) - -# Decorator for implementing thread synchronization. It can be used as a -# decorator, in which case the synchronization context is determined by -# what type of function is wrapped, or it can also be used as a context -# manager, where the user needs to supply the correct synchronization -# context. It is also possible to supply an object which appears to be a -# synchronization primitive of some sort, by virtue of having release() -# and acquire() methods. In that case that will be used directly as the -# synchronization primitive without creating a separate lock against the -# derived or supplied context. - -def synchronized(wrapped): - # Determine if being passed an object which is a synchronization - # primitive. We can't check by type for Lock, RLock, Semaphore etc, - # as the means of creating them isn't the type. Therefore use the - # existence of acquire() and release() methods. This is more - # extensible anyway as it allows custom synchronization mechanisms. - - if hasattr(wrapped, 'acquire') and hasattr(wrapped, 'release'): - # We remember what the original lock is and then return a new - # decorator which accesses and locks it. When returning the new - # decorator we wrap it with an object proxy so we can override - # the context manager methods in case it is being used to wrap - # synchronized statements with a 'with' statement. - - lock = wrapped - - @decorator - def _synchronized(wrapped, instance, args, kwargs): - # Execute the wrapped function while the original supplied - # lock is held. - - with lock: - return wrapped(*args, **kwargs) - - class _PartialDecorator(CallableObjectProxy): - - def __enter__(self): - lock.acquire() - return lock - - def __exit__(self, *args): - lock.release() - - return _PartialDecorator(wrapped=_synchronized) - - # Following only apply when the lock is being created automatically - # based on the context of what was supplied. In this case we supply - # a final decorator, but need to use FunctionWrapper directly as we - # want to derive from it to add context manager methods in case it is - # being used to wrap synchronized statements with a 'with' statement. - - def _synchronized_lock(context): - # Attempt to retrieve the lock for the specific context. - - lock = vars(context).get('_synchronized_lock', None) - - if lock is None: - # There is no existing lock defined for the context we - # are dealing with so we need to create one. This needs - # to be done in a way to guarantee there is only one - # created, even if multiple threads try and create it at - # the same time. We can't always use the setdefault() - # method on the __dict__ for the context. This is the - # case where the context is a class, as __dict__ is - # actually a dictproxy. What we therefore do is use a - # meta lock on this wrapper itself, to control the - # creation and assignment of the lock attribute against - # the context. - - with synchronized._synchronized_meta_lock: - # We need to check again for whether the lock we want - # exists in case two threads were trying to create it - # at the same time and were competing to create the - # meta lock. - - lock = vars(context).get('_synchronized_lock', None) - - if lock is None: - lock = RLock() - setattr(context, '_synchronized_lock', lock) - - return lock - - def _synchronized_wrapper(wrapped, instance, args, kwargs): - # Execute the wrapped function while the lock for the - # desired context is held. If instance is None then the - # wrapped function is used as the context. - - with _synchronized_lock(instance if instance is not None else wrapped): - return wrapped(*args, **kwargs) - - class _FinalDecorator(FunctionWrapper): - - def __enter__(self): - self._self_lock = _synchronized_lock(self.__wrapped__) - self._self_lock.acquire() - return self._self_lock - - def __exit__(self, *args): - self._self_lock.release() - - return _FinalDecorator(wrapped=wrapped, wrapper=_synchronized_wrapper) - -synchronized._synchronized_meta_lock = Lock() diff --git a/ddtrace/vendor/wrapt/importer.py b/ddtrace/vendor/wrapt/importer.py deleted file mode 100644 index 5c4d4cc6630..00000000000 --- a/ddtrace/vendor/wrapt/importer.py +++ /dev/null @@ -1,286 +0,0 @@ -"""This module implements a post import hook mechanism styled after what is -described in PEP-369. Note that it doesn't cope with modules being reloaded. - -""" - -import sys -import threading - -PY2 = sys.version_info[0] == 2 - -if PY2: - string_types = basestring, - find_spec = None -else: - string_types = str, - from importlib.util import find_spec - -from .decorators import synchronized - -# The dictionary registering any post import hooks to be triggered once -# the target module has been imported. Once a module has been imported -# and the hooks fired, the list of hooks recorded against the target -# module will be truncated but the list left in the dictionary. This -# acts as a flag to indicate that the module had already been imported. - -_post_import_hooks = {} -_post_import_hooks_init = False -_post_import_hooks_lock = threading.RLock() - -# Register a new post import hook for the target module name. This -# differs from the PEP-369 implementation in that it also allows the -# hook function to be specified as a string consisting of the name of -# the callback in the form 'module:function'. This will result in a -# proxy callback being registered which will defer loading of the -# specified module containing the callback function until required. - -def _create_import_hook_from_string(name): - def import_hook(module): - module_name, function = name.split(':') - attrs = function.split('.') - __import__(module_name) - callback = sys.modules[module_name] - for attr in attrs: - callback = getattr(callback, attr) - return callback(module) - return import_hook - -@synchronized(_post_import_hooks_lock) -def register_post_import_hook(hook, name): - # Create a deferred import hook if hook is a string name rather than - # a callable function. - - if isinstance(hook, string_types): - hook = _create_import_hook_from_string(hook) - - # Automatically install the import hook finder if it has not already - # been installed. - - global _post_import_hooks_init - - if not _post_import_hooks_init: - _post_import_hooks_init = True - sys.meta_path.insert(0, ImportHookFinder()) - - # Determine if any prior registration of a post import hook for - # the target modules has occurred and act appropriately. - - hooks = _post_import_hooks.get(name, None) - - if hooks is None: - # No prior registration of post import hooks for the target - # module. We need to check whether the module has already been - # imported. If it has we fire the hook immediately and add an - # empty list to the registry to indicate that the module has - # already been imported and hooks have fired. Otherwise add - # the post import hook to the registry. - - module = sys.modules.get(name, None) - - if module is not None: - _post_import_hooks[name] = [] - hook(module) - - else: - _post_import_hooks[name] = [hook] - - elif hooks == []: - # A prior registration of port import hooks for the target - # module was done and the hooks already fired. Fire the hook - # immediately. - - module = sys.modules[name] - hook(module) - - else: - # A prior registration of port import hooks for the target - # module was done but the module has not yet been imported. - - _post_import_hooks[name].append(hook) - -# Register post import hooks defined as package entry points. - -def _create_import_hook_from_entrypoint(entrypoint): - def import_hook(module): - __import__(entrypoint.module_name) - callback = sys.modules[entrypoint.module_name] - for attr in entrypoint.attrs: - callback = getattr(callback, attr) - return callback(module) - return import_hook - -def discover_post_import_hooks(group): - try: - import pkg_resources - except ImportError: - return - - for entrypoint in pkg_resources.iter_entry_points(group=group): - callback = _create_import_hook_from_entrypoint(entrypoint) - register_post_import_hook(callback, entrypoint.name) - -# Indicate that a module has been loaded. Any post import hooks which -# were registered against the target module will be invoked. If an -# exception is raised in any of the post import hooks, that will cause -# the import of the target module to fail. - -@synchronized(_post_import_hooks_lock) -def notify_module_loaded(module): - name = getattr(module, '__name__', None) - hooks = _post_import_hooks.get(name, None) - - if hooks: - _post_import_hooks[name] = [] - - for hook in hooks: - hook(module) - -# A custom module import finder. This intercepts attempts to import -# modules and watches out for attempts to import target modules of -# interest. When a module of interest is imported, then any post import -# hooks which are registered will be invoked. - -class _ImportHookLoader: - - def load_module(self, fullname): - module = sys.modules[fullname] - notify_module_loaded(module) - - return module - -class _ImportHookChainedLoader: - - def __init__(self, loader): - self.loader = loader - - if hasattr(loader, "load_module"): - self.load_module = self._load_module - if hasattr(loader, "create_module"): - self.create_module = self._create_module - if hasattr(loader, "exec_module"): - self.exec_module = self._exec_module - - def _load_module(self, fullname): - module = self.loader.load_module(fullname) - notify_module_loaded(module) - - return module - - # Python 3.4 introduced create_module() and exec_module() instead of - # load_module() alone. Splitting the two steps. - - def _create_module(self, spec): - return self.loader.create_module(spec) - - def _exec_module(self, module): - self.loader.exec_module(module) - notify_module_loaded(module) - -class ImportHookFinder: - - def __init__(self): - self.in_progress = {} - - @synchronized(_post_import_hooks_lock) - def find_module(self, fullname, path=None): - # If the module being imported is not one we have registered - # post import hooks for, we can return immediately. We will - # take no further part in the importing of this module. - - if not fullname in _post_import_hooks: - return None - - # When we are interested in a specific module, we will call back - # into the import system a second time to defer to the import - # finder that is supposed to handle the importing of the module. - # We set an in progress flag for the target module so that on - # the second time through we don't trigger another call back - # into the import system and cause a infinite loop. - - if fullname in self.in_progress: - return None - - self.in_progress[fullname] = True - - # Now call back into the import system again. - - try: - if not find_spec: - # For Python 2 we don't have much choice but to - # call back in to __import__(). This will - # actually cause the module to be imported. If no - # module could be found then ImportError will be - # raised. Otherwise we return a loader which - # returns the already loaded module and invokes - # the post import hooks. - - __import__(fullname) - - return _ImportHookLoader() - - else: - # For Python 3 we need to use find_spec().loader - # from the importlib.util module. It doesn't actually - # import the target module and only finds the - # loader. If a loader is found, we need to return - # our own loader which will then in turn call the - # real loader to import the module and invoke the - # post import hooks. - - loader = getattr(find_spec(fullname), "loader", None) - - if loader and not isinstance(loader, _ImportHookChainedLoader): - return _ImportHookChainedLoader(loader) - - finally: - del self.in_progress[fullname] - - def find_spec(self, fullname, path=None, target=None): - # Since Python 3.4, you are meant to implement find_spec() method - # instead of find_module() and since Python 3.10 you get deprecation - # warnings if you don't define find_spec(). - - # If the module being imported is not one we have registered - # post import hooks for, we can return immediately. We will - # take no further part in the importing of this module. - - if not fullname in _post_import_hooks: - return None - - # When we are interested in a specific module, we will call back - # into the import system a second time to defer to the import - # finder that is supposed to handle the importing of the module. - # We set an in progress flag for the target module so that on - # the second time through we don't trigger another call back - # into the import system and cause a infinite loop. - - if fullname in self.in_progress: - return None - - self.in_progress[fullname] = True - - # Now call back into the import system again. - - try: - # This should only be Python 3 so find_spec() should always - # exist so don't need to check. - - spec = find_spec(fullname) - loader = getattr(spec, "loader", None) - - if loader and not isinstance(loader, _ImportHookChainedLoader): - spec.loader = _ImportHookChainedLoader(loader) - - return spec - - finally: - del self.in_progress[fullname] - -# Decorator for marking that a function should be called as a post -# import hook when the target module is imported. - -def when_imported(name): - def register(hook): - register_post_import_hook(hook, name) - return hook - return register diff --git a/ddtrace/vendor/wrapt/setup.py b/ddtrace/vendor/wrapt/setup.py deleted file mode 100644 index dae324bd230..00000000000 --- a/ddtrace/vendor/wrapt/setup.py +++ /dev/null @@ -1,7 +0,0 @@ -__all__ = ["get_extensions"] - -from setuptools import Extension - - -def get_extensions(): - return [Extension("ddtrace.vendor.wrapt._wrappers", sources=["ddtrace/vendor/wrapt/_wrappers.c"],)] diff --git a/ddtrace/vendor/wrapt/wrappers.py b/ddtrace/vendor/wrapt/wrappers.py deleted file mode 100644 index e2825c644c2..00000000000 --- a/ddtrace/vendor/wrapt/wrappers.py +++ /dev/null @@ -1,1001 +0,0 @@ -import os -import sys -import functools -import operator -import weakref -import inspect - -PY2 = sys.version_info[0] == 2 - -if PY2: - string_types = (basestring,) -else: - string_types = (str,) - - -def with_metaclass(meta, *bases): - """Create a base class with a metaclass.""" - return meta("NewBase", bases, {}) - - -class _ObjectProxyMethods(object): - - # We use properties to override the values of __module__ and - # __doc__. If we add these in ObjectProxy, the derived class - # __dict__ will still be setup to have string variants of these - # attributes and the rules of descriptors means that they appear to - # take precedence over the properties in the base class. To avoid - # that, we copy the properties into the derived class type itself - # via a meta class. In that way the properties will always take - # precedence. - - @property - def __module__(self): - return self.__wrapped__.__module__ - - @__module__.setter - def __module__(self, value): - self.__wrapped__.__module__ = value - - @property - def __doc__(self): - return self.__wrapped__.__doc__ - - @__doc__.setter - def __doc__(self, value): - self.__wrapped__.__doc__ = value - - # We similar use a property for __dict__. We need __dict__ to be - # explicit to ensure that vars() works as expected. - - @property - def __dict__(self): - return self.__wrapped__.__dict__ - - # Need to also propagate the special __weakref__ attribute for case - # where decorating classes which will define this. If do not define - # it and use a function like inspect.getmembers() on a decorator - # class it will fail. This can't be in the derived classes. - - @property - def __weakref__(self): - return self.__wrapped__.__weakref__ - - -class _ObjectProxyMetaType(type): - def __new__(cls, name, bases, dictionary): - # Copy our special properties into the class so that they - # always take precedence over attributes of the same name added - # during construction of a derived class. This is to save - # duplicating the implementation for them in all derived classes. - - dictionary.update(vars(_ObjectProxyMethods)) - - return type.__new__(cls, name, bases, dictionary) - - -class ObjectProxy(with_metaclass(_ObjectProxyMetaType)): - - __slots__ = "__wrapped__" - - def __init__(self, wrapped): - object.__setattr__(self, "__wrapped__", wrapped) - - # Python 3.2+ has the __qualname__ attribute, but it does not - # allow it to be overridden using a property and it must instead - # be an actual string object instead. - - try: - object.__setattr__(self, "__qualname__", wrapped.__qualname__) - except AttributeError: - pass - - # Python 3.10 onwards also does not allow itself to be overridden - # using a property and it must instead be set explicitly. - - try: - object.__setattr__(self, "__annotations__", wrapped.__annotations__) - except AttributeError: - pass - - @property - def __name__(self): - return self.__wrapped__.__name__ - - @__name__.setter - def __name__(self, value): - self.__wrapped__.__name__ = value - - @property - def __class__(self): - return self.__wrapped__.__class__ - - @__class__.setter - def __class__(self, value): - self.__wrapped__.__class__ = value - - def __dir__(self): - return dir(self.__wrapped__) - - def __str__(self): - return str(self.__wrapped__) - - if not PY2: - - def __bytes__(self): - return bytes(self.__wrapped__) - - def __repr__(self): - return "<{} at 0x{:x} for {} at 0x{:x}>".format( - type(self).__name__, id(self), type(self.__wrapped__).__name__, id(self.__wrapped__) - ) - - def __reversed__(self): - return reversed(self.__wrapped__) - - if not PY2: - - def __round__(self): - return round(self.__wrapped__) - - if sys.hexversion >= 0x03070000: - - def __mro_entries__(self, bases): - return (self.__wrapped__,) - - def __lt__(self, other): - return self.__wrapped__ < other - - def __le__(self, other): - return self.__wrapped__ <= other - - def __eq__(self, other): - return self.__wrapped__ == other - - def __ne__(self, other): - return self.__wrapped__ != other - - def __gt__(self, other): - return self.__wrapped__ > other - - def __ge__(self, other): - return self.__wrapped__ >= other - - def __hash__(self): - return hash(self.__wrapped__) - - def __nonzero__(self): - return bool(self.__wrapped__) - - def __bool__(self): - return bool(self.__wrapped__) - - def __setattr__(self, name, value): - if name.startswith("_self_"): - object.__setattr__(self, name, value) - - elif name == "__wrapped__": - object.__setattr__(self, name, value) - try: - object.__delattr__(self, "__qualname__") - except AttributeError: - pass - try: - object.__setattr__(self, "__qualname__", value.__qualname__) - except AttributeError: - pass - try: - object.__delattr__(self, "__annotations__") - except AttributeError: - pass - try: - object.__setattr__(self, "__annotations__", value.__annotations__) - except AttributeError: - pass - - elif name == "__qualname__": - setattr(self.__wrapped__, name, value) - object.__setattr__(self, name, value) - - elif name == "__annotations__": - setattr(self.__wrapped__, name, value) - object.__setattr__(self, name, value) - - elif hasattr(type(self), name): - object.__setattr__(self, name, value) - - else: - setattr(self.__wrapped__, name, value) - - def __getattr__(self, name): - # If we are being to lookup '__wrapped__' then the - # '__init__()' method cannot have been called. - - if name == "__wrapped__": - raise ValueError("wrapper has not been initialised") - - return getattr(self.__wrapped__, name) - - def __delattr__(self, name): - if name.startswith("_self_"): - object.__delattr__(self, name) - - elif name == "__wrapped__": - raise TypeError("__wrapped__ must be an object") - - elif name == "__qualname__": - object.__delattr__(self, name) - delattr(self.__wrapped__, name) - - elif hasattr(type(self), name): - object.__delattr__(self, name) - - else: - delattr(self.__wrapped__, name) - - def __add__(self, other): - return self.__wrapped__ + other - - def __sub__(self, other): - return self.__wrapped__ - other - - def __mul__(self, other): - return self.__wrapped__ * other - - def __div__(self, other): - return operator.div(self.__wrapped__, other) - - def __truediv__(self, other): - return operator.truediv(self.__wrapped__, other) - - def __floordiv__(self, other): - return self.__wrapped__ // other - - def __mod__(self, other): - return self.__wrapped__ % other - - def __divmod__(self, other): - return divmod(self.__wrapped__, other) - - def __pow__(self, other, *args): - return pow(self.__wrapped__, other, *args) - - def __lshift__(self, other): - return self.__wrapped__ << other - - def __rshift__(self, other): - return self.__wrapped__ >> other - - def __and__(self, other): - return self.__wrapped__ & other - - def __xor__(self, other): - return self.__wrapped__ ^ other - - def __or__(self, other): - return self.__wrapped__ | other - - def __radd__(self, other): - return other + self.__wrapped__ - - def __rsub__(self, other): - return other - self.__wrapped__ - - def __rmul__(self, other): - return other * self.__wrapped__ - - def __rdiv__(self, other): - return operator.div(other, self.__wrapped__) - - def __rtruediv__(self, other): - return operator.truediv(other, self.__wrapped__) - - def __rfloordiv__(self, other): - return other // self.__wrapped__ - - def __rmod__(self, other): - return other % self.__wrapped__ - - def __rdivmod__(self, other): - return divmod(other, self.__wrapped__) - - def __rpow__(self, other, *args): - return pow(other, self.__wrapped__, *args) - - def __rlshift__(self, other): - return other << self.__wrapped__ - - def __rrshift__(self, other): - return other >> self.__wrapped__ - - def __rand__(self, other): - return other & self.__wrapped__ - - def __rxor__(self, other): - return other ^ self.__wrapped__ - - def __ror__(self, other): - return other | self.__wrapped__ - - def __iadd__(self, other): - self.__wrapped__ += other - return self - - def __isub__(self, other): - self.__wrapped__ -= other - return self - - def __imul__(self, other): - self.__wrapped__ *= other - return self - - def __idiv__(self, other): - self.__wrapped__ = operator.idiv(self.__wrapped__, other) - return self - - def __itruediv__(self, other): - self.__wrapped__ = operator.itruediv(self.__wrapped__, other) - return self - - def __ifloordiv__(self, other): - self.__wrapped__ //= other - return self - - def __imod__(self, other): - self.__wrapped__ %= other - return self - - def __ipow__(self, other): - self.__wrapped__ **= other - return self - - def __ilshift__(self, other): - self.__wrapped__ <<= other - return self - - def __irshift__(self, other): - self.__wrapped__ >>= other - return self - - def __iand__(self, other): - self.__wrapped__ &= other - return self - - def __ixor__(self, other): - self.__wrapped__ ^= other - return self - - def __ior__(self, other): - self.__wrapped__ |= other - return self - - def __neg__(self): - return -self.__wrapped__ - - def __pos__(self): - return +self.__wrapped__ - - def __abs__(self): - return abs(self.__wrapped__) - - def __invert__(self): - return ~self.__wrapped__ - - def __int__(self): - return int(self.__wrapped__) - - def __long__(self): - return long(self.__wrapped__) - - def __float__(self): - return float(self.__wrapped__) - - def __complex__(self): - return complex(self.__wrapped__) - - def __oct__(self): - return oct(self.__wrapped__) - - def __hex__(self): - return hex(self.__wrapped__) - - def __index__(self): - return operator.index(self.__wrapped__) - - def __len__(self): - return len(self.__wrapped__) - - def __contains__(self, value): - return value in self.__wrapped__ - - def __getitem__(self, key): - return self.__wrapped__[key] - - def __setitem__(self, key, value): - self.__wrapped__[key] = value - - def __delitem__(self, key): - del self.__wrapped__[key] - - def __getslice__(self, i, j): - return self.__wrapped__[i:j] - - def __setslice__(self, i, j, value): - self.__wrapped__[i:j] = value - - def __delslice__(self, i, j): - del self.__wrapped__[i:j] - - def __enter__(self): - return self.__wrapped__.__enter__() - - def __exit__(self, *args, **kwargs): - return self.__wrapped__.__exit__(*args, **kwargs) - - def __iter__(self): - return iter(self.__wrapped__) - - def __copy__(self): - raise NotImplementedError("object proxy must define __copy__()") - - def __deepcopy__(self, memo): - raise NotImplementedError("object proxy must define __deepcopy__()") - - def __reduce__(self): - raise NotImplementedError("object proxy must define __reduce_ex__()") - - def __reduce_ex__(self, protocol): - raise NotImplementedError("object proxy must define __reduce_ex__()") - - -class CallableObjectProxy(ObjectProxy): - def __call__(self, *args, **kwargs): - return self.__wrapped__(*args, **kwargs) - - -class PartialCallableObjectProxy(ObjectProxy): - def __init__(self, *args, **kwargs): - if len(args) < 1: - raise TypeError("partial type takes at least one argument") - - wrapped, args = args[0], args[1:] - - if not callable(wrapped): - raise TypeError("the first argument must be callable") - - super(PartialCallableObjectProxy, self).__init__(wrapped) - - self._self_args = args - self._self_kwargs = kwargs - - def __call__(self, *args, **kwargs): - _args = self._self_args + args - - _kwargs = dict(self._self_kwargs) - _kwargs.update(kwargs) - - return self.__wrapped__(*_args, **_kwargs) - - -class _FunctionWrapperBase(ObjectProxy): - - __slots__ = ("_self_instance", "_self_wrapper", "_self_enabled", "_self_binding", "_self_parent") - - def __init__(self, wrapped, instance, wrapper, enabled=None, binding="function", parent=None): - - super(_FunctionWrapperBase, self).__init__(wrapped) - - object.__setattr__(self, "_self_instance", instance) - object.__setattr__(self, "_self_wrapper", wrapper) - object.__setattr__(self, "_self_enabled", enabled) - object.__setattr__(self, "_self_binding", binding) - object.__setattr__(self, "_self_parent", parent) - - def __get__(self, instance, owner): - # This method is actually doing double duty for both unbound and - # bound derived wrapper classes. It should possibly be broken up - # and the distinct functionality moved into the derived classes. - # Can't do that straight away due to some legacy code which is - # relying on it being here in this base class. - # - # The distinguishing attribute which determines whether we are - # being called in an unbound or bound wrapper is the parent - # attribute. If binding has never occurred, then the parent will - # be None. - # - # First therefore, is if we are called in an unbound wrapper. In - # this case we perform the binding. - # - # We have one special case to worry about here. This is where we - # are decorating a nested class. In this case the wrapped class - # would not have a __get__() method to call. In that case we - # simply return self. - # - # Note that we otherwise still do binding even if instance is - # None and accessing an unbound instance method from a class. - # This is because we need to be able to later detect that - # specific case as we will need to extract the instance from the - # first argument of those passed in. - - if self._self_parent is None: - if not inspect.isclass(self.__wrapped__): - descriptor = self.__wrapped__.__get__(instance, owner) - - return self.__bound_function_wrapper__( - descriptor, instance, self._self_wrapper, self._self_enabled, self._self_binding, self - ) - - return self - - # Now we have the case of binding occurring a second time on what - # was already a bound function. In this case we would usually - # return ourselves again. This mirrors what Python does. - # - # The special case this time is where we were originally bound - # with an instance of None and we were likely an instance - # method. In that case we rebind against the original wrapped - # function from the parent again. - - if self._self_instance is None and self._self_binding == "function": - descriptor = self._self_parent.__wrapped__.__get__(instance, owner) - - return self._self_parent.__bound_function_wrapper__( - descriptor, instance, self._self_wrapper, self._self_enabled, self._self_binding, self._self_parent - ) - - return self - - def __call__(self, *args, **kwargs): - # If enabled has been specified, then evaluate it at this point - # and if the wrapper is not to be executed, then simply return - # the bound function rather than a bound wrapper for the bound - # function. When evaluating enabled, if it is callable we call - # it, otherwise we evaluate it as a boolean. - - if self._self_enabled is not None: - if callable(self._self_enabled): - if not self._self_enabled(): - return self.__wrapped__(*args, **kwargs) - elif not self._self_enabled: - return self.__wrapped__(*args, **kwargs) - - # This can occur where initial function wrapper was applied to - # a function that was already bound to an instance. In that case - # we want to extract the instance from the function and use it. - - if self._self_binding in ("function", "classmethod"): - if self._self_instance is None: - instance = getattr(self.__wrapped__, "__self__", None) - if instance is not None: - return self._self_wrapper(self.__wrapped__, instance, args, kwargs) - - # This is generally invoked when the wrapped function is being - # called as a normal function and is not bound to a class as an - # instance method. This is also invoked in the case where the - # wrapped function was a method, but this wrapper was in turn - # wrapped using the staticmethod decorator. - - return self._self_wrapper(self.__wrapped__, self._self_instance, args, kwargs) - - def __set_name__(self, owner, name): - # This is a special method use to supply information to - # descriptors about what the name of variable in a class - # definition is. Not wanting to add this to ObjectProxy as not - # sure of broader implications of doing that. Thus restrict to - # FunctionWrapper used by decorators. - - if hasattr(self.__wrapped__, "__set_name__"): - self.__wrapped__.__set_name__(owner, name) - - def __instancecheck__(self, instance): - # This is a special method used by isinstance() to make checks - # instance of the `__wrapped__`. - return isinstance(instance, self.__wrapped__) - - def __subclasscheck__(self, subclass): - # This is a special method used by issubclass() to make checks - # about inheritance of classes. We need to upwrap any object - # proxy. Not wanting to add this to ObjectProxy as not sure of - # broader implications of doing that. Thus restrict to - # FunctionWrapper used by decorators. - - if hasattr(subclass, "__wrapped__"): - return issubclass(subclass.__wrapped__, self.__wrapped__) - else: - return issubclass(subclass, self.__wrapped__) - - -class BoundFunctionWrapper(_FunctionWrapperBase): - def __call__(self, *args, **kwargs): - # If enabled has been specified, then evaluate it at this point - # and if the wrapper is not to be executed, then simply return - # the bound function rather than a bound wrapper for the bound - # function. When evaluating enabled, if it is callable we call - # it, otherwise we evaluate it as a boolean. - - if self._self_enabled is not None: - if callable(self._self_enabled): - if not self._self_enabled(): - return self.__wrapped__(*args, **kwargs) - elif not self._self_enabled: - return self.__wrapped__(*args, **kwargs) - - # We need to do things different depending on whether we are - # likely wrapping an instance method vs a static method or class - # method. - - if self._self_binding == "function": - if self._self_instance is None: - # This situation can occur where someone is calling the - # instancemethod via the class type and passing the instance - # as the first argument. We need to shift the args before - # making the call to the wrapper and effectively bind the - # instance to the wrapped function using a partial so the - # wrapper doesn't see anything as being different. - - if not args: - raise TypeError("missing 1 required positional argument") - - instance, args = args[0], args[1:] - wrapped = PartialCallableObjectProxy(self.__wrapped__, instance) - return self._self_wrapper(wrapped, instance, args, kwargs) - - return self._self_wrapper(self.__wrapped__, self._self_instance, args, kwargs) - - else: - # As in this case we would be dealing with a classmethod or - # staticmethod, then _self_instance will only tell us whether - # when calling the classmethod or staticmethod they did it via an - # instance of the class it is bound to and not the case where - # done by the class type itself. We thus ignore _self_instance - # and use the __self__ attribute of the bound function instead. - # For a classmethod, this means instance will be the class type - # and for a staticmethod it will be None. This is probably the - # more useful thing we can pass through even though we loose - # knowledge of whether they were called on the instance vs the - # class type, as it reflects what they have available in the - # decoratored function. - - instance = getattr(self.__wrapped__, "__self__", None) - - return self._self_wrapper(self.__wrapped__, instance, args, kwargs) - - -class FunctionWrapper(_FunctionWrapperBase): - - __bound_function_wrapper__ = BoundFunctionWrapper - - def __init__(self, wrapped, wrapper, enabled=None): - # What it is we are wrapping here could be anything. We need to - # try and detect specific cases though. In particular, we need - # to detect when we are given something that is a method of a - # class. Further, we need to know when it is likely an instance - # method, as opposed to a class or static method. This can - # become problematic though as there isn't strictly a fool proof - # method of knowing. - # - # The situations we could encounter when wrapping a method are: - # - # 1. The wrapper is being applied as part of a decorator which - # is a part of the class definition. In this case what we are - # given is the raw unbound function, classmethod or staticmethod - # wrapper objects. - # - # The problem here is that we will not know we are being applied - # in the context of the class being set up. This becomes - # important later for the case of an instance method, because in - # that case we just see it as a raw function and can't - # distinguish it from wrapping a normal function outside of - # a class context. - # - # 2. The wrapper is being applied when performing monkey - # patching of the class type afterwards and the method to be - # wrapped was retrieved direct from the __dict__ of the class - # type. This is effectively the same as (1) above. - # - # 3. The wrapper is being applied when performing monkey - # patching of the class type afterwards and the method to be - # wrapped was retrieved from the class type. In this case - # binding will have been performed where the instance against - # which the method is bound will be None at that point. - # - # This case is a problem because we can no longer tell if the - # method was a static method, plus if using Python3, we cannot - # tell if it was an instance method as the concept of an - # unnbound method no longer exists. - # - # 4. The wrapper is being applied when performing monkey - # patching of an instance of a class. In this case binding will - # have been performed where the instance was not None. - # - # This case is a problem because we can no longer tell if the - # method was a static method. - # - # Overall, the best we can do is look at the original type of the - # object which was wrapped prior to any binding being done and - # see if it is an instance of classmethod or staticmethod. In - # the case where other decorators are between us and them, if - # they do not propagate the __class__ attribute so that the - # isinstance() checks works, then likely this will do the wrong - # thing where classmethod and staticmethod are used. - # - # Since it is likely to be very rare that anyone even puts - # decorators around classmethod and staticmethod, likelihood of - # that being an issue is very small, so we accept it and suggest - # that those other decorators be fixed. It is also only an issue - # if a decorator wants to actually do things with the arguments. - # - # As to not being able to identify static methods properly, we - # just hope that that isn't something people are going to want - # to wrap, or if they do suggest they do it the correct way by - # ensuring that it is decorated in the class definition itself, - # or patch it in the __dict__ of the class type. - # - # So to get the best outcome we can, whenever we aren't sure what - # it is, we label it as a 'function'. If it was already bound and - # that is rebound later, we assume that it will be an instance - # method and try an cope with the possibility that the 'self' - # argument it being passed as an explicit argument and shuffle - # the arguments around to extract 'self' for use as the instance. - - if isinstance(wrapped, classmethod): - binding = "classmethod" - - elif isinstance(wrapped, staticmethod): - binding = "staticmethod" - - elif hasattr(wrapped, "__self__"): - if inspect.isclass(wrapped.__self__): - binding = "classmethod" - else: - binding = "function" - - else: - binding = "function" - - super(FunctionWrapper, self).__init__(wrapped, None, wrapper, enabled, binding) - - -try: - if not os.environ.get("WRAPT_DISABLE_EXTENSIONS"): - from ._wrappers import ( - ObjectProxy, - CallableObjectProxy, - PartialCallableObjectProxy, - FunctionWrapper, - BoundFunctionWrapper, - _FunctionWrapperBase, - ) -except ImportError: - pass - -# Helper functions for applying wrappers to existing functions. - - -def resolve_path(module, name): - if isinstance(module, string_types): - __import__(module) - module = sys.modules[module] - - parent = module - - path = name.split(".") - attribute = path[0] - - # We can't just always use getattr() because in doing - # that on a class it will cause binding to occur which - # will complicate things later and cause some things not - # to work. For the case of a class we therefore access - # the __dict__ directly. To cope though with the wrong - # class being given to us, or a method being moved into - # a base class, we need to walk the class hierarchy to - # work out exactly which __dict__ the method was defined - # in, as accessing it from __dict__ will fail if it was - # not actually on the class given. Fallback to using - # getattr() if we can't find it. If it truly doesn't - # exist, then that will fail. - - def lookup_attribute(parent, attribute): - if inspect.isclass(parent): - for cls in inspect.getmro(parent): - if attribute in vars(cls): - return vars(cls)[attribute] - else: - return getattr(parent, attribute) - else: - return getattr(parent, attribute) - - original = lookup_attribute(parent, attribute) - - for attribute in path[1:]: - parent = original - original = lookup_attribute(parent, attribute) - - return (parent, attribute, original) - - -def apply_patch(parent, attribute, replacement): - setattr(parent, attribute, replacement) - - -def wrap_object(module, name, factory, args=(), kwargs={}): - (parent, attribute, original) = resolve_path(module, name) - wrapper = factory(original, *args, **kwargs) - apply_patch(parent, attribute, wrapper) - return wrapper - - -# Function for applying a proxy object to an attribute of a class -# instance. The wrapper works by defining an attribute of the same name -# on the class which is a descriptor and which intercepts access to the -# instance attribute. Note that this cannot be used on attributes which -# are themselves defined by a property object. - - -class AttributeWrapper(object): - def __init__(self, attribute, factory, args, kwargs): - self.attribute = attribute - self.factory = factory - self.args = args - self.kwargs = kwargs - - def __get__(self, instance, owner): - value = instance.__dict__[self.attribute] - return self.factory(value, *self.args, **self.kwargs) - - def __set__(self, instance, value): - instance.__dict__[self.attribute] = value - - def __delete__(self, instance): - del instance.__dict__[self.attribute] - - -def wrap_object_attribute(module, name, factory, args=(), kwargs={}): - path, attribute = name.rsplit(".", 1) - parent = resolve_path(module, path)[2] - wrapper = AttributeWrapper(attribute, factory, args, kwargs) - apply_patch(parent, attribute, wrapper) - return wrapper - - -# Functions for creating a simple decorator using a FunctionWrapper, -# plus short cut functions for applying wrappers to functions. These are -# for use when doing monkey patching. For a more featured way of -# creating decorators see the decorator decorator instead. - - -def function_wrapper(wrapper): - def _wrapper(wrapped, instance, args, kwargs): - target_wrapped = args[0] - if instance is None: - target_wrapper = wrapper - elif inspect.isclass(instance): - target_wrapper = wrapper.__get__(None, instance) - else: - target_wrapper = wrapper.__get__(instance, type(instance)) - return FunctionWrapper(target_wrapped, target_wrapper) - - return FunctionWrapper(wrapper, _wrapper) - - -def wrap_function_wrapper(module, name, wrapper): - return wrap_object(module, name, FunctionWrapper, (wrapper,)) - - -def patch_function_wrapper(module, name): - def _wrapper(wrapper): - return wrap_object(module, name, FunctionWrapper, (wrapper,)) - - return _wrapper - - -def transient_function_wrapper(module, name): - def _decorator(wrapper): - def _wrapper(wrapped, instance, args, kwargs): - target_wrapped = args[0] - if instance is None: - target_wrapper = wrapper - elif inspect.isclass(instance): - target_wrapper = wrapper.__get__(None, instance) - else: - target_wrapper = wrapper.__get__(instance, type(instance)) - - def _execute(wrapped, instance, args, kwargs): - (parent, attribute, original) = resolve_path(module, name) - replacement = FunctionWrapper(original, target_wrapper) - setattr(parent, attribute, replacement) - try: - return wrapped(*args, **kwargs) - finally: - setattr(parent, attribute, original) - - return FunctionWrapper(target_wrapped, _execute) - - return FunctionWrapper(wrapper, _wrapper) - - return _decorator - - -# A weak function proxy. This will work on instance methods, class -# methods, static methods and regular functions. Special treatment is -# needed for the method types because the bound method is effectively a -# transient object and applying a weak reference to one will immediately -# result in it being destroyed and the weakref callback called. The weak -# reference is therefore applied to the instance the method is bound to -# and the original function. The function is then rebound at the point -# of a call via the weak function proxy. - - -def _weak_function_proxy_callback(ref, proxy, callback): - if proxy._self_expired: - return - - proxy._self_expired = True - - # This could raise an exception. We let it propagate back and let - # the weakref.proxy() deal with it, at which point it generally - # prints out a short error message direct to stderr and keeps going. - - if callback is not None: - callback(proxy) - - -class WeakFunctionProxy(ObjectProxy): - - __slots__ = ("_self_expired", "_self_instance") - - def __init__(self, wrapped, callback=None): - # We need to determine if the wrapped function is actually a - # bound method. In the case of a bound method, we need to keep a - # reference to the original unbound function and the instance. - # This is necessary because if we hold a reference to the bound - # function, it will be the only reference and given it is a - # temporary object, it will almost immediately expire and - # the weakref callback triggered. So what is done is that we - # hold a reference to the instance and unbound function and - # when called bind the function to the instance once again and - # then call it. Note that we avoid using a nested function for - # the callback here so as not to cause any odd reference cycles. - - _callback = callback and functools.partial(_weak_function_proxy_callback, proxy=self, callback=callback) - - self._self_expired = False - - if isinstance(wrapped, _FunctionWrapperBase): - self._self_instance = weakref.ref(wrapped._self_instance, _callback) - - if wrapped._self_parent is not None: - super(WeakFunctionProxy, self).__init__(weakref.proxy(wrapped._self_parent, _callback)) - - else: - super(WeakFunctionProxy, self).__init__(weakref.proxy(wrapped, _callback)) - - return - - try: - self._self_instance = weakref.ref(wrapped.__self__, _callback) - - super(WeakFunctionProxy, self).__init__(weakref.proxy(wrapped.__func__, _callback)) - - except AttributeError: - self._self_instance = None - - super(WeakFunctionProxy, self).__init__(weakref.proxy(wrapped, _callback)) - - def __call__(self, *args, **kwargs): - # We perform a boolean check here on the instance and wrapped - # function as that will trigger the reference error prior to - # calling if the reference had expired. - - instance = self._self_instance and self._self_instance() - function = self.__wrapped__ and self.__wrapped__ - - # If the wrapped function was originally a bound function, for - # which we retained a reference to the instance and the unbound - # function we need to rebind the function and then call it. If - # not just called the wrapped function. - - if instance is None: - return self.__wrapped__(*args, **kwargs) - - return function.__get__(instance, type(instance))(*args, **kwargs) diff --git a/docs/contributing-integrations.rst b/docs/contributing-integrations.rst index 29989e565f2..76761b329c1 100644 --- a/docs/contributing-integrations.rst +++ b/docs/contributing-integrations.rst @@ -25,7 +25,7 @@ What tools does an integration rely on? Integrations rely primarily on Wrapt, the Pin API, and the Core API. -The `Wrapt `_ library, vendored in ``ddtrace.vendor.wrapt``, is the main +The `Wrapt `_ library is the main piece of code that ``ddtrace`` uses to hook into the runtime execution of third-party libraries. The essential task of writing an integration is determining the functions in the third-party library that would serve as useful entrypoints and wrapping them with ``wrap_function_wrapper``. There are exceptions, but this is diff --git a/pyproject.toml b/pyproject.toml index 6afb08451a6..856031d7848 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,12 +42,14 @@ dependencies = [ "ipaddress; python_version<'3.7'", "opentelemetry-api>=1; python_version>='3.7'", "pathlib2; python_version<'3.5'", + "psutil>=5.6.7", "protobuf>=3,<3.18; python_version<'3.6'", "protobuf>=3,<4.0; python_version=='3.6'", "protobuf>=3; python_version>='3.7'", "six>=1.12.0", "typing; python_version<'3.5'", "typing_extensions", + "wrapt>=1.14.1", "xmltodict>=0.12", ] diff --git a/setup.cfg b/setup.cfg index af844537694..d841e06afb0 100644 --- a/setup.cfg +++ b/setup.cfg @@ -2,7 +2,7 @@ universal=1 [codespell] -skip = *.json,*.h,*.cpp,*.c,.riot,.tox,.mypy_cache,.git,*ddtrace/vendor,tests/contrib/openai/cassettes/*,tests/contrib/langchain/cassettes/*,ddtrace/appsec/_iast/_taint_tracking/_vendor/* +skip = *.json,*.h,*.cpp,*.c,.riot,.tox,.mypy_cache,.git,ddtrace/vendor/*,tests/contrib/openai/cassettes/*,tests/contrib/langchain/cassettes/*,ddtrace/appsec/_iast/_taint_tracking/_vendor/* exclude-file = .codespellignorelines ignore-words-list = asend,dne,fo,medias,ment,nin,ot,setttings,statics,ba,spawnve,doas diff --git a/setup.py b/setup.py index 13b09c87f91..868d98fda39 100644 --- a/setup.py +++ b/setup.py @@ -547,6 +547,8 @@ def get_ddup_ext(): "xmltodict>=0.12", "envier", "opentelemetry-api>=1; python_version>='3.7'", + "psutil==5.6.7", + "wrapt==14.1.0", ] + bytecode, extras_require={ @@ -645,7 +647,5 @@ def get_ddup_ext(): force=True, annotate=os.getenv("_DD_CYTHON_ANNOTATE") == "1", ) - + get_exts_for("wrapt") - + get_exts_for("psutil") + get_ddup_ext(), ) diff --git a/tests/appsec/iast/test_iast_mem_check.py b/tests/appsec/iast/test_iast_mem_check.py index fbc24489035..d27dfcf203f 100644 --- a/tests/appsec/iast/test_iast_mem_check.py +++ b/tests/appsec/iast/test_iast_mem_check.py @@ -30,6 +30,8 @@ ], ) def test_propagation_path_2_origins_3_propagation(origin1, origin2, iast_span_defaults): + import psutil + from ddtrace.appsec._iast._taint_tracking import OriginType from ddtrace.appsec._iast._taint_tracking import active_map_addreses_size from ddtrace.appsec._iast._taint_tracking import create_context @@ -37,7 +39,6 @@ def test_propagation_path_2_origins_3_propagation(origin1, origin2, iast_span_de from ddtrace.appsec._iast._taint_tracking import num_objects_tainted from ddtrace.appsec._iast._taint_tracking import reset_context from ddtrace.appsec._iast._taint_tracking import taint_pyobject - from ddtrace.vendor import psutil start_memory = psutil.Process(os.getpid()).memory_info().rss diff --git a/tests/appsec/test_remoteconfiguration_e2e.py b/tests/appsec/test_remoteconfiguration_e2e.py index 4b9b47915fc..b28b8c58967 100644 --- a/tests/appsec/test_remoteconfiguration_e2e.py +++ b/tests/appsec/test_remoteconfiguration_e2e.py @@ -11,13 +11,13 @@ import time import uuid +import psutil import pytest from ddtrace import tracer from ddtrace.internal.compat import httplib from ddtrace.internal.compat import parse from ddtrace.internal.utils.retry import RetryError -from ddtrace.vendor import psutil from tests.webclient import Client diff --git a/tests/contrib/aioredis/test_aioredis.py b/tests/contrib/aioredis/test_aioredis.py index 216be33ef07..87ab9be5660 100644 --- a/tests/contrib/aioredis/test_aioredis.py +++ b/tests/contrib/aioredis/test_aioredis.py @@ -3,13 +3,13 @@ import aioredis import pytest +from wrapt import ObjectProxy from ddtrace import Pin from ddtrace import tracer from ddtrace.contrib.aioredis.patch import aioredis_version from ddtrace.contrib.aioredis.patch import patch from ddtrace.contrib.aioredis.patch import unpatch -from ddtrace.vendor.wrapt import ObjectProxy from tests.utils import override_config from ..config import REDIS_CONFIG diff --git a/tests/contrib/aredis/test_aredis.py b/tests/contrib/aredis/test_aredis.py index 6317e32ea34..9c21d30f649 100644 --- a/tests/contrib/aredis/test_aredis.py +++ b/tests/contrib/aredis/test_aredis.py @@ -3,12 +3,12 @@ import aredis import pytest +from wrapt import ObjectProxy from ddtrace import Pin from ddtrace.contrib.aredis.patch import patch from ddtrace.contrib.aredis.patch import unpatch from ddtrace.internal.schema.span_attribute_schema import _DEFAULT_SPAN_SERVICE_NAMES -from ddtrace.vendor.wrapt import ObjectProxy from tests.opentracer.utils import init_tracer from tests.utils import override_config diff --git a/tests/contrib/asyncio/test_patch.py b/tests/contrib/asyncio/test_patch.py index b2acfc4a041..3ea32621164 100644 --- a/tests/contrib/asyncio/test_patch.py +++ b/tests/contrib/asyncio/test_patch.py @@ -2,10 +2,10 @@ import sys import pytest +import wrapt from ddtrace.contrib.asyncio.patch import patch from ddtrace.contrib.asyncio.patch import unpatch -from ddtrace.vendor import wrapt from .utils import AsyncioTestCase diff --git a/tests/contrib/asynctest/test_asynctest.py b/tests/contrib/asynctest/test_asynctest.py index b919dcfbfe4..046cf430b45 100644 --- a/tests/contrib/asynctest/test_asynctest.py +++ b/tests/contrib/asynctest/test_asynctest.py @@ -42,7 +42,7 @@ def pytest_configure(config): "attribute 'coroutine'", ) def test_asynctest_not_raise_attribute_error_exception(self): - """Test AttributeError exception in `ddtrace/vendor/wrapt/wrappers.py` when try to import asynctest package. + """Test AttributeError exception in `wrapt/wrappers.py` when try to import asynctest package. Issue: https://github.com/DataDog/dd-trace-py/issues/4484 """ py_file = self.testdir.makepyfile( diff --git a/tests/contrib/consul/test.py b/tests/contrib/consul/test.py index 98c5cc781d1..a1af811b92d 100644 --- a/tests/contrib/consul/test.py +++ b/tests/contrib/consul/test.py @@ -1,4 +1,5 @@ import consul +from wrapt import BoundFunctionWrapper from ddtrace import Pin from ddtrace.constants import ANALYTICS_SAMPLE_RATE_KEY @@ -6,7 +7,6 @@ from ddtrace.contrib.consul.patch import unpatch from ddtrace.ext import consul as consulx from ddtrace.internal.schema import DEFAULT_SPAN_SERVICE_NAME -from ddtrace.vendor.wrapt import BoundFunctionWrapper from tests.utils import TracerTestCase from tests.utils import assert_is_measured diff --git a/tests/contrib/django/test_django.py b/tests/contrib/django/test_django.py index 5368bb8929d..d3ce3fc9acd 100644 --- a/tests/contrib/django/test_django.py +++ b/tests/contrib/django/test_django.py @@ -15,6 +15,7 @@ import mock import pytest from six import ensure_text +import wrapt from ddtrace import config from ddtrace.constants import ANALYTICS_SAMPLE_RATE_KEY @@ -37,7 +38,6 @@ from ddtrace.propagation.http import HTTP_HEADER_PARENT_ID from ddtrace.propagation.http import HTTP_HEADER_SAMPLING_PRIORITY from ddtrace.propagation.http import HTTP_HEADER_TRACE_ID -from ddtrace.vendor import wrapt from tests.opentracer.utils import init_tracer from tests.utils import assert_dict_issuperset from tests.utils import override_config diff --git a/tests/contrib/flask/__init__.py b/tests/contrib/flask/__init__.py index 0fc1971dea7..bbec059ec0f 100644 --- a/tests/contrib/flask/__init__.py +++ b/tests/contrib/flask/__init__.py @@ -1,10 +1,10 @@ import flask from flask.testing import FlaskClient +import wrapt from ddtrace import Pin from ddtrace.contrib.flask import patch from ddtrace.contrib.flask import unpatch -from ddtrace.vendor import wrapt from tests.utils import TracerTestCase diff --git a/tests/contrib/flask/test_idempotency.py b/tests/contrib/flask/test_idempotency.py index 5782ffb5749..5c87f060277 100644 --- a/tests/contrib/flask/test_idempotency.py +++ b/tests/contrib/flask/test_idempotency.py @@ -2,12 +2,12 @@ import flask import mock +import wrapt from ddtrace.contrib.flask import patch from ddtrace.contrib.flask import unpatch from ddtrace.contrib.flask.patch import _u from ddtrace.contrib.flask.patch import _w -from ddtrace.vendor import wrapt class FlaskIdempotencyTestCase(unittest.TestCase): diff --git a/tests/contrib/flask_autopatch/test_flask_autopatch.py b/tests/contrib/flask_autopatch/test_flask_autopatch.py index 89a8752ec17..3da871f27f4 100644 --- a/tests/contrib/flask_autopatch/test_flask_autopatch.py +++ b/tests/contrib/flask_autopatch/test_flask_autopatch.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- import flask +import wrapt from ddtrace import Pin from ddtrace.contrib.flask.patch import flask_version from ddtrace.ext import http -from ddtrace.vendor import wrapt from tests.utils import TracerTestCase from tests.utils import assert_is_measured from tests.utils import assert_span_http_status_code diff --git a/tests/contrib/httplib/test_httplib.py b/tests/contrib/httplib/test_httplib.py index 73943165371..2fb373dc444 100644 --- a/tests/contrib/httplib/test_httplib.py +++ b/tests/contrib/httplib/test_httplib.py @@ -3,6 +3,7 @@ import sys import pytest +import wrapt from ddtrace import config from ddtrace.constants import ANALYTICS_SAMPLE_RATE_KEY @@ -16,7 +17,6 @@ from ddtrace.internal.constants import _HTTPLIB_NO_TRACE_REQUEST from ddtrace.internal.schema import DEFAULT_SPAN_SERVICE_NAME from ddtrace.pin import Pin -from ddtrace.vendor import wrapt from tests.opentracer.utils import init_tracer from tests.utils import TracerTestCase from tests.utils import assert_span_http_status_code diff --git a/tests/contrib/httplib/test_httplib_distributed.py b/tests/contrib/httplib/test_httplib_distributed.py index 3475a8e796f..4616f84ce8b 100644 --- a/tests/contrib/httplib/test_httplib_distributed.py +++ b/tests/contrib/httplib/test_httplib_distributed.py @@ -1,11 +1,12 @@ # Standard library import contextlib +import wrapt + # Project from ddtrace import config from ddtrace.internal.compat import httplib from ddtrace.pin import Pin -from ddtrace.vendor import wrapt from tests.utils import TracerTestCase from .test_httplib import HTTPLibBaseMixin diff --git a/tests/contrib/httpx/test_httpx.py b/tests/contrib/httpx/test_httpx.py index 010e6fb7a3c..0857cae3f58 100644 --- a/tests/contrib/httpx/test_httpx.py +++ b/tests/contrib/httpx/test_httpx.py @@ -1,6 +1,7 @@ import httpx import pytest import six +from wrapt import ObjectProxy from ddtrace import config from ddtrace.contrib.httpx.patch import HTTPX_VERSION @@ -8,7 +9,6 @@ from ddtrace.contrib.httpx.patch import unpatch from ddtrace.pin import Pin from ddtrace.settings.http import HttpConfig -from ddtrace.vendor.wrapt import ObjectProxy from tests.utils import override_config from tests.utils import override_http_config diff --git a/tests/contrib/httpx/test_httpx_pre_0_11.py b/tests/contrib/httpx/test_httpx_pre_0_11.py index 3be81d81194..7bd00e4fe95 100644 --- a/tests/contrib/httpx/test_httpx_pre_0_11.py +++ b/tests/contrib/httpx/test_httpx_pre_0_11.py @@ -1,6 +1,7 @@ import httpx import pytest import six +from wrapt import ObjectProxy from ddtrace import config from ddtrace.contrib.httpx.patch import HTTPX_VERSION @@ -8,7 +9,6 @@ from ddtrace.contrib.httpx.patch import unpatch from ddtrace.pin import Pin from ddtrace.settings.http import HttpConfig -from ddtrace.vendor.wrapt import ObjectProxy from tests.utils import override_config from tests.utils import override_http_config diff --git a/tests/contrib/logging/test_logging.py b/tests/contrib/logging/test_logging.py index d1192cf94af..dc029e6fd5a 100644 --- a/tests/contrib/logging/test_logging.py +++ b/tests/contrib/logging/test_logging.py @@ -2,6 +2,7 @@ import pytest import six +import wrapt import ddtrace from ddtrace.constants import ENV_KEY @@ -12,7 +13,6 @@ from ddtrace.contrib.logging.patch import RECORD_ATTR_TRACE_ID from ddtrace.internal.compat import StringIO from ddtrace.internal.constants import MAX_UINT_64BITS -from ddtrace.vendor import wrapt from tests.utils import TracerTestCase diff --git a/tests/contrib/patch.py b/tests/contrib/patch.py index 19b38a17e13..62923223e88 100644 --- a/tests/contrib/patch.py +++ b/tests/contrib/patch.py @@ -6,7 +6,8 @@ from textwrap import dedent import unittest -from ddtrace.vendor import wrapt +import wrapt + from tests.subprocesstest import SubprocessTestCase from tests.subprocesstest import run_in_subprocess from tests.utils import call_program @@ -695,7 +696,7 @@ def test_ddtrace_run_patch_on_import(self): """ import sys - from ddtrace.vendor.wrapt import wrap_function_wrapper as wrap + from wrapt import wrap_function_wrapper as wrap patched = False diff --git a/tests/contrib/psycopg/test_psycopg_snapshot.py b/tests/contrib/psycopg/test_psycopg_snapshot.py index 2023f97afdc..86571b48abc 100644 --- a/tests/contrib/psycopg/test_psycopg_snapshot.py +++ b/tests/contrib/psycopg/test_psycopg_snapshot.py @@ -3,10 +3,10 @@ import psycopg import pytest +import wrapt from ddtrace.contrib.psycopg.patch import patch from ddtrace.contrib.psycopg.patch import unpatch -from ddtrace.vendor import wrapt from tests.contrib.config import POSTGRES_CONFIG from tests.utils import override_config diff --git a/tests/contrib/psycopg2/test_psycopg_snapshot.py b/tests/contrib/psycopg2/test_psycopg_snapshot.py index 27e98d944d6..c2e63464c2a 100644 --- a/tests/contrib/psycopg2/test_psycopg_snapshot.py +++ b/tests/contrib/psycopg2/test_psycopg_snapshot.py @@ -2,10 +2,10 @@ import psycopg2 import pytest +import wrapt from ddtrace.contrib.psycopg.patch import patch from ddtrace.contrib.psycopg.patch import unpatch -from ddtrace.vendor import wrapt from tests.contrib.config import POSTGRES_CONFIG from tests.utils import override_config diff --git a/tests/contrib/pymemcache/autopatch/test.py b/tests/contrib/pymemcache/autopatch/test.py index c494dda549e..2c4a4ed20ef 100644 --- a/tests/contrib/pymemcache/autopatch/test.py +++ b/tests/contrib/pymemcache/autopatch/test.py @@ -2,8 +2,7 @@ import pymemcache from pymemcache.client import hash as pymemcache_hash - -from ddtrace.vendor import wrapt +import wrapt class AutoPatchTestCase(unittest.TestCase): diff --git a/tests/contrib/pymemcache/test_client.py b/tests/contrib/pymemcache/test_client.py index 19940834e57..657fce2b2a6 100644 --- a/tests/contrib/pymemcache/test_client.py +++ b/tests/contrib/pymemcache/test_client.py @@ -7,6 +7,7 @@ from pymemcache.exceptions import MemcacheUnknownCommandError from pymemcache.exceptions import MemcacheUnknownError import pytest +import wrapt # project from ddtrace import Pin @@ -14,7 +15,6 @@ from ddtrace.contrib.pymemcache.patch import patch from ddtrace.contrib.pymemcache.patch import unpatch from ddtrace.internal.schema import DEFAULT_SPAN_SERVICE_NAME -from ddtrace.vendor import wrapt from tests.utils import DummyTracer from tests.utils import TracerTestCase diff --git a/tests/contrib/redis/test_redis_asyncio.py b/tests/contrib/redis/test_redis_asyncio.py index 8a8999787c9..026ad26ff04 100644 --- a/tests/contrib/redis/test_redis_asyncio.py +++ b/tests/contrib/redis/test_redis_asyncio.py @@ -3,12 +3,12 @@ import pytest import redis import redis.asyncio +from wrapt import ObjectProxy from ddtrace import Pin from ddtrace import tracer from ddtrace.contrib.redis.patch import patch from ddtrace.contrib.redis.patch import unpatch -from ddtrace.vendor.wrapt import ObjectProxy from tests.utils import override_config from ..config import REDIS_CONFIG diff --git a/tests/contrib/tornado/test_executor_decorator.py b/tests/contrib/tornado/test_executor_decorator.py index 94970b239e9..3e0eb1d952e 100644 --- a/tests/contrib/tornado/test_executor_decorator.py +++ b/tests/contrib/tornado/test_executor_decorator.py @@ -188,7 +188,7 @@ def test_futures_double_instrumentation(self): patch(futures=True) from concurrent.futures import ThreadPoolExecutor - from ddtrace.vendor.wrapt import BoundFunctionWrapper + from wrapt import BoundFunctionWrapper fn_wrapper = getattr(ThreadPoolExecutor.submit, "__wrapped__", None) assert not isinstance(fn_wrapper, BoundFunctionWrapper) diff --git a/tests/contrib/vertica/test_vertica.py b/tests/contrib/vertica/test_vertica.py index 6d102ebf7ad..605050cdd60 100644 --- a/tests/contrib/vertica/test_vertica.py +++ b/tests/contrib/vertica/test_vertica.py @@ -1,4 +1,5 @@ import pytest +import wrapt import ddtrace from ddtrace import Pin @@ -11,7 +12,6 @@ from ddtrace.contrib.vertica.patch import unpatch from ddtrace.internal.schema import DEFAULT_SPAN_SERVICE_NAME from ddtrace.settings.config import _deepmerge -from ddtrace.vendor import wrapt from tests.contrib.config import VERTICA_CONFIG from tests.opentracer.utils import init_tracer from tests.utils import DummyTracer diff --git a/tests/contrib/yaaredis/test_yaaredis.py b/tests/contrib/yaaredis/test_yaaredis.py index 88b897cbb05..a1195161de8 100644 --- a/tests/contrib/yaaredis/test_yaaredis.py +++ b/tests/contrib/yaaredis/test_yaaredis.py @@ -3,12 +3,12 @@ import uuid import pytest +from wrapt import ObjectProxy import yaaredis from ddtrace import Pin from ddtrace.contrib.yaaredis.patch import patch from ddtrace.contrib.yaaredis.patch import unpatch -from ddtrace.vendor.wrapt import ObjectProxy from tests.opentracer.utils import init_tracer from tests.utils import override_config diff --git a/tests/debugging/function/test_discovery.py b/tests/debugging/function/test_discovery.py index 22822216ad5..232516c1202 100644 --- a/tests/debugging/function/test_discovery.py +++ b/tests/debugging/function/test_discovery.py @@ -111,7 +111,7 @@ def test_function_mangled(stuff_discovery): def test_discovery_after_external_wrapping(stuff): - import ddtrace.vendor.wrapt as wrapt + import wrapt as wrapt def wrapper(wrapped, inst, args, kwargs): pass diff --git a/tests/debugging/test_debugger.py b/tests/debugging/test_debugger.py index ab1e3890345..e3a382062d9 100644 --- a/tests/debugging/test_debugger.py +++ b/tests/debugging/test_debugger.py @@ -513,7 +513,7 @@ def test_debugger_multiple_function_probes_on_same_function(): # DEV: The following tests are to ensure compatibility with the tracer -import ddtrace.vendor.wrapt as wrapt # noqa +import wrapt as wrapt # noqa def wrapper(wrapped, instance, args, kwargs): diff --git a/tests/tracer/runtime/test_metric_collectors.py b/tests/tracer/runtime/test_metric_collectors.py index a0d88f74587..ee8eea458ed 100644 --- a/tests/tracer/runtime/test_metric_collectors.py +++ b/tests/tracer/runtime/test_metric_collectors.py @@ -36,7 +36,7 @@ def test_static_metrics(self): import threading import time - from ddtrace.vendor import psutil + import psutil # Something to bump CPU utilization def busy_wait(duration_ms): diff --git a/tests/utils.py b/tests/utils.py index 6b346d5f284..e0b2783ab29 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -11,6 +11,7 @@ import attr import pkg_resources import pytest +import wrapt import ddtrace from ddtrace import Span @@ -29,7 +30,6 @@ from ddtrace.internal.schema import SCHEMA_VERSION from ddtrace.internal.utils.formats import parse_tags_str from ddtrace.internal.writer import AgentWriter -from ddtrace.vendor import wrapt from tests.subprocesstest import SubprocessTestCase