-
Notifications
You must be signed in to change notification settings - Fork 17.9k
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
runtime: unable to use SIGSTOP to background #4391
Labels
Milestone
Comments
This makes the backgrounding mostly work: package main import ( "syscall" "fmt" ) func main() { fmt.Println("one") pid := syscall.Getpid() tid := syscall.Gettid() err := syscall.Tgkill(pid, tid, syscall.SIGSTOP) if err != nil { panic("bleh") } fmt.Println("two") } except now any other threads that happen to be trying to read /dev/tty are busy looping getting endless SIGTTIN. Although that may be an artifact of me using strace to look at them. |
Alright so I said "mostly". That's because in a real app (my fork of godit, with suspend support https://github.com/tv42/godit/tree/suspend -- depends on my fork of termbox-go), if I look at the process with `strace -ff -p "$(pidof godit)"`, after I hit control-Z, the rest of the threads seem to start busy looping. I don't currently know if this is triggered purely by strace; the CPU usage doesn't spike significantly. Also, this might just mean the app needs to catch SIGTTIN -- but what should it do? [pid 23688] --- SIGTTIN (Stopped (tty input)) @ 0 (0) --- [pid 23689] --- SIGTTIN (Stopped (tty input)) @ 0 (0) --- [pid 23688] restart_syscall(<... resuming interrupted call ...> <unfinished ...> [pid 23689] --- SIGTTIN (Stopped (tty input)) @ 0 (0) --- [pid 23691] <... futex resumed> ) = ? ERESTARTSYS (To be restarted) [pid 23690] <... futex resumed> ) = ? ERESTARTSYS (To be restarted) [pid 23691] --- SIGTTIN (Stopped (tty input)) @ 0 (0) --- [pid 23690] --- SIGTTIN (Stopped (tty input)) @ 0 (0) --- [pid 23691] futex(0xf84005fc28, FUTEX_WAIT, 0, NULL <unfinished ...> [pid 23690] futex(0x586678, FUTEX_WAIT, 0, NULL <unfinished ...> [pid 23689] read(4, <unfinished ...> [pid 23688] <... restart_syscall resumed> ) = ? ERESTART_RESTARTBLOCK (To be restarted) [pid 23689] <... read resumed> 0xf8400cf000, 128) = ? ERESTARTSYS (To be restarted) [pid 23688] --- SIGTTIN (Stopped (tty input)) @ 0 (0) --- [pid 23689] --- SIGTTIN (Stopped (tty input)) @ 0 (0) --- [pid 23688] restart_syscall(<... resuming interrupted call ...> <unfinished ...> [pid 23689] --- SIGTTIN (Stopped (tty input)) @ 0 (0) --- [pid 23691] <... futex resumed> ) = ? ERESTARTSYS (To be restarted) [pid 23690] <... futex resumed> ) = ? ERESTARTSYS (To be restarted) [pid 23691] --- SIGTTIN (Stopped (tty input)) @ 0 (0) --- [pid 23690] --- SIGTTIN (Stopped (tty input)) @ 0 (0) --- [pid 23691] futex(0xf84005fc28, FUTEX_WAIT, 0, NULL <unfinished ...> [pid 23690] futex(0x586678, FUTEX_WAIT, 0, NULL <unfinished ...> [pid 23689] read(4, <unfinished ...> [pid 23688] <... restart_syscall resumed> ) = ? ERESTART_RESTARTBLOCK (To be restarted) [pid 23689] <... read resumed> 0xf8400cf000, 128) = ? ERESTARTSYS (To be restarted) [pid 23688] --- SIGTTIN (Stopped (tty input)) @ 0 (0) --- [pid 23689] --- SIGTTIN (Stopped (tty input)) @ 0 (0) --- [pid 23688] restart_syscall(<... resuming interrupted call ...> <unfinished ...> [pid 23689] --- SIGTTIN (Stopped (tty input)) @ 0 (0) --- [pid 23691] <... futex resumed> ) = ? ERESTARTSYS (To be restarted) [pid 23690] <... futex resumed> ) = ? ERESTARTSYS (To be restarted) [pid 23691] --- SIGTTIN (Stopped (tty input)) @ 0 (0) --- [pid 23690] --- SIGTTIN (Stopped (tty input)) @ 0 (0) --- [pid 23691] futex(0xf84005fc28, FUTEX_WAIT, 0, NULL <unfinished ...> [pid 23690] futex(0x586678, FUTEX_WAIT, 0, NULL <unfinished ...> [pid 23689] read(4, <unfinished ...> [pid 23688] <... restart_syscall resumed> ) = ? ERESTART_RESTARTBLOCK (To be restarted) [pid 23689] <... read resumed> 0xf8400cf000, 128) = ? ERESTARTSYS (To be restarted) [pid 23688] --- SIGTTIN (Stopped (tty input)) @ 0 (0) --- [pid 23689] --- SIGTTIN (Stopped (tty input)) @ 0 (0) --- [pid 23688] restart_syscall(<... resuming interrupted call ...> <unfinished ...> [pid 23689] --- SIGTTIN (Stopped (tty input)) @ 0 (0) --- [pid 23691] <... futex resumed> ) = ? ERESTARTSYS (To be restarted) [pid 23690] <... futex resumed> ) = ? ERESTARTSYS (To be restarted) [pid 23691] --- SIGTTIN (Stopped (tty input)) @ 0 (0) --- [pid 23690] --- SIGTTIN (Stopped (tty input)) @ 0 (0) --- [pid 23691] futex(0xf84005fc28, FUTEX_WAIT, 0, NULL <unfinished ...> [pid 23690] futex(0x586678, FUTEX_WAIT, 0, NULL <unfinished ...> [pid 23689] read(4, <unfinished ...> [pid 23688] <... restart_syscall resumed> ) = ? ERESTART_RESTARTBLOCK (To be restarted) [pid 23689] <... read resumed> 0xf8400cf000, 128) = ? ERESTARTSYS (To be restarted) [pid 23688] --- SIGTTIN (Stopped (tty input)) @ 0 (0) --- [pid 23689] --- SIGTTIN (Stopped (tty input)) @ 0 (0) --- [pid 23688] restart_syscall(<... resuming interrupted call ...> <unfinished ...> [pid 23689] --- SIGTTIN (Stopped (tty input)) @ 0 (0) --- [pid 23691] <... futex resumed> ) = ? ERESTARTSYS (To be restarted) [pid 23690] <... futex resumed> ) = ? ERESTARTSYS (To be restarted) [pid 23691] --- SIGTTIN (Stopped (tty input)) @ 0 (0) --- [pid 23690] --- SIGTTIN (Stopped (tty input)) @ 0 (0) --- [pid 23691] futex(0xf84005fc28, FUTEX_WAIT, 0, NULL <unfinished ...> |
SIGTTIN is out fault actually I think. Because we should not make read attempts while the process is stopped. That's what SIGTTIN means it is a /dev/tty read attempt from a process that was stopped by SIGSTOP. There are a couple of problems as well actually. For example Go sets all the signal handlers with SA_RESTART, but frankly it would be nice to have an ability to interrupt a syscall by a signal. SIGTTIN is one the cases for that. Anyways, I think we can workaround all that if we try really hard, without bug reporting on Go a lot. :) |
Sorry for lack of updates. The SIGTTIN strace in the above is caused by the app in question having goroutines trying to still read from the tty. Every read attempt gets a SIGTTIN, and it keeps spinning there. While the app *could* be careful and stop the reading goroutines (which isn't trivial in the first place; they're blocking on .Read() currently), very few apps will have custom code to handle SIGTSTP in the first place, so I expect C-z'ing miscellaneous Go applications will have messy results. A goroutine blocking on os.Stdin.Read() oughta behave better, with no extra logic. Also, I'm not convinced the syscall.Gettid and .Tgkill hack is guaranteed to work in general; I don't think I saw anything in the ref saying goroutines can't reschedule whenever they want. The OS thread id might change, unless we do runtime.LockOSThread(), and that's really only useful for new goroutines (because we don't want to leave things locked). Not sure what would be a clean way out of this mess. |
Yuck. See also issue #4494. |
> A quick strace of a suspended godit shows threads still spinning with SIGTTIN/SIGTTOU, so that part is not resolved either. Nothing like that happens on my machine. I can only see SIGIO (since we're using that now in termbox) when godit is active (in foreground), after C-z strace shows no activity. Have you updated the termbox-go library? Try the full update: `go get -u github.com/nsf/godit`. It can't be an OS specific issue as C-z works only under linux . |
This works as expected in Go 1.5 and on tip. |
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
The text was updated successfully, but these errors were encountered: