Skip to content

Commit 9963d1f

Browse files
Document SYS_PTRACE
1 parent e959f7d commit 9963d1f

File tree

2 files changed

+71
-14
lines changed

2 files changed

+71
-14
lines changed

debugwand/cli.py

Lines changed: 49 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -133,19 +133,55 @@ def _inject_debugpy_into_pod(pod: PodInfo, pid: int, script_path: str) -> None:
133133
print_step(
134134
f"Injecting debugpy into PID [cyan bold]{pid}[/cyan bold] in pod [blue]{pod.name}[/blue]..."
135135
)
136-
# Run injection in background (non-blocking)
137-
exec_command_in_pod(
138-
pod=pod,
139-
command=[
140-
"python3",
141-
"/tmp/attacher.py",
142-
"--pid",
143-
str(pid),
144-
"--script",
145-
f"/tmp/{script_basename}",
146-
],
147-
background=True,
148-
)
136+
# Run injection synchronously to capture errors
137+
try:
138+
result = exec_command_in_pod(
139+
pod=pod,
140+
command=[
141+
"python3",
142+
"/tmp/attacher.py",
143+
"--pid",
144+
str(pid),
145+
"--script",
146+
f"/tmp/{script_basename}",
147+
],
148+
silent_errors=True,
149+
)
150+
except subprocess.CalledProcessError as e:
151+
# Check for permission error
152+
if "CAP_SYS_PTRACE" in e.stdout or "Permission denied" in str(e.stderr):
153+
typer.echo(
154+
"\n❌ Permission denied: Cannot attach to process.", err=True
155+
)
156+
typer.echo(
157+
" On Linux/containers, you need CAP_SYS_PTRACE capability.", err=True
158+
)
159+
typer.echo(
160+
" Add this to your Kubernetes deployment:", err=True
161+
)
162+
typer.echo(
163+
" securityContext:", err=True
164+
)
165+
typer.echo(
166+
" capabilities:", err=True
167+
)
168+
typer.echo(
169+
" add:", err=True
170+
)
171+
typer.echo(
172+
" - SYS_PTRACE", err=True
173+
)
174+
typer.echo(
175+
"\n Or for Docker: docker run --cap-add=SYS_PTRACE ...", err=True
176+
)
177+
typer.echo(
178+
"\n See: https://docs.python.org/3/howto/remote_debugging.html", err=True
179+
)
180+
raise typer.Exit(1)
181+
else:
182+
typer.echo(f"\n❌ Failed to inject debugpy: {e.stderr or e.stdout}", err=True)
183+
raise typer.Exit(1)
184+
149185
# Give debugpy time to start listening
150186
time.sleep(2)
151187
print_success(

docs/troubleshooting.md

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
11
# Troubleshooting
22

3+
## "Permission denied" / "CAP_SYS_PTRACE"
4+
5+
On Linux and in containers, you need the `CAP_SYS_PTRACE` capability to attach to a running process. See the [Python remote debugging docs](https://docs.python.org/3/howto/remote_debugging.html) for details.
6+
7+
**Kubernetes:** Add to your deployment:
8+
```yaml
9+
securityContext:
10+
capabilities:
11+
add:
12+
- SYS_PTRACE
13+
```
14+
15+
**Docker:** Run with `--cap-add=SYS_PTRACE`:
16+
```bash
17+
docker run --cap-add=SYS_PTRACE ...
18+
```
19+
20+
**Note:** macOS may require running with elevated privileges (`sudo`) instead of `CAP_SYS_PTRACE`.
21+
322
## "No module named 'debugpy'"
423

524
The target pod doesn't have debugpy installed. Add debugpy to your application dependencies.
@@ -11,11 +30,13 @@ The target pod doesn't have debugpy installed. Add debugpy to your application d
1130
3. Verify path mappings in `launch.json` or DAP config
1231
4. Check Python version compatibility (3.14+ required)
1332

33+
34+
1435
## Breakpoints not hitting
1536

1637
**Path mappings:** Ensure your `launch.json` maps local to remote paths correctly.
1738

1839
**Multiple pods:** If you have multiple replicas, requests may be load-balanced to a different pod than the one you're debugging. You can:
1940
- Set `DEBUGWAND_AUTO_SELECT_POD=1` to automatically select the newest pod
2041
- Scale down to a single replica during debugging
21-
- Use pod selection to choose the specific pod handling your traffic
42+
- Use pod selection to choose the specific pod handling your traffic

0 commit comments

Comments
 (0)