Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
avocado
提交
1445c82f
A
avocado
项目概览
openeuler
/
avocado
通知
0
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
A
avocado
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
1445c82f
编写于
7月 29, 2015
作者:
L
Lukáš Doktor
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #732 from lmr/proposal-ctrl-c-handling
avocado.core.runner: Do better Ctrl+C handling
上级
418a80f4
c400b2f4
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
76 addition
and
67 deletion
+76
-67
avocado/core/runner.py
avocado/core/runner.py
+76
-67
未找到文件。
avocado/core/runner.py
浏览文件 @
1445c82f
...
...
@@ -52,6 +52,7 @@ class TestRunner(object):
"""
self
.
job
=
job
self
.
result
=
test_result
self
.
current_test_subprocess
=
None
def
_run_test
(
self
,
test_factory
,
queue
):
"""
...
...
@@ -134,6 +135,8 @@ class TestRunner(object):
proc
=
multiprocessing
.
Process
(
target
=
self
.
_run_test
,
args
=
(
test_factory
,
queue
,))
self
.
current_test_subprocess
=
proc
cycle_timeout
=
1
time_started
=
time
.
time
()
test_state
=
None
...
...
@@ -160,61 +163,30 @@ class TestRunner(object):
else
:
deadline
=
test_deadline
ctrl_c_count
=
0
ignore_window
=
2.0
ignore_time_started
=
time
.
time
()
stage_1_msg_displayed
=
False
stage_2_msg_displayed
=
False
first
=
0.01
step
=
0.1
while
True
:
try
:
if
time
.
time
()
>=
deadline
:
os
.
kill
(
proc
.
pid
,
signal
.
SIGUSR1
)
if
time
.
time
()
>=
deadline
:
os
.
kill
(
proc
.
pid
,
signal
.
SIGUSR1
)
break
wait
.
wait_for
(
lambda
:
not
queue
.
empty
()
or
not
proc
.
is_alive
(),
cycle_timeout
,
first
,
step
)
if
not
queue
.
empty
():
test_state
=
queue
.
get
()
if
not
test_state
[
'running'
]:
break
wait
.
wait_for
(
lambda
:
not
queue
.
empty
()
or
not
proc
.
is_alive
(),
cycle_timeout
,
first
,
step
)
if
not
queue
.
empty
():
test_state
=
queue
.
get
()
if
not
test_state
[
'running'
]:
break
else
:
self
.
job
.
result_proxy
.
notify_progress
(
True
)
if
test_state
[
'paused'
]:
msg
=
test_state
[
'paused_msg'
]
if
msg
:
self
.
job
.
view
.
notify
(
event
=
'partial'
,
msg
=
msg
)
elif
proc
.
is_alive
():
if
ctrl_c_count
==
0
:
self
.
job
.
result_proxy
.
notify_progress
()
else
:
break
except
KeyboardInterrupt
:
time_elapsed
=
time
.
time
()
-
ignore_time_started
ctrl_c_count
+=
1
if
ctrl_c_count
==
2
:
if
not
stage_1_msg_displayed
:
k_msg_1
=
(
"SIGINT sent to tests, waiting for their "
"reaction"
)
k_msg_2
=
(
"Ignoring Ctrl+C during the next "
"%d seconds so they can try to finish"
%
ignore_window
)
k_msg_3
=
(
"A new Ctrl+C sent after that will send a "
"SIGKILL to them"
)
self
.
job
.
view
.
notify
(
event
=
'message'
,
msg
=
k_msg_1
)
self
.
job
.
view
.
notify
(
event
=
'message'
,
msg
=
k_msg_2
)
self
.
job
.
view
.
notify
(
event
=
'message'
,
msg
=
k_msg_3
)
stage_1_msg_displayed
=
True
ignore_time_started
=
time
.
time
()
if
(
ctrl_c_count
>
2
)
and
(
time_elapsed
>
ignore_window
):
if
not
stage_2_msg_displayed
:
k_msg_3
=
(
"Ctrl+C received after the ignore window. "
"Killing all active tests"
)
self
.
job
.
view
.
notify
(
event
=
'message'
,
msg
=
k_msg_3
)
stage_2_msg_displayed
=
True
os
.
kill
(
proc
.
pid
,
signal
.
SIGKILL
)
self
.
job
.
result_proxy
.
notify_progress
(
True
)
if
test_state
[
'paused'
]:
msg
=
test_state
[
'paused_msg'
]
if
msg
:
self
.
job
.
view
.
notify
(
event
=
'partial'
,
msg
=
msg
)
elif
proc
.
is_alive
():
self
.
job
.
result_proxy
.
notify_progress
()
else
:
break
# If test_state is None, the test was aborted before it ended.
if
test_state
is
None
:
...
...
@@ -229,16 +201,10 @@ class TestRunner(object):
'Test aborted unexpectedly'
,
test_state
[
'name'
])
# don't process other tests from the list
if
ctrl_c_count
>
0
:
self
.
job
.
view
.
notify
(
event
=
'minor'
,
msg
=
''
)
self
.
result
.
check_test
(
test_state
)
if
not
status
.
mapping
[
test_state
[
'status'
]]:
failures
.
append
(
test_state
[
'name'
])
if
ctrl_c_count
>
0
:
return
False
return
True
def
run_suite
(
self
,
test_suite
,
mux
,
timeout
=
0
):
...
...
@@ -250,6 +216,44 @@ class TestRunner(object):
:param timeout: maximum amount of time (in seconds) to execute.
:return: a list of test failures.
"""
def
wait_and_ignore_interrupt
(
ignore_window
=
2.0
):
try
:
signal
.
signal
(
signal
.
SIGINT
,
signal
.
SIG_IGN
)
self
.
job
.
view
.
notify
(
event
=
'minor'
,
msg
=
''
)
self
.
job
.
view
.
notify
(
event
=
'message'
,
msg
=
(
'Interrupt requested. Waiting %d '
'seconds for test to finish '
'(ignoring new Ctrl+C until then)'
%
ignore_window
))
end_time
=
time
.
time
()
+
ignore_window
while
time
.
time
()
<
end_time
:
if
not
self
.
current_test_subprocess
.
is_alive
():
return
time
.
sleep
(
1.0
)
finally
:
return
def
kill_test_subprocess
(
signum
,
frame
):
try
:
self
.
job
.
view
.
notify
(
event
=
'minor'
,
msg
=
''
)
self
.
job
.
view
.
notify
(
event
=
'message'
,
msg
=
(
'Killing test subprocess PID %s'
%
self
.
current_test_subprocess
.
pid
))
os
.
kill
(
self
.
current_test_subprocess
.
pid
,
signal
.
SIGKILL
)
except
OSError
:
pass
def
clean_test_subprocess
():
try
:
signal
.
signal
(
signal
.
SIGINT
,
kill_test_subprocess
)
if
self
.
current_test_subprocess
.
is_alive
():
self
.
job
.
view
.
notify
(
event
=
'message'
,
msg
=
(
'Test still active. Press '
'Ctrl+C to kill it'
))
except
(
OSError
,
AssertionError
):
pass
failures
=
[]
if
self
.
job
.
sysinfo
is
not
None
:
self
.
job
.
sysinfo
.
start_job_hook
()
...
...
@@ -262,18 +266,23 @@ class TestRunner(object):
deadline
=
None
for
test_template
in
test_suite
:
test_template
[
1
][
'base_logdir'
]
=
self
.
job
.
logdir
test_template
[
1
][
'job'
]
=
self
.
job
for
test_factory
in
mux
.
itertests
(
test_template
):
if
deadline
is
not
None
and
time
.
time
()
>
deadline
:
test_parameters
=
test_factory
[
1
]
if
'methodName'
in
test_parameters
:
del
test_parameters
[
'methodName'
]
test_factory
=
(
test
.
TimeOutSkipTest
,
test_parameters
)
self
.
run_test
(
test_factory
,
queue
,
failures
)
else
:
if
not
self
.
run_test
(
test_factory
,
queue
,
failures
,
deadline
):
break
try
:
test_template
[
1
][
'base_logdir'
]
=
self
.
job
.
logdir
test_template
[
1
][
'job'
]
=
self
.
job
for
test_factory
in
mux
.
itertests
(
test_template
):
if
deadline
is
not
None
and
time
.
time
()
>
deadline
:
test_parameters
=
test_factory
[
1
]
if
'methodName'
in
test_parameters
:
del
test_parameters
[
'methodName'
]
test_factory
=
(
test
.
TimeOutSkipTest
,
test_parameters
)
self
.
run_test
(
test_factory
,
queue
,
failures
)
else
:
if
not
self
.
run_test
(
test_factory
,
queue
,
failures
,
deadline
):
break
except
KeyboardInterrupt
:
wait_and_ignore_interrupt
(
ignore_window
=
3.0
)
clean_test_subprocess
()
break
runtime
.
CURRENT_TEST
=
None
self
.
result
.
end_tests
()
if
self
.
job
.
sysinfo
is
not
None
:
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录