提交 98a4ff7a 编写于 作者: A Alessandro Arzilli 提交者: Derek Parker

terminal: bugfix: deref of nil SelectedGoroutine switching goroutines (#829)

If CurrentThread isn't running a goroutine SelectedGoroutine can be
nil, do not blindly dereference it.

Fixes #827
上级 f6091694
package main
import (
"fmt"
"log"
"net/http"
"sync"
)
func main() {
http.HandleFunc("/test", func(w http.ResponseWriter, req *http.Request) {
go func() {
// I know this is wrong, it is just to simulate a deadlocked goroutine
fmt.Println("locking...")
mtx := &sync.Mutex{}
mtx.Lock()
mtx.Lock()
fmt.Println("will never print this")
}()
})
log.Fatalln(http.ListenAndServe("127.0.0.1:8888", nil))
}
......@@ -473,6 +473,13 @@ func goroutines(t *Term, ctx callContext, argstr string) error {
return nil
}
func selectedGID(state *api.DebuggerState) int {
if state.SelectedGoroutine == nil {
return 0
}
return state.SelectedGoroutine.ID
}
func (c *Commands) goroutine(t *Term, ctx callContext, argstr string) error {
args := strings.SplitN(argstr, " ", 2)
......@@ -505,7 +512,7 @@ func (c *Commands) goroutine(t *Term, ctx callContext, argstr string) error {
return err
}
fmt.Printf("Switched from %d to %d (thread %d)\n", oldState.SelectedGoroutine.ID, gid, newState.CurrentThread.ID)
fmt.Printf("Switched from %d to %d (thread %d)\n", selectedGID(oldState), gid, newState.CurrentThread.ID)
return nil
}
......
......@@ -5,12 +5,14 @@ import (
"fmt"
"io/ioutil"
"net"
"net/http"
"os"
"path/filepath"
"regexp"
"strconv"
"strings"
"testing"
"time"
"github.com/derekparker/delve/pkg/proc/test"
"github.com/derekparker/delve/service"
......@@ -38,6 +40,8 @@ type FakeTerminal struct {
t testing.TB
}
const logCommandOutput = false
func (ft *FakeTerminal) Exec(cmdstr string) (outstr string, err error) {
outfh, err := ioutil.TempFile("", "cmdtestout")
if err != nil {
......@@ -54,6 +58,9 @@ func (ft *FakeTerminal) Exec(cmdstr string) (outstr string, err error) {
ft.t.Fatalf("could not read temporary output file: %v", err)
}
outstr = string(outbs)
if logCommandOutput {
ft.t.Logf("command %q -> %q", cmdstr, outstr)
}
os.Remove(outfh.Name())
}()
err = ft.cmds.Call(cmdstr, ft.Term)
......@@ -581,3 +588,18 @@ func TestCheckpoints(t *testing.T) {
listIsAt(t, term, "restart c1", 16, -1, -1)
})
}
func TestIssue827(t *testing.T) {
// switching goroutines when the current thread isn't running any goroutine
// causes nil pointer dereference.
withTestTerminal("notify-v2", t, func(term *FakeTerminal) {
go func() {
time.Sleep(1 * time.Second)
http.Get("http://127.0.0.1:8888/test")
time.Sleep(1 * time.Second)
term.client.Halt()
}()
term.MustExec("continue")
term.MustExec("goroutine 1")
})
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册