Skip to main content

Analysis of the stack of remote python processes

Project description


OS Linux PyPI - Python Version PyPI - Implementation PyPI PyPI - Downloads Tests Code Style

PyStack

Print the stack trace of a running Python process, or of a Python core dump.

PyStack is a tool that uses forbidden magic to let you inspect the stack frames of a running Python process or a Python core dump, helping you quickly and easily learn what it's doing (or what it was doing when it crashed) without having to interpret nasty CPython internals.

What PyStack can do

PyStack has the following amazing features:

  • 💻 Works with both running processes and core dump files.
  • 🧵 Shows if each thread currently holds the Python GIL, is waiting to acquire it, or is currently dropping it.
  • 🗑️ Shows if a thread is running a garbage collection cycle.
  • 🐍 Optionally shows native function calls, as well as Python ones. In this mode, PyStack prints the native stack trace (C/C++/Rust function calls), except that the calls to Python callables are replaced with frames showing the Python code being executed, instead of showing the internal C code the interpreter used to make the call.
  • 🔍 Automatically demangles symbols shown in the native stack.
  • 📈 Includes calls to inlined functions in the native stack whenever enough debug information is available.
  • 🔍 Optionally shows the values of local variables and function arguments in Python stack frames.
  • 🔒 Safe to use on running processes. PyStack does not modify any memory or execute any code in a process that is running. It simply attaches just long enough to read some of the process's memory.
  • ⚡ Optionally, it can perform a Python stack analysis without pausing the process at all. This minimizes impact to the debugged process, at the cost of potentially failing due to data races.
  • 🚀 Super fast! It can analyze core files 10x faster than general-purpose tools like GDB.
  • 🎯 Even works with aggressively optimized Python interpreter binaries.
  • 🔍 Even works with Python interpreters' binaries that do not have symbols or debug information (Python stack only).
  • 💥 Tolerates memory corruption well. Even if the process crashed due to memory corruption, PyStack can usually reconstruct the stack.
  • 💼 Self-contained: it does not depend on external tools or programs other than the Python interpreter used to run PyStack itself.

Building from source

If you wish to build PyStack from source, you need the following binary dependencies in your system:

  • libdw
  • libelf

Note that sometimes both libraries are provided together as part of a distribution's elfutils package.

Check your package manager on how to install these dependencies (e.g., apt-get install libdw-dev libelf-dev in Debian-based systems). Note that you may need to tell the compiler where to find the header and library files of the dependencies for the build to succeed. Check your distribution's documentation to determine the location of the header and library files or for more detailed information.

Once you have these binary dependencies installed, you can clone the repository and follow the typical build process for Python libraries:

git clone git@github.com:bloomberg/pystack.git pystack
cd pystack
python3 -m venv ../pystack-env/  # just an example, put this wherever you want
source ../pystack-env/bin/activate
python3 -m pip install --upgrade pip
python3 -m pip install -e .
python3 -m pip install -r requirements-test.txt -r requirements-extra.txt

This will install PyStack in the virtual environment in development mode (the -e of the last pip install command), and then install the Python libraries needed to test it, lint it, and generate its documentation.

Documentation

You can find the full documentation here.

Usage

PyStack uses distinct subcommands for analyzing running processes and core dump files.

usage: pystack [-h] [-v] [--no-color] {remote,core} ...

Get Python stack trace of a remote process

options:
  -h, --help     show this help message and exit
  -v, --verbose
  --no-color     Deactivate colored output

commands:
  {remote,core}  What should be analyzed by PyStack (use <command> --help for a command-specific help section).
    remote       Analyze a remote process given its PID
    core         Analyze a core dump file given its location and the executable

Analyzing running processes

The remote command is used to analyze the status of a running (remote) process. The analysis is always done in a safe and non-intrusive way, as no code is loaded in the memory space of the process under analysis and no memory is modified in the remote process. This makes analysis using PyStack a great option even for those services and applications that are running in environments where the running process must not be impacted in any way (other than being temporarily paused, though --no-block can avoid even that). There are several options available:

usage: pystack remote [-h] [-v] [--no-color] [--no-block] [--native] [--native-all] [--locals] [--exhaustive] [--self] pid

positional arguments:
  pid            The PID of the remote process

options:
  -h, --help     show this help message and exit
  -v, --verbose
  --no-color     Deactivate colored output
  --no-block     do not block the process when inspecting its memory
  --native       Include the native (C) frames in the resulting stack trace
  --native-all   Include native (C) frames from threads not registered with the interpreter (implies --native)
  --locals       Show local variables for each frame in the stack trace
  --exhaustive   Use all possible methods to obtain the Python stack info (may be slow)

To use PyStack, you just need to provide the PID of the process:

$ pystack remote 112
Traceback for thread 112 [] (most recent call last):
    (Python) File "/test.py", line 17, in <module>
        first_func()
    (Python) File "/test.py", line 6, in first_func
        second_func()
    (Python) File "/test.py", line 10, in second_func
        third_func()
    (Python) File "/test.py", line 14, in third_func
        time.sleep(1000)

Analyzing core dumps

The core subcommand is used to analyze the status of a core dump file. Analyzing core files is very similar to analyzing processes but there are some differences, as the core file does not contain the totality of the memory that was valid when the program was live. In most cases, this makes no difference, as PyStack will try to adapt automatically. However, in some cases, you will need to specify extra command line options to help PyStack locate the information it needs. When analyzing cores, there are several options available:

usage: pystack core [-h] [-v] [--no-color] [--native] [--native-all] [--locals] [--exhaustive] [--lib-search-path LIB_SEARCH_PATH | --lib-search-root LIB_SEARCH_ROOT] core [executable]

positional arguments:
  core                  The path to the core file
  executable            (Optional) The path to the executable of the core file

options:
  -h, --help            show this help message and exit
  -v, --verbose
  --no-color            Deactivate colored output
  --native              Include the native (C) frames in the resulting stack trace
  --native-all          Include native (C) frames from threads not registered with the interpreter (implies --native)
  --locals              Show local variables for each frame in the stack trace
  --exhaustive          Use all possible methods to obtain the Python stack info (may be slow)
  --lib-search-path LIB_SEARCH_PATH
                        List of paths to search for shared libraries loaded in the core. Paths must be separated by the ':' character
  --lib-search-root LIB_SEARCH_ROOT
                        Root directory to search recursively for shared libraries loaded into the core.

In most cases, you just need to provide the location of the core to use PyStack with core dump files:

$ pystack core ./the_core_file
Using executable found in the core file: /usr/bin/python3.8

Core file information:
state: t zombie: True niceness: 0
pid: 570 ppid: 1 sid: 1
uid: 0 gid: 0 pgrp: 570
executable: python3.8 arguments: python3.8

The process died due receiving signal SIGSTOP
Traceback for thread 570 [] (most recent call last):
    (Python) File "/test.py", line 19, in <module>
        first_func({1: None}, [1,2,3])
    (Python) File "/test.py", line 7, in first_func
        second_func(x, y)
    (Python) File "/test.py", line 12, in second_func
        third_func(x, y)
    (Python) File "/test.py", line 16, in third_func
        time.sleep(1000)

License

PyStack is Apache-2.0 licensed, as found in the LICENSE file.

Code of Conduct

This project has adopted a Code of Conduct. If you have any concerns about the Code, or behavior that you have experienced in the project, please contact us at opensource@bloomberg.net.

Security Policy

If you believe you have identified a security vulnerability in this project, please send an email to the project team at opensource@bloomberg.net, detailing the suspected issue and any methods you've found to reproduce it.

Please do NOT open an issue in the GitHub repository, as we'd prefer to keep vulnerability reports private until we've had an opportunity to review and address them.

Contributing

We welcome your contributions to help us improve and extend this project!

Below you will find some basic steps required to be able to contribute to the project. If you have any questions about this process or any other aspect of contributing to a Bloomberg open source project, feel free to send an email to opensource@bloomberg.net and we'll get your questions answered as quickly as we can.

Contribution Licensing

Since this project is distributed under the terms of an open source license, contributions that you make are licensed under the same terms. For us to be able to accept your contributions, we will need explicit confirmation from you that you are able and willing to provide them under these terms, and the mechanism we use to do this is called a Developer's Certificate of Origin (DCO). This is similar to the process used by the Linux(R) kernel, Samba, and many other major open source projects.

To participate under these terms, all that you must do is include a line like the following as the last line of the commit message for each commit in your contribution:

Signed-Off-By: Random J. Developer <random@developer.example.org>

The simplest way to accomplish this is to add -s or --signoff to your git commit command.

You must use your real name (sorry, no pseudonyms, and no anonymous contributions).

Steps

  • Create an Issue, select 'Feature Request', and explain the proposed change.
  • Follow the guidelines in the issue template presented to you.
  • Submit the Issue.
  • Submit a Pull Request and link it to the Issue by including "#" in the Pull Request summary.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pystack-1.0.1.tar.gz (82.9 kB view details)

Uploaded Source

Built Distributions

pystack-1.0.1-cp311-cp311-musllinux_1_1_x86_64.whl (5.6 MB view details)

Uploaded CPython 3.11 musllinux: musl 1.1+ x86-64

pystack-1.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.5 MB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ x86-64

pystack-1.0.1-cp310-cp310-musllinux_1_1_x86_64.whl (5.6 MB view details)

Uploaded CPython 3.10 musllinux: musl 1.1+ x86-64

pystack-1.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.4 MB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ x86-64

pystack-1.0.1-cp39-cp39-musllinux_1_1_x86_64.whl (5.6 MB view details)

Uploaded CPython 3.9 musllinux: musl 1.1+ x86-64

pystack-1.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.5 MB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ x86-64

pystack-1.0.1-cp38-cp38-musllinux_1_1_x86_64.whl (5.7 MB view details)

Uploaded CPython 3.8 musllinux: musl 1.1+ x86-64

pystack-1.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.5 MB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ x86-64

pystack-1.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl (5.5 MB view details)

Uploaded CPython 3.7m musllinux: musl 1.1+ x86-64

pystack-1.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.4 MB view details)

Uploaded CPython 3.7m manylinux: glibc 2.17+ x86-64

File details

Details for the file pystack-1.0.1.tar.gz.

File metadata

  • Download URL: pystack-1.0.1.tar.gz
  • Upload date:
  • Size: 82.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.11.3

File hashes

Hashes for pystack-1.0.1.tar.gz
Algorithm Hash digest
SHA256 6b7362d4a2688270511a1f0868fddcc02f0db20950ecdb2c990bff777e5737a5
MD5 f1a4bd63f5dac5e27d64e5d950706ee7
BLAKE2b-256 4bb3462244c5105678aa3106a950026ce99f1cbbf8a9e6c18d9e2679614b73a2

See more details on using hashes here.

File details

Details for the file pystack-1.0.1-cp311-cp311-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for pystack-1.0.1-cp311-cp311-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 ce09c6ae1475921ed4da1118020e274b707d4e39e41046c7283bf45090527c74
MD5 e7bdde4706bf2a4f0248c6396745c166
BLAKE2b-256 1cb479db33217bd173c9d1d90d3a7c729b262cf04f03264e52f4faa2c51b6d90

See more details on using hashes here.

File details

Details for the file pystack-1.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pystack-1.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 3ccda476f1902021a1bb1d2f10ed707e71758614c0b03d213ca0bc180a64eb72
MD5 31785ef58d8b0685c2304f31ddede274
BLAKE2b-256 a0fe9d75d86609fecf0e93c8a703bb314d9ddecbe8a38aab28a29c0d39a3f513

See more details on using hashes here.

File details

Details for the file pystack-1.0.1-cp310-cp310-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for pystack-1.0.1-cp310-cp310-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 26de0f27080745c7d68fad540ef6019edcf465c58ec3beebcdd065ca9c49d770
MD5 dc2bad697a1932cbfe83eaf0d58b1c57
BLAKE2b-256 a831688dd02f58dc6684873465f1911140c46e5f7009b979f9d52ce7e4101dbe

See more details on using hashes here.

File details

Details for the file pystack-1.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pystack-1.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 3b8a5cec973953b996ec5cc32e56a22be1442c5f50606817dd43aa74ea12d440
MD5 a701712837d4569d0c3147c78832525c
BLAKE2b-256 23d6618f3cab0297c9b5319a02f0c8c5cba9e9d278a37eaaf08cb15f75f6351e

See more details on using hashes here.

File details

Details for the file pystack-1.0.1-cp39-cp39-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for pystack-1.0.1-cp39-cp39-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 ebde1c8c8b732b3a4452469e760f9451067eec254ffb9f07404ed8af9f930024
MD5 71f6b1f76be8f5108b84854e2a63263b
BLAKE2b-256 a0bf71d96dcc4db17f69d60116cfe14308576855dfcc611edbbb5764a7a9e0ab

See more details on using hashes here.

File details

Details for the file pystack-1.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pystack-1.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 6cf9e0709f561905369eb93b5fb932712f29fc74bc9beb915a6cfc8c736f9008
MD5 f9f2c9d273df71c170e65956c690e4a1
BLAKE2b-256 e2fa47894031d6eafc863da6b371b7b887be0b561523fd26a2fdc67b7188a010

See more details on using hashes here.

File details

Details for the file pystack-1.0.1-cp38-cp38-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for pystack-1.0.1-cp38-cp38-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 f9e2dc72b813b215af4414940bef39202da52a6ff3d2cf1593c064cf453e195b
MD5 f79014fda1e9f2633a70cc4893327b8f
BLAKE2b-256 62c50ae3341f80eaf2845c88151b1d839356082a64fe4df90b7558160052de92

See more details on using hashes here.

File details

Details for the file pystack-1.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pystack-1.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 390a64003952c4241d1766bee0408a081fe819248d3831597bdbdcd0e1acf389
MD5 605cdcb5baeff15ea24f1b5fe9ea8e2d
BLAKE2b-256 110af72736b2d7156e3f2e271cc1164364c82c839f2a7495957afadc8ef1a76b

See more details on using hashes here.

File details

Details for the file pystack-1.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for pystack-1.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 df84285abb3f5dfc25178cc81644a0254384cbf8a4f95f75127b67d5d2d3cb6a
MD5 7349ab2237476ec3f09b4b5e5897425e
BLAKE2b-256 9005bf674fcfd208253bdeef141dda1c0a964a5e9e9bf1896de6495338ac9007

See more details on using hashes here.

File details

Details for the file pystack-1.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pystack-1.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 63806b2070da527ec795b15b31d85b9dc32c1b72f75e0a25d77baa434daeeadd
MD5 01936fcf772d44845e517cac80f8c919
BLAKE2b-256 b18d64875251e58e2398b7000279fd646e4a8f8c68f4a9a217b479a7f679db81

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page