Closed pwaller closed 5 years ago
ptrace
docs:
The request
ptrace(PTRACE_TRACEME, 0, 0, 0);
turns the calling thread into a tracee. The thread continues to run (doesn't enter ptrace-stop).
However it does say:
If the PTRACE_O_TRACEEXEC option is not in effect for the execing tracee, and if the tracee was PTRACE_ATTACHed rather
that PTRACE_SEIZEd, the kernel delivers an extra SIGTRAP to the tracee after execve(2) returns. This is an ordinary sig‐
nal (similar to one which can be generated by kill -TRAP), not a special kind of ptrace-stop. Employing PTRACE_GETSIGINFO
for this signal returns si_code set to 0 (SI_USER). This signal may be blocked by signal mask, and thus may be delivered
(much) later.
I think this is saying that you'll get a SIGTRAP immediately after execve
, which can be continued with SIGCONT.
So that seems to be the way to do it. Slightly unfortunate to need to use ptrace because it may require further elevated permissions, but I guess the least invasive thing to do is:
Ptrace: true
PTRACE_DETACH
.Is such hackery suitable for a perf.Command
library function?
That sounds reasonable to me. One question: where does the PTRACE_ATTACH
fit in?
Ah, I think there is no need for that. Never mind. Sorry for the noise.
One use case I have is to measure another process I want to start from Go. A slight challenge I immediately came up against was how to start the measurement before the process starts doing useful work.
Assumptions:
Illustration of the issue
Idea
So my idea is to have some sort of user interface which takes the process to run. Either the
*exec.Cmd
, or arguments that are passed to `exec.Command (though I guess that would be less flexible).First there is a challenge to solve: How to create a process in Go such that it is in the stopped state, so that you can start measurement before it does work you want to measure? Searching around I'm surprised there is not an immediate solution to this.
Ptrace
on SysProcAttr might do it - I haven't checked yet.The next best thing I can think of is to rig up a shell process along the lines of
sh -c 'kill -STOP $$; exec "$@"' -- ...
.Whatever the solution is, it could be wrapped up in
perf.Command
or alike.