proc/gdbserial: fix redirect bugs with debugserver

1. Forward stdin/stdout/stderr to the target process when in foreground
   mode instead of always forwarding the current tty (issue #1964)
2. When redirecting a file descriptor make sure to also specify
   something for all three otherwise debugserver will misbehave (either
   exit on launch or run but giving the target process a closed file
   descriptor).

Fixes #1964
This commit is contained in:
aarzilli 2020-11-09 09:31:12 +01:00 committed by Alessandro Arzilli
parent 4f03ef0bc4
commit 6ab6929b9a
3 changed files with 61 additions and 20 deletions

15
_fixtures/cat.go Normal file

@ -0,0 +1,15 @@
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
s := bufio.NewScanner(os.Stdin)
for s.Scan() {
fmt.Printf("read %q\n", s.Text())
}
os.Stdout.Close()
}

@ -296,6 +296,38 @@ func TestChildProcessExitWhenNoDebugInfo(t *testing.T) {
}
}
// TestRedirect verifies that redirecting stdin works
func TestRedirect(t *testing.T) {
const listenAddr = "127.0.0.1:40573"
dlvbin, tmpdir := getDlvBin(t)
defer os.RemoveAll(tmpdir)
catfixture := filepath.Join(protest.FindFixturesDir(), "cat.go")
cmd := exec.Command(dlvbin, "debug", "--headless", "--continue", "--accept-multiclient", "--listen", listenAddr, "-r", catfixture, catfixture)
stdout, err := cmd.StdoutPipe()
assertNoError(err, t, "stderr pipe")
defer stdout.Close()
assertNoError(cmd.Start(), t, "start headless instance")
scan := bufio.NewScanner(stdout)
// wait for the debugger to start
for scan.Scan() {
t.Log(scan.Text())
if scan.Text() == "read \"}\"" {
break
}
}
// and detach from and kill the headless instance
client := rpc2.NewClient(listenAddr)
if err := client.Detach(true); err != nil {
t.Fatalf("error detaching from headless instance: %v", err)
}
cmd.Wait()
}
func checkAutogenDoc(t *testing.T, filename, gencommand string, generated []byte) {
saved := slurpFile(t, filepath.Join(projectRoot(), filename))

@ -349,20 +349,13 @@ func LLDBLaunch(cmd []string, wd string, flags proc.LaunchFlags, debugInfoDirs [
foreground := flags&proc.LaunchForeground != 0
if foreground {
// Disable foregrounding if we can't open /dev/tty or debugserver will
// crash. See issue #1215.
if !isatty.IsTerminal(os.Stdin.Fd()) {
foreground = false
}
}
var (
isDebugserver bool
listener net.Listener
port string
process *exec.Cmd
err error
hasRedirects bool
)
if debugserverExecutable := getDebugServerAbsolutePath(); debugserverExecutable != "" {
@ -382,18 +375,15 @@ func LLDBLaunch(cmd []string, wd string, flags proc.LaunchFlags, debugInfoDirs [
for i := range redirects {
if redirects[i] != "" {
found[i] = true
hasRedirects = true
args = append(args, fmt.Sprintf("--%s-path", names[i]), redirects[i])
}
}
if foreground {
if !found[0] && !found[1] && !found[2] {
args = append(args, "--stdio-path", "/dev/tty")
} else {
if foreground || hasRedirects {
for i := range found {
if !found[i] {
args = append(args, fmt.Sprintf("--%s-path", names[i]), "/dev/tty")
}
args = append(args, fmt.Sprintf("--%s-path", names[i]), "/dev/"+names[i])
}
}
}
@ -423,19 +413,23 @@ func LLDBLaunch(cmd []string, wd string, flags proc.LaunchFlags, debugInfoDirs [
process = commandLogger("lldb-server", args...)
}
if logflags.LLDBServerOutput() || logflags.GdbWire() || foreground {
if logflags.LLDBServerOutput() || logflags.GdbWire() || foreground || hasRedirects {
process.Stdout = os.Stdout
process.Stderr = os.Stderr
}
if foreground {
if foreground || hasRedirects {
if isatty.IsTerminal(os.Stdin.Fd()) {
foregroundSignalsIgnore()
}
process.Stdin = os.Stdin
}
if wd != "" {
process.Dir = wd
}
if isatty.IsTerminal(os.Stdin.Fd()) {
process.SysProcAttr = sysProcAttr(foreground)
}
if runtime.GOOS == "darwin" {
process.Env = proc.DisableAsyncPreemptEnv()