sf-veritas 0.11.10__cp314-cp314-manylinux_2_28_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sf_veritas/__init__.py +46 -0
- sf_veritas/_auto_preload.py +73 -0
- sf_veritas/_sfconfig.c +162 -0
- sf_veritas/_sfconfig.cpython-314-x86_64-linux-gnu.so +0 -0
- sf_veritas/_sfcrashhandler.c +267 -0
- sf_veritas/_sfcrashhandler.cpython-314-x86_64-linux-gnu.so +0 -0
- sf_veritas/_sffastlog.c +953 -0
- sf_veritas/_sffastlog.cpython-314-x86_64-linux-gnu.so +0 -0
- sf_veritas/_sffastnet.c +994 -0
- sf_veritas/_sffastnet.cpython-314-x86_64-linux-gnu.so +0 -0
- sf_veritas/_sffastnetworkrequest.c +727 -0
- sf_veritas/_sffastnetworkrequest.cpython-314-x86_64-linux-gnu.so +0 -0
- sf_veritas/_sffuncspan.c +2791 -0
- sf_veritas/_sffuncspan.cpython-314-x86_64-linux-gnu.so +0 -0
- sf_veritas/_sffuncspan_config.c +730 -0
- sf_veritas/_sffuncspan_config.cpython-314-x86_64-linux-gnu.so +0 -0
- sf_veritas/_sfheadercheck.c +341 -0
- sf_veritas/_sfheadercheck.cpython-314-x86_64-linux-gnu.so +0 -0
- sf_veritas/_sfnetworkhop.c +1454 -0
- sf_veritas/_sfnetworkhop.cpython-314-x86_64-linux-gnu.so +0 -0
- sf_veritas/_sfservice.c +1223 -0
- sf_veritas/_sfservice.cpython-314-x86_64-linux-gnu.so +0 -0
- sf_veritas/_sfteepreload.c +6227 -0
- sf_veritas/app_config.py +57 -0
- sf_veritas/cli.py +336 -0
- sf_veritas/constants.py +10 -0
- sf_veritas/custom_excepthook.py +304 -0
- sf_veritas/custom_log_handler.py +146 -0
- sf_veritas/custom_output_wrapper.py +153 -0
- sf_veritas/custom_print.py +153 -0
- sf_veritas/django_app.py +5 -0
- sf_veritas/env_vars.py +186 -0
- sf_veritas/exception_handling_middleware.py +18 -0
- sf_veritas/exception_metaclass.py +69 -0
- sf_veritas/fast_frame_info.py +116 -0
- sf_veritas/fast_network_hop.py +293 -0
- sf_veritas/frame_tools.py +112 -0
- sf_veritas/funcspan_config_loader.py +693 -0
- sf_veritas/function_span_profiler.py +1313 -0
- sf_veritas/get_preload_path.py +34 -0
- sf_veritas/import_hook.py +62 -0
- sf_veritas/infra_details/__init__.py +3 -0
- sf_veritas/infra_details/get_infra_details.py +24 -0
- sf_veritas/infra_details/kubernetes/__init__.py +3 -0
- sf_veritas/infra_details/kubernetes/get_cluster_name.py +147 -0
- sf_veritas/infra_details/kubernetes/get_details.py +7 -0
- sf_veritas/infra_details/running_on/__init__.py +17 -0
- sf_veritas/infra_details/running_on/kubernetes.py +11 -0
- sf_veritas/interceptors.py +543 -0
- sf_veritas/libsfnettee.so +0 -0
- sf_veritas/local_env_detect.py +118 -0
- sf_veritas/package_metadata.py +6 -0
- sf_veritas/patches/__init__.py +0 -0
- sf_veritas/patches/_patch_tracker.py +74 -0
- sf_veritas/patches/concurrent_futures.py +19 -0
- sf_veritas/patches/constants.py +1 -0
- sf_veritas/patches/exceptions.py +82 -0
- sf_veritas/patches/multiprocessing.py +32 -0
- sf_veritas/patches/network_libraries/__init__.py +99 -0
- sf_veritas/patches/network_libraries/aiohttp.py +294 -0
- sf_veritas/patches/network_libraries/curl_cffi.py +363 -0
- sf_veritas/patches/network_libraries/http_client.py +670 -0
- sf_veritas/patches/network_libraries/httpcore.py +580 -0
- sf_veritas/patches/network_libraries/httplib2.py +315 -0
- sf_veritas/patches/network_libraries/httpx.py +557 -0
- sf_veritas/patches/network_libraries/niquests.py +218 -0
- sf_veritas/patches/network_libraries/pycurl.py +399 -0
- sf_veritas/patches/network_libraries/requests.py +595 -0
- sf_veritas/patches/network_libraries/ssl_socket.py +822 -0
- sf_veritas/patches/network_libraries/tornado.py +360 -0
- sf_veritas/patches/network_libraries/treq.py +270 -0
- sf_veritas/patches/network_libraries/urllib_request.py +483 -0
- sf_veritas/patches/network_libraries/utils.py +598 -0
- sf_veritas/patches/os.py +17 -0
- sf_veritas/patches/threading.py +231 -0
- sf_veritas/patches/web_frameworks/__init__.py +54 -0
- sf_veritas/patches/web_frameworks/aiohttp.py +798 -0
- sf_veritas/patches/web_frameworks/async_websocket_consumer.py +337 -0
- sf_veritas/patches/web_frameworks/blacksheep.py +532 -0
- sf_veritas/patches/web_frameworks/bottle.py +513 -0
- sf_veritas/patches/web_frameworks/cherrypy.py +683 -0
- sf_veritas/patches/web_frameworks/cors_utils.py +122 -0
- sf_veritas/patches/web_frameworks/django.py +963 -0
- sf_veritas/patches/web_frameworks/eve.py +401 -0
- sf_veritas/patches/web_frameworks/falcon.py +931 -0
- sf_veritas/patches/web_frameworks/fastapi.py +738 -0
- sf_veritas/patches/web_frameworks/flask.py +526 -0
- sf_veritas/patches/web_frameworks/klein.py +501 -0
- sf_veritas/patches/web_frameworks/litestar.py +616 -0
- sf_veritas/patches/web_frameworks/pyramid.py +440 -0
- sf_veritas/patches/web_frameworks/quart.py +841 -0
- sf_veritas/patches/web_frameworks/robyn.py +708 -0
- sf_veritas/patches/web_frameworks/sanic.py +874 -0
- sf_veritas/patches/web_frameworks/starlette.py +742 -0
- sf_veritas/patches/web_frameworks/strawberry.py +1446 -0
- sf_veritas/patches/web_frameworks/tornado.py +485 -0
- sf_veritas/patches/web_frameworks/utils.py +170 -0
- sf_veritas/print_override.py +13 -0
- sf_veritas/regular_data_transmitter.py +444 -0
- sf_veritas/request_interceptor.py +401 -0
- sf_veritas/request_utils.py +550 -0
- sf_veritas/segfault_handler.py +116 -0
- sf_veritas/server_status.py +1 -0
- sf_veritas/shutdown_flag.py +11 -0
- sf_veritas/subprocess_startup.py +3 -0
- sf_veritas/test_cli.py +145 -0
- sf_veritas/thread_local.py +1319 -0
- sf_veritas/timeutil.py +114 -0
- sf_veritas/transmit_exception_to_sailfish.py +28 -0
- sf_veritas/transmitter.py +132 -0
- sf_veritas/types.py +47 -0
- sf_veritas/unified_interceptor.py +1678 -0
- sf_veritas/utils.py +39 -0
- sf_veritas-0.11.10.dist-info/METADATA +97 -0
- sf_veritas-0.11.10.dist-info/RECORD +141 -0
- sf_veritas-0.11.10.dist-info/WHEEL +5 -0
- sf_veritas-0.11.10.dist-info/entry_points.txt +2 -0
- sf_veritas-0.11.10.dist-info/top_level.txt +1 -0
- sf_veritas.libs/libbrotlicommon-6ce2a53c.so.1.0.6 +0 -0
- sf_veritas.libs/libbrotlidec-811d1be3.so.1.0.6 +0 -0
- sf_veritas.libs/libcom_err-730ca923.so.2.1 +0 -0
- sf_veritas.libs/libcrypt-52aca757.so.1.1.0 +0 -0
- sf_veritas.libs/libcrypto-bdaed0ea.so.1.1.1k +0 -0
- sf_veritas.libs/libcurl-eaa3cf66.so.4.5.0 +0 -0
- sf_veritas.libs/libgssapi_krb5-323bbd21.so.2.2 +0 -0
- sf_veritas.libs/libidn2-2f4a5893.so.0.3.6 +0 -0
- sf_veritas.libs/libk5crypto-9a74ff38.so.3.1 +0 -0
- sf_veritas.libs/libkeyutils-2777d33d.so.1.6 +0 -0
- sf_veritas.libs/libkrb5-a55300e8.so.3.3 +0 -0
- sf_veritas.libs/libkrb5support-e6594cfc.so.0.1 +0 -0
- sf_veritas.libs/liblber-2-d20824ef.4.so.2.10.9 +0 -0
- sf_veritas.libs/libldap-2-cea2a960.4.so.2.10.9 +0 -0
- sf_veritas.libs/libnghttp2-39367a22.so.14.17.0 +0 -0
- sf_veritas.libs/libpcre2-8-516f4c9d.so.0.7.1 +0 -0
- sf_veritas.libs/libpsl-99becdd3.so.5.3.1 +0 -0
- sf_veritas.libs/libsasl2-7de4d792.so.3.0.0 +0 -0
- sf_veritas.libs/libselinux-d0805dcb.so.1 +0 -0
- sf_veritas.libs/libssh-c11d285b.so.4.8.7 +0 -0
- sf_veritas.libs/libssl-60250281.so.1.1.1k +0 -0
- sf_veritas.libs/libunistring-05abdd40.so.2.1.0 +0 -0
- sf_veritas.libs/libuuid-95b83d40.so.1.3.0 +0 -0
sf_veritas/__init__.py
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Note: LD_PRELOAD must be set manually by user for C library mode
|
|
2
|
+
# The C library (libsfnettee.so) is available but requires explicit LD_PRELOAD configuration
|
|
3
|
+
|
|
4
|
+
# Install C-level crash handler FIRST (catches crashes before Python can)
|
|
5
|
+
import sys
|
|
6
|
+
try:
|
|
7
|
+
sys.stderr.write("[__init__] Attempting to load C crash handler...\n")
|
|
8
|
+
sys.stderr.flush()
|
|
9
|
+
from . import _sfcrashhandler
|
|
10
|
+
sys.stderr.write("[__init__] C crash handler module loaded, installing...\n")
|
|
11
|
+
sys.stderr.flush()
|
|
12
|
+
_sfcrashhandler.install()
|
|
13
|
+
sys.stderr.write("[__init__] C crash handler installed successfully\n")
|
|
14
|
+
sys.stderr.flush()
|
|
15
|
+
except Exception as e:
|
|
16
|
+
import traceback
|
|
17
|
+
sys.stderr.write(f"[WARNING] Failed to install C crash handler: {e}\n")
|
|
18
|
+
traceback.print_exc(file=sys.stderr)
|
|
19
|
+
sys.stderr.flush()
|
|
20
|
+
|
|
21
|
+
# Install Python-level segfault handler as backup
|
|
22
|
+
try:
|
|
23
|
+
from . import segfault_handler # noqa: F401
|
|
24
|
+
except Exception:
|
|
25
|
+
pass # Silently fail if handler can't be installed
|
|
26
|
+
|
|
27
|
+
from .function_span_profiler import (
|
|
28
|
+
skip_tracing, # Backward compatibility
|
|
29
|
+
skip_function_tracing,
|
|
30
|
+
skip_network_tracing,
|
|
31
|
+
capture_function_spans,
|
|
32
|
+
)
|
|
33
|
+
from .package_metadata import __version__
|
|
34
|
+
from .transmit_exception_to_sailfish import transmit_exception_to_sailfish
|
|
35
|
+
from .unified_interceptor import setup_interceptors, reinitialize_after_fork
|
|
36
|
+
|
|
37
|
+
__all__ = [
|
|
38
|
+
"setup_interceptors",
|
|
39
|
+
"transmit_exception_to_sailfish",
|
|
40
|
+
"skip_tracing", # Backward compatibility
|
|
41
|
+
"skip_function_tracing",
|
|
42
|
+
"skip_network_tracing",
|
|
43
|
+
"capture_function_spans",
|
|
44
|
+
"reinitialize_after_fork",
|
|
45
|
+
"__version__",
|
|
46
|
+
]
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Auto-detection and configuration of LD_PRELOAD mode.
|
|
3
|
+
|
|
4
|
+
This module automatically detects if libsfnettee.so is available in the package
|
|
5
|
+
and sets the LD_PRELOAD environment variable if it's not already set. This enables
|
|
6
|
+
LD_PRELOAD mode automatically without requiring manual configuration.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import os
|
|
10
|
+
import sys
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _auto_enable_ld_preload() -> bool:
|
|
14
|
+
"""
|
|
15
|
+
Check if LD_PRELOAD mode is active.
|
|
16
|
+
|
|
17
|
+
This function checks if the C library (libsfnettee.so) is loaded via LD_PRELOAD.
|
|
18
|
+
It does NOT attempt to automatically enable it - users must set LD_PRELOAD themselves.
|
|
19
|
+
|
|
20
|
+
To enable high-performance C library mode, set LD_PRELOAD before starting Python:
|
|
21
|
+
export LD_PRELOAD=/path/to/site-packages/sf_veritas/libsfnettee.so
|
|
22
|
+
python your_app.py
|
|
23
|
+
|
|
24
|
+
Or in your Dockerfile entrypoint:
|
|
25
|
+
ENV LD_PRELOAD=/usr/local/lib/python3.12/site-packages/sf_veritas/libsfnettee.so
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
True if LD_PRELOAD mode is active (C library loaded)
|
|
29
|
+
False if not active (will use Python patches)
|
|
30
|
+
"""
|
|
31
|
+
# Check if LD_PRELOAD is already set with libsfnettee.so
|
|
32
|
+
current_ld_preload = os.getenv("LD_PRELOAD", "")
|
|
33
|
+
if "libsfnettee.so" in current_ld_preload or "_sfteepreload" in current_ld_preload:
|
|
34
|
+
if os.getenv("SF_DEBUG", "false").lower() == "true":
|
|
35
|
+
sys.stderr.write(f"[sf_veritas] ✓ C library active via LD_PRELOAD: {current_ld_preload}\n")
|
|
36
|
+
sys.stderr.flush()
|
|
37
|
+
return True
|
|
38
|
+
|
|
39
|
+
# Not active - check if library exists and print helpful message
|
|
40
|
+
try:
|
|
41
|
+
package_dir = os.path.dirname(os.path.abspath(__file__))
|
|
42
|
+
libsfnettee_path = os.path.join(package_dir, "libsfnettee.so")
|
|
43
|
+
|
|
44
|
+
if os.path.isfile(libsfnettee_path):
|
|
45
|
+
if os.getenv("SF_DEBUG", "false").lower() == "true":
|
|
46
|
+
sys.stderr.write(f"[sf_veritas] C library available but not loaded (using Python patches)\n")
|
|
47
|
+
sys.stderr.write(f"[sf_veritas] For better performance, set LD_PRELOAD before starting Python:\n")
|
|
48
|
+
sys.stderr.write(f"[sf_veritas] export LD_PRELOAD={libsfnettee_path}\n")
|
|
49
|
+
sys.stderr.flush()
|
|
50
|
+
else:
|
|
51
|
+
if os.getenv("SF_DEBUG", "false").lower() == "true":
|
|
52
|
+
sys.stderr.write(f"[sf_veritas] C library not found at {libsfnettee_path}\n")
|
|
53
|
+
sys.stderr.write(f"[sf_veritas] Using Python patches (slower but works)\n")
|
|
54
|
+
sys.stderr.flush()
|
|
55
|
+
except Exception:
|
|
56
|
+
pass
|
|
57
|
+
|
|
58
|
+
return False
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
# Check if LD_PRELOAD mode is active
|
|
62
|
+
_LD_PRELOAD_ACTIVE = _auto_enable_ld_preload()
|
|
63
|
+
|
|
64
|
+
# Enable Python SSL mode when LD_PRELOAD is active (default ON)
|
|
65
|
+
# This tells the C library to disable its SSL hooks (Python handles HTTPS, C handles HTTP)
|
|
66
|
+
if _LD_PRELOAD_ACTIVE:
|
|
67
|
+
# Default to '1' (C SSL hooks disabled) unless explicitly overridden
|
|
68
|
+
if 'SF_SSL_PYTHON_MODE' not in os.environ:
|
|
69
|
+
os.environ['SF_SSL_PYTHON_MODE'] = '1'
|
|
70
|
+
|
|
71
|
+
if os.getenv("SF_DEBUG", "false").lower() == "true":
|
|
72
|
+
sys.stderr.write("[sf_veritas] ✓ Python SSL mode enabled (C handles HTTP, Python handles HTTPS)\n")
|
|
73
|
+
sys.stderr.flush()
|
sf_veritas/_sfconfig.c
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
// Python C extension module to configure the C library
|
|
2
|
+
// This provides a clean, secure interface using dlsym to find runtime symbols
|
|
3
|
+
#define PY_SSIZE_T_CLEAN
|
|
4
|
+
#include <Python.h>
|
|
5
|
+
#include <dlfcn.h>
|
|
6
|
+
#include <stdlib.h>
|
|
7
|
+
#include <stdio.h>
|
|
8
|
+
|
|
9
|
+
// Function pointers for the C library functions
|
|
10
|
+
typedef void (*sf_set_sink_url_t)(const char *url);
|
|
11
|
+
typedef void (*sf_set_api_key_t)(const char *key);
|
|
12
|
+
typedef void (*sf_set_service_uuid_t)(const char *uuid);
|
|
13
|
+
typedef void (*sf_initialize_t)(void);
|
|
14
|
+
|
|
15
|
+
static sf_set_sink_url_t sf_set_sink_url_ptr = NULL;
|
|
16
|
+
static sf_set_api_key_t sf_set_api_key_ptr = NULL;
|
|
17
|
+
static sf_set_service_uuid_t sf_set_service_uuid_ptr = NULL;
|
|
18
|
+
static sf_initialize_t sf_initialize_ptr = NULL;
|
|
19
|
+
static int symbols_resolved = 0;
|
|
20
|
+
|
|
21
|
+
// Lazy symbol resolution - called on first use of any function
|
|
22
|
+
static void ensure_symbols_resolved(void) {
|
|
23
|
+
if (symbols_resolved) {
|
|
24
|
+
return; // Already resolved
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Clear any previous dlsym errors
|
|
28
|
+
dlerror();
|
|
29
|
+
|
|
30
|
+
// Use RTLD_DEFAULT to search all loaded libraries (including LD_PRELOAD)
|
|
31
|
+
sf_set_sink_url_ptr = (sf_set_sink_url_t)dlsym(RTLD_DEFAULT, "sf_set_sink_url");
|
|
32
|
+
const char *err1 = dlerror();
|
|
33
|
+
|
|
34
|
+
sf_set_api_key_ptr = (sf_set_api_key_t)dlsym(RTLD_DEFAULT, "sf_set_api_key");
|
|
35
|
+
const char *err2 = dlerror();
|
|
36
|
+
|
|
37
|
+
sf_set_service_uuid_ptr = (sf_set_service_uuid_t)dlsym(RTLD_DEFAULT, "sf_set_service_uuid");
|
|
38
|
+
const char *err3 = dlerror();
|
|
39
|
+
|
|
40
|
+
sf_initialize_ptr = (sf_initialize_t)dlsym(RTLD_DEFAULT, "sf_initialize");
|
|
41
|
+
const char *err4 = dlerror();
|
|
42
|
+
|
|
43
|
+
// Debug output to help diagnose symbol resolution issues
|
|
44
|
+
if (!sf_set_sink_url_ptr || !sf_set_api_key_ptr || !sf_set_service_uuid_ptr || !sf_initialize_ptr) {
|
|
45
|
+
const char *ld_preload = getenv("LD_PRELOAD");
|
|
46
|
+
fprintf(stderr, "[_sfconfig] Symbol resolution FAILED!\n");
|
|
47
|
+
fprintf(stderr, " LD_PRELOAD=%s\n", ld_preload ? ld_preload : "(not set)");
|
|
48
|
+
fprintf(stderr, " sf_set_sink_url: %s (%s)\n",
|
|
49
|
+
sf_set_sink_url_ptr ? "OK" : "FAILED", err1 ? err1 : "no error");
|
|
50
|
+
fprintf(stderr, " sf_set_api_key: %s (%s)\n",
|
|
51
|
+
sf_set_api_key_ptr ? "OK" : "FAILED", err2 ? err2 : "no error");
|
|
52
|
+
fprintf(stderr, " sf_set_service_uuid: %s (%s)\n",
|
|
53
|
+
sf_set_service_uuid_ptr ? "OK" : "FAILED", err3 ? err3 : "no error");
|
|
54
|
+
fprintf(stderr, " sf_initialize: %s (%s)\n",
|
|
55
|
+
sf_initialize_ptr ? "OK" : "FAILED", err4 ? err4 : "no error");
|
|
56
|
+
fflush(stderr);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
symbols_resolved = 1;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Python wrapper: sf_set_sink_url(url: str) -> None
|
|
63
|
+
static PyObject* py_sf_set_sink_url(PyObject* self, PyObject* args) {
|
|
64
|
+
const char *url;
|
|
65
|
+
if (!PyArg_ParseTuple(args, "s", &url)) {
|
|
66
|
+
return NULL;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Lazy symbol resolution on first call
|
|
70
|
+
ensure_symbols_resolved();
|
|
71
|
+
|
|
72
|
+
if (!sf_set_sink_url_ptr) {
|
|
73
|
+
PyErr_SetString(PyExc_RuntimeError, "C library not loaded (LD_PRELOAD not active?)");
|
|
74
|
+
return NULL;
|
|
75
|
+
}
|
|
76
|
+
sf_set_sink_url_ptr(url);
|
|
77
|
+
Py_RETURN_NONE;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Python wrapper: sf_set_api_key(key: str) -> None
|
|
81
|
+
static PyObject* py_sf_set_api_key(PyObject* self, PyObject* args) {
|
|
82
|
+
const char *key;
|
|
83
|
+
if (!PyArg_ParseTuple(args, "s", &key)) {
|
|
84
|
+
return NULL;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Lazy symbol resolution on first call
|
|
88
|
+
ensure_symbols_resolved();
|
|
89
|
+
|
|
90
|
+
if (!sf_set_api_key_ptr) {
|
|
91
|
+
PyErr_SetString(PyExc_RuntimeError, "C library not loaded (LD_PRELOAD not active?)");
|
|
92
|
+
return NULL;
|
|
93
|
+
}
|
|
94
|
+
sf_set_api_key_ptr(key);
|
|
95
|
+
Py_RETURN_NONE;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Python wrapper: sf_set_service_uuid(uuid: str) -> None
|
|
99
|
+
static PyObject* py_sf_set_service_uuid(PyObject* self, PyObject* args) {
|
|
100
|
+
const char *uuid;
|
|
101
|
+
if (!PyArg_ParseTuple(args, "s", &uuid)) {
|
|
102
|
+
return NULL;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Lazy symbol resolution on first call
|
|
106
|
+
ensure_symbols_resolved();
|
|
107
|
+
|
|
108
|
+
if (!sf_set_service_uuid_ptr) {
|
|
109
|
+
PyErr_SetString(PyExc_RuntimeError, "C library not loaded (LD_PRELOAD not active?)");
|
|
110
|
+
return NULL;
|
|
111
|
+
}
|
|
112
|
+
sf_set_service_uuid_ptr(uuid);
|
|
113
|
+
Py_RETURN_NONE;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Python wrapper: sf_initialize() -> None
|
|
117
|
+
static PyObject* py_sf_initialize(PyObject* self, PyObject* args) {
|
|
118
|
+
// Lazy symbol resolution on first call
|
|
119
|
+
ensure_symbols_resolved();
|
|
120
|
+
|
|
121
|
+
if (!sf_initialize_ptr) {
|
|
122
|
+
PyErr_SetString(PyExc_RuntimeError, "C library not loaded (LD_PRELOAD not active?)");
|
|
123
|
+
return NULL;
|
|
124
|
+
}
|
|
125
|
+
sf_initialize_ptr();
|
|
126
|
+
Py_RETURN_NONE;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Method definitions
|
|
130
|
+
static PyMethodDef SfConfigMethods[] = {
|
|
131
|
+
{"set_sink_url", py_sf_set_sink_url, METH_VARARGS,
|
|
132
|
+
"Set the GraphQL endpoint URL for the C library"},
|
|
133
|
+
{"set_api_key", py_sf_set_api_key, METH_VARARGS,
|
|
134
|
+
"Set the API key for the C library"},
|
|
135
|
+
{"set_service_uuid", py_sf_set_service_uuid, METH_VARARGS,
|
|
136
|
+
"Set the service UUID for the C library"},
|
|
137
|
+
{"initialize", py_sf_initialize, METH_NOARGS,
|
|
138
|
+
"Initialize and activate the C library (sets SF_INITIALIZED=1)"},
|
|
139
|
+
{NULL, NULL, 0, NULL}
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
// Module definition
|
|
143
|
+
static struct PyModuleDef sfconfig_module = {
|
|
144
|
+
PyModuleDef_HEAD_INIT,
|
|
145
|
+
"_sfconfig",
|
|
146
|
+
"Configuration interface for the Sailfish C library",
|
|
147
|
+
-1,
|
|
148
|
+
SfConfigMethods
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
// Module initialization
|
|
152
|
+
PyMODINIT_FUNC PyInit__sfconfig(void) {
|
|
153
|
+
PyObject *module = PyModule_Create(&sfconfig_module);
|
|
154
|
+
if (module == NULL) {
|
|
155
|
+
return NULL;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Symbol resolution is done lazily on first function call
|
|
159
|
+
// This ensures the C library is fully loaded before we try to find symbols
|
|
160
|
+
|
|
161
|
+
return module;
|
|
162
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
// C-level crash handler that prints registers and stack addresses
|
|
2
|
+
// This catches segfaults that happen in C code before Python can handle them
|
|
3
|
+
|
|
4
|
+
// Ensure we have write() and fsync() available
|
|
5
|
+
#ifndef _POSIX_C_SOURCE
|
|
6
|
+
#define _POSIX_C_SOURCE 200809L
|
|
7
|
+
#endif
|
|
8
|
+
|
|
9
|
+
// macOS requires _XOPEN_SOURCE for ucontext
|
|
10
|
+
#ifdef __APPLE__
|
|
11
|
+
#define _XOPEN_SOURCE 600
|
|
12
|
+
#endif
|
|
13
|
+
|
|
14
|
+
#include <Python.h>
|
|
15
|
+
#include <signal.h>
|
|
16
|
+
#include <stdio.h>
|
|
17
|
+
#include <stdlib.h>
|
|
18
|
+
#include <string.h>
|
|
19
|
+
#include <unistd.h>
|
|
20
|
+
#include <execinfo.h>
|
|
21
|
+
#include <sys/types.h>
|
|
22
|
+
|
|
23
|
+
// Platform-specific includes for register access
|
|
24
|
+
#if defined(__linux__)
|
|
25
|
+
#include <ucontext.h>
|
|
26
|
+
#include <sys/syscall.h>
|
|
27
|
+
#elif defined(__APPLE__)
|
|
28
|
+
#include <sys/ucontext.h>
|
|
29
|
+
#endif
|
|
30
|
+
|
|
31
|
+
// Get thread ID
|
|
32
|
+
static long gettid(void) {
|
|
33
|
+
#ifdef SYS_gettid
|
|
34
|
+
return (long)syscall(SYS_gettid);
|
|
35
|
+
#else
|
|
36
|
+
return (long)getpid();
|
|
37
|
+
#endif
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Signal handler that prints everything
|
|
41
|
+
static void crash_handler(int sig, siginfo_t *si, void *ctx) {
|
|
42
|
+
ucontext_t *uc = (ucontext_t *)ctx;
|
|
43
|
+
void *backtrace_buffer[100];
|
|
44
|
+
int backtrace_size;
|
|
45
|
+
char **bt_symbols;
|
|
46
|
+
int i;
|
|
47
|
+
|
|
48
|
+
// Make stderr unbuffered to ensure output appears
|
|
49
|
+
setvbuf(stderr, NULL, _IONBF, 0);
|
|
50
|
+
|
|
51
|
+
// Print to stderr directly (unbuffered)
|
|
52
|
+
const char *sig_name =
|
|
53
|
+
sig == SIGSEGV ? "SIGSEGV" :
|
|
54
|
+
sig == SIGABRT ? "SIGABRT" :
|
|
55
|
+
sig == SIGBUS ? "SIGBUS" :
|
|
56
|
+
sig == SIGFPE ? "SIGFPE" :
|
|
57
|
+
sig == SIGILL ? "SIGILL" : "UNKNOWN";
|
|
58
|
+
|
|
59
|
+
// Write directly to fd 2 (stderr) to bypass buffering entirely
|
|
60
|
+
const char *header = "\n\n=== CRASH HANDLER TRIGGERED ===\n";
|
|
61
|
+
write(2, header, strlen(header));
|
|
62
|
+
|
|
63
|
+
fprintf(stderr, "\n");
|
|
64
|
+
fprintf(stderr, "================================================================================\n");
|
|
65
|
+
fprintf(stderr, "CRASH DETECTED: Signal %d (%s)\n", sig, sig_name);
|
|
66
|
+
fprintf(stderr, "================================================================================\n");
|
|
67
|
+
fprintf(stderr, "Process ID: %d\n", getpid());
|
|
68
|
+
fprintf(stderr, "Thread ID: %ld\n", gettid());
|
|
69
|
+
fprintf(stderr, "Signal code: %d\n", si->si_code);
|
|
70
|
+
fprintf(stderr, "Fault addr: %p\n", si->si_addr);
|
|
71
|
+
fprintf(stderr, "\n");
|
|
72
|
+
|
|
73
|
+
// Print registers (platform-specific)
|
|
74
|
+
#if defined(__linux__) && defined(__x86_64__)
|
|
75
|
+
fprintf(stderr, "--- x86_64 Registers (Linux) ---\n");
|
|
76
|
+
fprintf(stderr, "RIP: 0x%016llx RSP: 0x%016llx RBP: 0x%016llx\n",
|
|
77
|
+
(unsigned long long)uc->uc_mcontext.gregs[REG_RIP],
|
|
78
|
+
(unsigned long long)uc->uc_mcontext.gregs[REG_RSP],
|
|
79
|
+
(unsigned long long)uc->uc_mcontext.gregs[REG_RBP]);
|
|
80
|
+
fprintf(stderr, "RAX: 0x%016llx RBX: 0x%016llx RCX: 0x%016llx\n",
|
|
81
|
+
(unsigned long long)uc->uc_mcontext.gregs[REG_RAX],
|
|
82
|
+
(unsigned long long)uc->uc_mcontext.gregs[REG_RBX],
|
|
83
|
+
(unsigned long long)uc->uc_mcontext.gregs[REG_RCX]);
|
|
84
|
+
fprintf(stderr, "RDX: 0x%016llx RSI: 0x%016llx RDI: 0x%016llx\n",
|
|
85
|
+
(unsigned long long)uc->uc_mcontext.gregs[REG_RDX],
|
|
86
|
+
(unsigned long long)uc->uc_mcontext.gregs[REG_RSI],
|
|
87
|
+
(unsigned long long)uc->uc_mcontext.gregs[REG_RDI]);
|
|
88
|
+
fprintf(stderr, "R8: 0x%016llx R9: 0x%016llx R10: 0x%016llx\n",
|
|
89
|
+
(unsigned long long)uc->uc_mcontext.gregs[REG_R8],
|
|
90
|
+
(unsigned long long)uc->uc_mcontext.gregs[REG_R9],
|
|
91
|
+
(unsigned long long)uc->uc_mcontext.gregs[REG_R10]);
|
|
92
|
+
fprintf(stderr, "R11: 0x%016llx R12: 0x%016llx R13: 0x%016llx\n",
|
|
93
|
+
(unsigned long long)uc->uc_mcontext.gregs[REG_R11],
|
|
94
|
+
(unsigned long long)uc->uc_mcontext.gregs[REG_R12],
|
|
95
|
+
(unsigned long long)uc->uc_mcontext.gregs[REG_R13]);
|
|
96
|
+
fprintf(stderr, "R14: 0x%016llx R15: 0x%016llx\n",
|
|
97
|
+
(unsigned long long)uc->uc_mcontext.gregs[REG_R14],
|
|
98
|
+
(unsigned long long)uc->uc_mcontext.gregs[REG_R15]);
|
|
99
|
+
#elif defined(__linux__) && defined(__aarch64__)
|
|
100
|
+
fprintf(stderr, "--- ARM64 Registers (Linux) ---\n");
|
|
101
|
+
fprintf(stderr, "PC: 0x%016llx SP: 0x%016llx FP: 0x%016llx\n",
|
|
102
|
+
(unsigned long long)uc->uc_mcontext.pc,
|
|
103
|
+
(unsigned long long)uc->uc_mcontext.sp,
|
|
104
|
+
(unsigned long long)uc->uc_mcontext.regs[29]);
|
|
105
|
+
for (i = 0; i < 29; i += 3) {
|
|
106
|
+
fprintf(stderr, "X%-2d: 0x%016llx ", i, (unsigned long long)uc->uc_mcontext.regs[i]);
|
|
107
|
+
if (i + 1 < 29)
|
|
108
|
+
fprintf(stderr, "X%-2d: 0x%016llx ", i+1, (unsigned long long)uc->uc_mcontext.regs[i+1]);
|
|
109
|
+
if (i + 2 < 29)
|
|
110
|
+
fprintf(stderr, "X%-2d: 0x%016llx", i+2, (unsigned long long)uc->uc_mcontext.regs[i+2]);
|
|
111
|
+
fprintf(stderr, "\n");
|
|
112
|
+
}
|
|
113
|
+
#elif defined(__APPLE__) && defined(__x86_64__)
|
|
114
|
+
fprintf(stderr, "--- x86_64 Registers (macOS) ---\n");
|
|
115
|
+
fprintf(stderr, "RIP: 0x%016llx RSP: 0x%016llx RBP: 0x%016llx\n",
|
|
116
|
+
(unsigned long long)uc->uc_mcontext->__ss.__rip,
|
|
117
|
+
(unsigned long long)uc->uc_mcontext->__ss.__rsp,
|
|
118
|
+
(unsigned long long)uc->uc_mcontext->__ss.__rbp);
|
|
119
|
+
fprintf(stderr, "RAX: 0x%016llx RBX: 0x%016llx RCX: 0x%016llx\n",
|
|
120
|
+
(unsigned long long)uc->uc_mcontext->__ss.__rax,
|
|
121
|
+
(unsigned long long)uc->uc_mcontext->__ss.__rbx,
|
|
122
|
+
(unsigned long long)uc->uc_mcontext->__ss.__rcx);
|
|
123
|
+
fprintf(stderr, "RDX: 0x%016llx RSI: 0x%016llx RDI: 0x%016llx\n",
|
|
124
|
+
(unsigned long long)uc->uc_mcontext->__ss.__rdx,
|
|
125
|
+
(unsigned long long)uc->uc_mcontext->__ss.__rsi,
|
|
126
|
+
(unsigned long long)uc->uc_mcontext->__ss.__rdi);
|
|
127
|
+
fprintf(stderr, "R8: 0x%016llx R9: 0x%016llx R10: 0x%016llx\n",
|
|
128
|
+
(unsigned long long)uc->uc_mcontext->__ss.__r8,
|
|
129
|
+
(unsigned long long)uc->uc_mcontext->__ss.__r9,
|
|
130
|
+
(unsigned long long)uc->uc_mcontext->__ss.__r10);
|
|
131
|
+
fprintf(stderr, "R11: 0x%016llx R12: 0x%016llx R13: 0x%016llx\n",
|
|
132
|
+
(unsigned long long)uc->uc_mcontext->__ss.__r11,
|
|
133
|
+
(unsigned long long)uc->uc_mcontext->__ss.__r12,
|
|
134
|
+
(unsigned long long)uc->uc_mcontext->__ss.__r13);
|
|
135
|
+
fprintf(stderr, "R14: 0x%016llx R15: 0x%016llx\n",
|
|
136
|
+
(unsigned long long)uc->uc_mcontext->__ss.__r14,
|
|
137
|
+
(unsigned long long)uc->uc_mcontext->__ss.__r15);
|
|
138
|
+
#elif defined(__APPLE__) && defined(__aarch64__)
|
|
139
|
+
fprintf(stderr, "--- ARM64 Registers (macOS) ---\n");
|
|
140
|
+
fprintf(stderr, "PC: 0x%016llx SP: 0x%016llx FP: 0x%016llx\n",
|
|
141
|
+
(unsigned long long)__darwin_arm_thread_state64_get_pc(uc->uc_mcontext->__ss),
|
|
142
|
+
(unsigned long long)__darwin_arm_thread_state64_get_sp(uc->uc_mcontext->__ss),
|
|
143
|
+
(unsigned long long)__darwin_arm_thread_state64_get_fp(uc->uc_mcontext->__ss));
|
|
144
|
+
for (i = 0; i < 29; i += 3) {
|
|
145
|
+
fprintf(stderr, "X%-2d: 0x%016llx ", i, (unsigned long long)uc->uc_mcontext->__ss.__x[i]);
|
|
146
|
+
if (i + 1 < 29)
|
|
147
|
+
fprintf(stderr, "X%-2d: 0x%016llx ", i+1, (unsigned long long)uc->uc_mcontext->__ss.__x[i+1]);
|
|
148
|
+
if (i + 2 < 29)
|
|
149
|
+
fprintf(stderr, "X%-2d: 0x%016llx", i+2, (unsigned long long)uc->uc_mcontext->__ss.__x[i+2]);
|
|
150
|
+
fprintf(stderr, "\n");
|
|
151
|
+
}
|
|
152
|
+
#else
|
|
153
|
+
fprintf(stderr, "--- Registers (architecture not recognized) ---\n");
|
|
154
|
+
(void)uc; // Suppress unused variable warning
|
|
155
|
+
#endif
|
|
156
|
+
fprintf(stderr, "\n");
|
|
157
|
+
|
|
158
|
+
// Print native backtrace
|
|
159
|
+
fprintf(stderr, "--- Native Stack Trace (C level) ---\n");
|
|
160
|
+
backtrace_size = backtrace(backtrace_buffer, 100);
|
|
161
|
+
bt_symbols = backtrace_symbols(backtrace_buffer, backtrace_size);
|
|
162
|
+
|
|
163
|
+
if (bt_symbols) {
|
|
164
|
+
for (i = 0; i < backtrace_size; i++) {
|
|
165
|
+
fprintf(stderr, "[%2d] %s\n", i, bt_symbols[i]);
|
|
166
|
+
}
|
|
167
|
+
free(bt_symbols);
|
|
168
|
+
} else {
|
|
169
|
+
fprintf(stderr, "Failed to get backtrace symbols\n");
|
|
170
|
+
}
|
|
171
|
+
fprintf(stderr, "\n");
|
|
172
|
+
|
|
173
|
+
// Print raw stack memory
|
|
174
|
+
fprintf(stderr, "--- Stack Memory (32 bytes from fault) ---\n");
|
|
175
|
+
unsigned char *fault_ptr = (unsigned char *)si->si_addr;
|
|
176
|
+
fprintf(stderr, "Fault address: %p\n", fault_ptr);
|
|
177
|
+
|
|
178
|
+
// Try to read memory around fault address (may fail)
|
|
179
|
+
// Print stack pointer area instead
|
|
180
|
+
#if defined(__linux__) && defined(__x86_64__)
|
|
181
|
+
unsigned long long *sp = (unsigned long long *)uc->uc_mcontext.gregs[REG_RSP];
|
|
182
|
+
#elif defined(__linux__) && defined(__aarch64__)
|
|
183
|
+
unsigned long long *sp = (unsigned long long *)uc->uc_mcontext.sp;
|
|
184
|
+
#elif defined(__APPLE__) && defined(__x86_64__)
|
|
185
|
+
unsigned long long *sp = (unsigned long long *)uc->uc_mcontext->__ss.__rsp;
|
|
186
|
+
#elif defined(__APPLE__) && defined(__aarch64__)
|
|
187
|
+
unsigned long long *sp = (unsigned long long *)__darwin_arm_thread_state64_get_sp(uc->uc_mcontext->__ss);
|
|
188
|
+
#else
|
|
189
|
+
unsigned long long *sp = NULL;
|
|
190
|
+
#endif
|
|
191
|
+
|
|
192
|
+
if (sp) {
|
|
193
|
+
fprintf(stderr, "Stack at RSP/SP (%p):\n", sp);
|
|
194
|
+
for (i = 0; i < 4; i++) {
|
|
195
|
+
fprintf(stderr, " [SP+%2d] 0x%016llx\n", i*8, (unsigned long long)sp[i]);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
fprintf(stderr, "\n");
|
|
199
|
+
|
|
200
|
+
fprintf(stderr, "================================================================================\n");
|
|
201
|
+
fprintf(stderr, "Use addr2line to decode addresses:\n");
|
|
202
|
+
fprintf(stderr, " addr2line -e /path/to/_sffuncspan.*.so <address>\n");
|
|
203
|
+
fprintf(stderr, "================================================================================\n");
|
|
204
|
+
fprintf(stderr, "\n");
|
|
205
|
+
|
|
206
|
+
fflush(stderr);
|
|
207
|
+
fsync(2); // Force write to disk
|
|
208
|
+
|
|
209
|
+
const char *footer = "\n=== END CRASH HANDLER ===\n\n";
|
|
210
|
+
write(2, footer, strlen(footer));
|
|
211
|
+
|
|
212
|
+
// Re-raise signal with default handler (generates core dump)
|
|
213
|
+
signal(sig, SIG_DFL);
|
|
214
|
+
raise(sig);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Install crash handler
|
|
218
|
+
static PyObject *install_crash_handler(PyObject *self, PyObject *args) {
|
|
219
|
+
struct sigaction sa;
|
|
220
|
+
memset(&sa, 0, sizeof(sa));
|
|
221
|
+
sa.sa_sigaction = crash_handler;
|
|
222
|
+
sa.sa_flags = SA_SIGINFO | SA_RESTART;
|
|
223
|
+
sigemptyset(&sa.sa_mask);
|
|
224
|
+
|
|
225
|
+
if (sigaction(SIGSEGV, &sa, NULL) == -1) {
|
|
226
|
+
PyErr_SetString(PyExc_RuntimeError, "Failed to install SIGSEGV handler");
|
|
227
|
+
return NULL;
|
|
228
|
+
}
|
|
229
|
+
if (sigaction(SIGABRT, &sa, NULL) == -1) {
|
|
230
|
+
PyErr_SetString(PyExc_RuntimeError, "Failed to install SIGABRT handler");
|
|
231
|
+
return NULL;
|
|
232
|
+
}
|
|
233
|
+
if (sigaction(SIGBUS, &sa, NULL) == -1) {
|
|
234
|
+
PyErr_SetString(PyExc_RuntimeError, "Failed to install SIGBUS handler");
|
|
235
|
+
return NULL;
|
|
236
|
+
}
|
|
237
|
+
if (sigaction(SIGFPE, &sa, NULL) == -1) {
|
|
238
|
+
PyErr_SetString(PyExc_RuntimeError, "Failed to install SIGFPE handler");
|
|
239
|
+
return NULL;
|
|
240
|
+
}
|
|
241
|
+
if (sigaction(SIGILL, &sa, NULL) == -1) {
|
|
242
|
+
PyErr_SetString(PyExc_RuntimeError, "Failed to install SIGILL handler");
|
|
243
|
+
return NULL;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
fprintf(stderr, "[_sfcrashhandler] C-level crash handlers installed (PID=%d)\n", getpid());
|
|
247
|
+
fflush(stderr);
|
|
248
|
+
|
|
249
|
+
Py_RETURN_NONE;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
static PyMethodDef crash_handler_methods[] = {
|
|
253
|
+
{"install", install_crash_handler, METH_NOARGS, "Install C-level crash handler"},
|
|
254
|
+
{NULL, NULL, 0, NULL}
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
static struct PyModuleDef crash_handler_module = {
|
|
258
|
+
PyModuleDef_HEAD_INIT,
|
|
259
|
+
"_sfcrashhandler",
|
|
260
|
+
"C-level crash handler for debugging segfaults",
|
|
261
|
+
-1,
|
|
262
|
+
crash_handler_methods
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
PyMODINIT_FUNC PyInit__sfcrashhandler(void) {
|
|
266
|
+
return PyModule_Create(&crash_handler_module);
|
|
267
|
+
}
|
|
Binary file
|