Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
HugeYuan
delve
提交
3a8730de
D
delve
项目概览
HugeYuan
/
delve
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
delve
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
3a8730de
编写于
1月 30, 2016
作者:
A
aarzilli
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
proc: Do not panic when a command is executed on an exited process
Fixes #355
上级
fb721093
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
119 addition
and
11 deletion
+119
-11
proc/proc.go
proc/proc.go
+30
-0
service/debugger/debugger.go
service/debugger/debugger.go
+13
-6
service/rpc/server.go
service/rpc/server.go
+12
-5
service/test/integration_test.go
service/test/integration_test.go
+64
-0
未找到文件。
proc/proc.go
浏览文件 @
3a8730de
...
...
@@ -229,6 +229,9 @@ func (dbp *Process) CurrentLocation() (*Location, error) {
// RequestManualStop sets the `halt` flag and
// sends SIGSTOP to all threads.
func
(
dbp
*
Process
)
RequestManualStop
()
error
{
if
dbp
.
exited
{
return
&
ProcessExitedError
{}
}
dbp
.
halt
=
true
return
dbp
.
requestManualStop
()
}
...
...
@@ -237,6 +240,9 @@ func (dbp *Process) RequestManualStop() error {
// break point table. Setting a break point must be thread specific due to
// ptrace actions needing the thread to be in a signal-delivery-stop.
func
(
dbp
*
Process
)
SetBreakpoint
(
addr
uint64
)
(
*
Breakpoint
,
error
)
{
if
dbp
.
exited
{
return
nil
,
&
ProcessExitedError
{}
}
return
dbp
.
setBreakpoint
(
dbp
.
CurrentThread
.
ID
,
addr
,
false
)
}
...
...
@@ -247,6 +253,9 @@ func (dbp *Process) SetTempBreakpoint(addr uint64) (*Breakpoint, error) {
// ClearBreakpoint clears the breakpoint at addr.
func
(
dbp
*
Process
)
ClearBreakpoint
(
addr
uint64
)
(
*
Breakpoint
,
error
)
{
if
dbp
.
exited
{
return
nil
,
&
ProcessExitedError
{}
}
bp
,
ok
:=
dbp
.
FindBreakpoint
(
addr
)
if
!
ok
{
return
nil
,
NoBreakpointError
{
addr
:
addr
}
...
...
@@ -268,6 +277,9 @@ func (dbp *Process) Status() *WaitStatus {
// Next continues execution until the next source line.
func
(
dbp
*
Process
)
Next
()
(
err
error
)
{
if
dbp
.
exited
{
return
&
ProcessExitedError
{}
}
for
i
:=
range
dbp
.
Breakpoints
{
if
dbp
.
Breakpoints
[
i
]
.
Temp
{
return
fmt
.
Errorf
(
"next while nexting"
)
...
...
@@ -357,6 +369,9 @@ func (dbp *Process) setChanRecvBreakpoints() (int, error) {
// process. It will continue until it hits a breakpoint
// or is otherwise stopped.
func
(
dbp
*
Process
)
Continue
()
error
{
if
dbp
.
exited
{
return
&
ProcessExitedError
{}
}
for
{
if
err
:=
dbp
.
resume
();
err
!=
nil
{
return
err
...
...
@@ -498,6 +513,9 @@ func (dbp *Process) StepInstruction() (err error) {
// SwitchThread changes from current thread to the thread specified by `tid`.
func
(
dbp
*
Process
)
SwitchThread
(
tid
int
)
error
{
if
dbp
.
exited
{
return
&
ProcessExitedError
{}
}
if
th
,
ok
:=
dbp
.
Threads
[
tid
];
ok
{
dbp
.
CurrentThread
=
th
dbp
.
SelectedGoroutine
,
_
=
dbp
.
CurrentThread
.
GetG
()
...
...
@@ -509,6 +527,9 @@ func (dbp *Process) SwitchThread(tid int) error {
// SwitchGoroutine changes from current thread to the thread
// running the specified goroutine.
func
(
dbp
*
Process
)
SwitchGoroutine
(
gid
int
)
error
{
if
dbp
.
exited
{
return
&
ProcessExitedError
{}
}
g
,
err
:=
dbp
.
FindGoroutine
(
gid
)
if
err
!=
nil
{
return
err
...
...
@@ -527,6 +548,9 @@ func (dbp *Process) SwitchGoroutine(gid int) error {
// GoroutinesInfo returns an array of G structures representing the information
// Delve cares about from the internal runtime G structure.
func
(
dbp
*
Process
)
GoroutinesInfo
()
([]
*
G
,
error
)
{
if
dbp
.
exited
{
return
nil
,
&
ProcessExitedError
{}
}
if
dbp
.
allGCache
!=
nil
{
return
dbp
.
allGCache
,
nil
}
...
...
@@ -597,6 +621,9 @@ func (dbp *Process) GoroutinesInfo() ([]*G, error) {
// Halt stops all threads.
func
(
dbp
*
Process
)
Halt
()
(
err
error
)
{
if
dbp
.
exited
{
return
&
ProcessExitedError
{}
}
for
_
,
th
:=
range
dbp
.
Threads
{
if
err
:=
th
.
Halt
();
err
!=
nil
{
return
err
...
...
@@ -817,6 +844,9 @@ func (dbp *Process) FindGoroutine(gid int) (*G, error) {
// ConvertEvalScope returns a new EvalScope in the context of the
// specified goroutine ID and stack frame.
func
(
dbp
*
Process
)
ConvertEvalScope
(
gid
,
frame
int
)
(
*
EvalScope
,
error
)
{
if
dbp
.
exited
{
return
nil
,
&
ProcessExitedError
{}
}
g
,
err
:=
dbp
.
FindGoroutine
(
gid
)
if
err
!=
nil
{
return
nil
,
err
...
...
service/debugger/debugger.go
浏览文件 @
3a8730de
...
...
@@ -213,22 +213,29 @@ func (d *Debugger) FindBreakpoint(id int) *api.Breakpoint {
}
// Threads returns the threads of the target process.
func
(
d
*
Debugger
)
Threads
()
[]
*
api
.
Thread
{
func
(
d
*
Debugger
)
Threads
()
([]
*
api
.
Thread
,
error
)
{
if
d
.
process
.
Exited
()
{
return
nil
,
&
proc
.
ProcessExitedError
{}
}
threads
:=
[]
*
api
.
Thread
{}
for
_
,
th
:=
range
d
.
process
.
Threads
{
threads
=
append
(
threads
,
api
.
ConvertThread
(
th
))
}
return
threads
return
threads
,
nil
}
// FindThread returns the thread for the given 'id'.
func
(
d
*
Debugger
)
FindThread
(
id
int
)
*
api
.
Thread
{
for
_
,
thread
:=
range
d
.
Threads
()
{
func
(
d
*
Debugger
)
FindThread
(
id
int
)
(
*
api
.
Thread
,
error
)
{
threads
,
err
:=
d
.
Threads
()
if
err
!=
nil
{
return
nil
,
err
}
for
_
,
thread
:=
range
threads
{
if
thread
.
ID
==
id
{
return
thread
return
thread
,
nil
}
}
return
nil
return
nil
,
nil
}
// Command handles commands which control the debugger lifecycle
...
...
service/rpc/server.go
浏览文件 @
3a8730de
...
...
@@ -162,13 +162,16 @@ func (s *RPCServer) ClearBreakpoint(id int, breakpoint *api.Breakpoint) error {
return
nil
}
func
(
s
*
RPCServer
)
ListThreads
(
arg
interface
{},
threads
*
[]
*
api
.
Thread
)
error
{
*
threads
=
s
.
debugger
.
Threads
()
return
nil
func
(
s
*
RPCServer
)
ListThreads
(
arg
interface
{},
threads
*
[]
*
api
.
Thread
)
(
err
error
)
{
*
threads
,
err
=
s
.
debugger
.
Threads
()
return
err
}
func
(
s
*
RPCServer
)
GetThread
(
id
int
,
thread
*
api
.
Thread
)
error
{
t
:=
s
.
debugger
.
FindThread
(
id
)
t
,
err
:=
s
.
debugger
.
FindThread
(
id
)
if
err
!=
nil
{
return
err
}
if
t
==
nil
{
return
fmt
.
Errorf
(
"no thread with id %d"
,
id
)
}
...
...
@@ -201,7 +204,11 @@ type ThreadListArgs struct {
}
func
(
s
*
RPCServer
)
ListThreadPackageVars
(
args
*
ThreadListArgs
,
variables
*
[]
api
.
Variable
)
error
{
if
thread
:=
s
.
debugger
.
FindThread
(
args
.
Id
);
thread
==
nil
{
thread
,
err
:=
s
.
debugger
.
FindThread
(
args
.
Id
)
if
err
!=
nil
{
return
err
}
if
thread
==
nil
{
return
fmt
.
Errorf
(
"no thread with id %d"
,
args
.
Id
)
}
...
...
service/test/integration_test.go
浏览文件 @
3a8730de
...
...
@@ -28,6 +28,14 @@ func assertNoError(err error, t *testing.T, s string) {
}
}
func
assertError
(
err
error
,
t
*
testing
.
T
,
s
string
)
{
if
err
==
nil
{
_
,
file
,
line
,
_
:=
runtime
.
Caller
(
1
)
fname
:=
filepath
.
Base
(
file
)
t
.
Fatalf
(
"failed assertion at %s:%d: %s (no error)
\n
"
,
fname
,
line
,
s
)
}
}
func
TestMain
(
m
*
testing
.
M
)
{
os
.
Exit
(
protest
.
RunTestsWithFixtures
(
m
))
}
...
...
@@ -734,3 +742,59 @@ func TestClientServer_FullStacktrace(t *testing.T) {
}
})
}
func
TestIssue355
(
t
*
testing
.
T
)
{
// After the target process has terminated should return an error but not crash
withTestClient
(
"continuetestprog"
,
t
,
func
(
c
service
.
Client
)
{
bp
,
err
:=
c
.
CreateBreakpoint
(
&
api
.
Breakpoint
{
FunctionName
:
"main.sayhi"
,
Line
:
-
1
})
assertNoError
(
err
,
t
,
"CreateBreakpoint()"
)
ch
:=
c
.
Continue
()
state
:=
<-
ch
tid
:=
state
.
CurrentThread
.
ID
gid
:=
state
.
SelectedGoroutine
.
ID
assertNoError
(
state
.
Err
,
t
,
"First Continue()"
)
ch
=
c
.
Continue
()
state
=
<-
ch
if
!
state
.
Exited
{
t
.
Fatalf
(
"Target did not terminate after second continue"
)
}
ch
=
c
.
Continue
()
state
=
<-
ch
assertError
(
state
.
Err
,
t
,
"Continue()"
)
_
,
err
=
c
.
Next
()
assertError
(
err
,
t
,
"Next()"
)
_
,
err
=
c
.
Step
()
assertError
(
err
,
t
,
"Step()"
)
_
,
err
=
c
.
StepInstruction
()
assertError
(
err
,
t
,
"StepInstruction()"
)
_
,
err
=
c
.
SwitchThread
(
tid
)
assertError
(
err
,
t
,
"SwitchThread()"
)
_
,
err
=
c
.
SwitchGoroutine
(
gid
)
assertError
(
err
,
t
,
"SwitchGoroutine()"
)
_
,
err
=
c
.
Halt
()
assertError
(
err
,
t
,
"Halt()"
)
_
,
err
=
c
.
CreateBreakpoint
(
&
api
.
Breakpoint
{
FunctionName
:
"main.main"
,
Line
:
-
1
})
assertError
(
err
,
t
,
"CreateBreakpoint()"
)
_
,
err
=
c
.
ClearBreakpoint
(
bp
.
ID
)
assertError
(
err
,
t
,
"ClearBreakpoint()"
)
_
,
err
=
c
.
ListThreads
()
assertError
(
err
,
t
,
"ListThreads()"
)
_
,
err
=
c
.
GetThread
(
tid
)
assertError
(
err
,
t
,
"GetThread()"
)
assertError
(
c
.
SetVariable
(
api
.
EvalScope
{
gid
,
0
},
"a"
,
"10"
),
t
,
"SetVariable()"
)
_
,
err
=
c
.
ListLocalVariables
(
api
.
EvalScope
{
gid
,
0
})
assertError
(
err
,
t
,
"ListLocalVariables()"
)
_
,
err
=
c
.
ListFunctionArgs
(
api
.
EvalScope
{
gid
,
0
})
assertError
(
err
,
t
,
"ListFunctionArgs()"
)
_
,
err
=
c
.
ListRegisters
()
assertError
(
err
,
t
,
"ListRegisters()"
)
_
,
err
=
c
.
ListGoroutines
()
assertError
(
err
,
t
,
"ListGoroutines()"
)
_
,
err
=
c
.
Stacktrace
(
gid
,
10
,
false
)
assertError
(
err
,
t
,
"Stacktrace()"
)
_
,
err
=
c
.
FindLocation
(
api
.
EvalScope
{
gid
,
0
},
"+1"
)
assertError
(
err
,
t
,
"FindLocation()"
)
})
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录