Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

syscall: ptrace calls must all come from one thread #7699

Closed
gopherbot opened this issue Apr 3, 2014 · 8 comments
Closed

syscall: ptrace calls must all come from one thread #7699

gopherbot opened this issue Apr 3, 2014 · 8 comments

Comments

@gopherbot
Copy link

by tom.fogal:

What does 'go version' print?

This bug occurs on both:

  go version devel +23cb4547ef55 Wed Apr 02 19:43:39 2014 +0900 linux/amd64

and

  go version go1.1.2 linux/amd64

What steps reproduce the problem?

os.StartProcess with 'Ptrace' set in your attr; then try to query any state for the
process.

This is a sample program:

  http://play.golang.org/p/bSI7aGlcyt

Unfortunately it does not compile in the playground.  The environment
must be slightly different, as it compiles fine with the two Go
versions listed above.

What happened?

For me, the functionality is split about 50/50: half the time, the
program on the playground works fine, which is to say it counts the
number of instructions a subprocess requires to execute.  The other
half of the time I receive:

  error single stepping: no such process
  panic: ptrace

and a stacktrace (see lines 22--26).

What should have happened instead?

I would like the program to count the number of instructions of the
subprocess reliably, without panic'ing.

Please provide any additional information below.

I have experimented with adding

  proc.Signal(syscall.SIGSTOP)

into the program closely after the os.StartProcess.  Subjectively,
this seems to help, but it does not fix the problem.

This is a transliteration of a C program:

  http://eli.thegreenplace.net/files/prog_code/articles_code/debugger/simple_tracer.c

into Go.  The C program works reliably.  I checked the implementation of
forkAndExecInChild (syscall/exec_linux.go) and it does seem to properly set
PTRACE_TRACEME.  Perhaps the combination of other things that it does prevents the
normal parent-notification-when-child-does-exec operation.
@gopherbot
Copy link
Author

Comment 1 by tom.fogal:

burns.ethan@gmail.com suggested that I add:
  func init() { runtime.LockOSThread() }
to the program.  This does indeed seem to fix the problem!
The 'SysProcAttr'ibutes includes (as used in the program above) an attribute to indicate
that one wants to trace the spawned process.  It seems from this example that the
default setup, however, will never work without locking the thread.  Perhaps
forkAndExecInChild should lock the thread for the user, then?

@ianlancetaylor
Copy link
Contributor

Comment 2:

I haven't tried to figure out what is going on here, but given that we have a Ptrace
field in syscall.SysProcAttr we should document this or fix it.

Labels changed: added repo-main, release-go1.3maybe.

@rsc
Copy link
Contributor

rsc commented May 9, 2014

Comment 3:

All calls to ptrace for a given child must be made from the same thread. It's a ptrace
API bug that no Unix vendor has bothered to fix. There are many such problems with
ptrace. I am not sure we can document them all, or even in enough detail to explain how
to use it. Syscall in particular is mostly undocumented. Perhaps some day operating
systems will have a good API for debugging programs.

Status changed to Unfortunate.

@tarndt
Copy link

tarndt commented Mar 25, 2016

Unfortunate indeed, I just wasted many days of project progress on this bug. 😿

I was intercepting syscalls using ptrace's syscall.PtraceSyscall and I was getting syscall.ESRCH, but only intermittently after 30k to 200k successful interception enter-exit cycles.

I think either:

  1. We should add syscall package documentation line that reads "All calls to ptrace for a given child must be made from the same thread; therefore, use runtime.LockOSThread() to guarantee this behavior occurs for any programs that use syscall.Ptrace*(.. functions".
  2. We should call runtime.LockOSThread() the first time a `syscall.Ptrace* function is used and document that behavior in the syscall package.

I realize this is a stupid (non-Go) API fragility, but the current Go API inferface implementation is both guaranteed to break by default for non-trivial ptrace use cases and, while known to be so, is not documented to say so. Perhaps this was less of a major issue back at 1.3 when GOMAXPROCs defaulted to 1?

@rsc @ianlancetaylor Does this need to be re-evaluated in light of the GOMAXPROCs change that took place with Go 1.5?

@bradfitz
Copy link
Contributor

This is unrelated to GOMAXPROCS.

@bradfitz
Copy link
Contributor

...that is, even with GOMAXPROCS 1, Go has always used different threads.

@tarndt
Copy link

tarndt commented Mar 26, 2016

...that is, even with GOMAXPROCS 1, Go has always used different threads.

OK, thanks for the clarification, I wasn't sure if that was the case. I still think something should be done, even if its a single sentence of documentation. That of course is just an opinion.

@bradfitz
Copy link
Contributor

Two year old issues are not the place for this, though. This bug is already fixed. In fact, we're about to deploy a bot to auto-freeze all old closed issues. Please open a new one for documentation.

@golang golang locked and limited conversation to collaborators Mar 26, 2017
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants