Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
avocado
提交
a94ad29d
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,发现更多精彩内容 >>
提交
a94ad29d
编写于
8月 22, 2014
作者:
L
Lucas Meneghel Rodrigues
提交者:
Lucas Meneghel Rodrigues
8月 22, 2014
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #158 from lmr/ctrl-c-improvements-last
Ctrl c improvements last
上级
93fee768
b4a2b7a9
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
107 addition
and
86 deletion
+107
-86
avocado/job.py
avocado/job.py
+40
-39
avocado/utils/process.py
avocado/utils/process.py
+66
-43
selftests/all/functional/avocado/basic_tests.py
selftests/all/functional/avocado/basic_tests.py
+0
-1
tests/trinity.py
tests/trinity.py
+1
-3
未找到文件。
avocado/job.py
浏览文件 @
a94ad29d
...
...
@@ -135,14 +135,8 @@ class TestRunner(object):
raise
exceptions
.
TestTimeoutError
(
e_msg
)
def
interrupt_handler
(
signum
,
frame
):
instance
.
status
=
exceptions
.
TestInterruptedError
.
status
instance
.
fail_class
=
exceptions
.
TestInterruptedError
.
__class__
.
__name__
e_msg
=
'Interrupted by user'
instance
.
fail_reason
=
exceptions
.
TestInterruptedError
(
e_msg
)
instance
.
traceback
=
'Traceback not available'
with
open
(
instance
.
logfile
,
'r'
)
as
log_file_obj
:
instance
.
text_output
=
log_file_obj
.
read
()
sys
.
exit
(
error_codes
.
numeric_status
[
'AVOCADO_JOB_INTERRUPTED'
])
e_msg
=
"Test %s interrupted by user"
%
instance
raise
exceptions
.
TestTimeoutError
(
e_msg
)
signal
.
signal
(
signal
.
SIGUSR1
,
timeout_handler
)
signal
.
signal
(
signal
.
SIGINT
,
interrupt_handler
)
...
...
@@ -200,6 +194,12 @@ class TestRunner(object):
time_deadline
=
time_started
+
timeout
ctrl_c_count
=
0
ignore_window
=
2.0
ignore_time_started
=
time
.
time
()
stage_1_msg_displayed
=
False
stage_2_msg_displayed
=
False
while
True
:
try
:
if
time
.
time
()
>=
time_deadline
:
...
...
@@ -216,10 +216,37 @@ class TestRunner(object):
except
Queue
.
Empty
:
if
p
.
is_alive
():
self
.
job
.
result_proxy
.
throbber_progress
()
if
ctrl_c_count
==
0
:
self
.
job
.
result_proxy
.
throbber_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
.
output_manager
.
log_header
(
"
\n
"
)
self
.
job
.
output_manager
.
log_header
(
k_msg_1
)
self
.
job
.
output_manager
.
log_header
(
k_msg_2
)
self
.
job
.
output_manager
.
log_header
(
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
.
output_manager
.
log_header
(
k_msg_3
)
stage_2_msg_displayed
=
True
os
.
kill
(
p
.
pid
,
signal
.
SIGKILL
)
# If test_state is None, the test was aborted before it ended.
if
test_state
is
None
:
try
:
...
...
@@ -227,10 +254,10 @@ class TestRunner(object):
except
Queue
.
Empty
:
early_state
[
'time_elapsed'
]
=
time
.
time
()
-
time_started
test_state
=
self
.
_fill_aborted_test_state
(
early_state
)
test_log
=
logging
.
getLogger
(
'avocado.test'
)
test_log
.
error
(
'ERROR %s -> TestAbortedError: '
'Test aborted unexpectedly'
,
test_state
[
'name'
])
test_log
=
logging
.
getLogger
(
'avocado.test'
)
test_log
.
error
(
'ERROR %s -> TestAbortedError: '
'Test aborted unexpectedly'
,
test_state
[
'name'
])
self
.
result
.
check_test
(
test_state
)
if
not
status
.
mapping
[
test_state
[
'status'
]]:
...
...
@@ -471,32 +498,6 @@ class Job(object):
except
exceptions
.
OptionValidationError
,
details
:
self
.
output_manager
.
log_fail_header
(
str
(
details
))
return
error_codes
.
numeric_status
[
'AVOCADO_JOB_FAIL'
]
except
KeyboardInterrupt
:
kill_prompt_displayed
=
False
time_elapsed
=
0
ignore_window
=
2.0
self
.
output_manager
.
log_header
(
'
\n
'
)
self
.
output_manager
.
log_header
(
'Interrupted by user request'
)
start_time
=
time
.
time
()
while
multiprocessing
.
active_children
():
time_elapsed
=
time
.
time
()
-
start_time
try
:
time
.
sleep
(
0.1
)
except
KeyboardInterrupt
:
if
not
kill_prompt_displayed
:
k_msg
=
(
'Waiting for tests to end. Ignoring Ctrl+C '
'for %d seconds'
%
ignore_window
)
self
.
output_manager
.
log_header
(
k_msg
)
k_msg
=
(
'After that, a new Ctrl+C will send a SIGKILL '
'to them'
)
self
.
output_manager
.
log_header
(
k_msg
)
kill_prompt_displayed
=
True
if
time_elapsed
<
ignore_window
:
continue
else
:
for
child
in
multiprocessing
.
active_children
():
os
.
kill
(
child
.
pid
,
signal
.
SIGKILL
)
sys
.
exit
(
error_codes
.
numeric_status
[
'AVOCADO_JOB_INTERRUPTED'
])
except
Exception
,
details
:
self
.
status
=
"ERROR"
...
...
avocado/utils/process.py
浏览文件 @
a94ad29d
...
...
@@ -20,7 +20,6 @@ import logging
import
os
import
StringIO
import
signal
import
shlex
import
subprocess
import
time
import
threading
...
...
@@ -117,13 +116,14 @@ class SubProcess(object):
:param verbose: Whether to log the command run and stdout/stderr.
:type verbose: bool
"""
args
=
shlex
.
split
(
cmd
)
self
.
cmd
=
cmd
self
.
verbose
=
verbose
if
self
.
verbose
:
log
.
info
(
"Running '%s'"
,
cmd
)
self
.
sp
=
subprocess
.
Popen
(
args
,
self
.
sp
=
subprocess
.
Popen
(
cmd
,
stdout
=
subprocess
.
PIPE
,
stderr
=
subprocess
.
PIPE
)
stderr
=
subprocess
.
PIPE
,
shell
=
True
)
self
.
start_time
=
time
.
time
()
self
.
result
=
CmdResult
(
cmd
)
self
.
stdout_file
=
StringIO
.
StringIO
()
...
...
@@ -141,6 +141,17 @@ class SubProcess(object):
self
.
stdout_thread
.
start
()
self
.
stderr_thread
.
start
()
def
signal_handler
(
signum
,
frame
):
self
.
wait
()
signal
.
signal
(
signal
.
SIGINT
,
signal_handler
)
def
__str__
(
self
):
if
self
.
result
.
exit_status
is
None
:
rc
=
'(still running)'
else
:
rc
=
self
.
result
.
exit_status
return
'SubProcess(cmd="%s", rc="%s")'
%
(
self
.
cmd
,
rc
)
def
_fd_drainer
(
self
,
input_pipe
):
"""
Read from input_pipe, storing and logging output.
...
...
@@ -175,6 +186,25 @@ class SubProcess(object):
finally
:
lock
.
release
()
def
_fill_results
(
self
,
rc
):
self
.
result
.
exit_status
=
rc
if
self
.
result
.
duration
==
0
:
self
.
result
.
duration
=
time
.
time
()
-
self
.
start_time
self
.
_fill_streams
()
def
_fill_streams
(
self
):
"""
Close subprocess stdout and stderr, and put values into result obj.
"""
# Cleaning up threads
self
.
stdout_thread
.
join
()
self
.
stderr_thread
.
join
()
# Clean subprocess pipes and populate stdout/err
self
.
sp
.
stdout
.
close
()
self
.
sp
.
stderr
.
close
()
self
.
result
.
stdout
=
self
.
get_stdout
()
self
.
result
.
stderr
=
self
.
get_stderr
()
def
get_stdout
(
self
):
"""
Get the full stdout of the subprocess so far.
...
...
@@ -219,7 +249,25 @@ class SubProcess(object):
"""
self
.
sp
.
send_signal
(
sig
)
def
wait
(
self
,
timeout
=
None
,
sig
=
signal
.
SIGTERM
):
def
poll
(
self
):
"""
Call the subprocess poll() method, fill results if rc is not None.
"""
rc
=
self
.
sp
.
poll
()
if
rc
is
not
None
:
self
.
_fill_results
(
rc
)
return
rc
def
wait
(
self
):
"""
Call the subprocess poll() method, fill results if rc is not None.
"""
rc
=
self
.
sp
.
wait
()
if
rc
is
not
None
:
self
.
_fill_results
(
rc
)
return
rc
def
run
(
self
,
timeout
=
None
,
sig
=
signal
.
SIGTERM
):
"""
Wait for the process to end, filling and returning the result attr.
...
...
@@ -230,59 +278,34 @@ class SubProcess(object):
:returns: The command result object.
:rtype: A :class:`avocado.utils.process.CmdResult` instance.
"""
start_time
=
time
.
time
()
if
timeout
is
None
:
self
.
sp
.
wait
()
self
.
result
.
exit_status
=
self
.
sp
.
returncode
self
.
wait
()
if
timeout
>
0
:
start_time
=
time
.
time
()
if
timeout
>
0.0
:
while
time
.
time
()
-
start_time
<
timeout
:
self
.
result
.
exit_status
=
self
.
sp
.
poll
()
self
.
poll
()
if
self
.
result
.
exit_status
is
not
None
:
break
else
:
# Give one second to check if we can successfully kill the process
timeout
=
1
if
self
.
result
.
exit_status
is
None
:
internal_timeout
=
1.0
self
.
send_signal
(
sig
)
# Timeout here should be 1 second (see comment above)
stop_time
=
time
.
time
()
+
timeout
stop_time
=
time
.
time
()
+
internal_timeout
while
time
.
time
()
<
stop_time
:
self
.
result
.
exit_status
=
self
.
sp
.
poll
()
self
.
poll
()
if
self
.
result
.
exit_status
is
not
None
:
break
else
:
self
.
kill
()
self
.
result
.
exit_status
=
self
.
sp
.
poll
()
self
.
poll
()
duration
=
time
.
time
()
-
self
.
start_time
self
.
result
.
duration
=
duration
self
.
cleanup
()
return
self
.
result
def
cleanup
(
self
):
"""
Close subprocess stdout and stderr, and put values into result obj.
"""
# Cleaning up threads
self
.
stdout_thread
.
join
(
1
)
self
.
stderr_thread
.
join
(
1
)
# Last sanity check
e_msg
=
'Stdout thread for %s is still alive'
%
self
.
sp
.
pid
assert
not
self
.
stdout_thread
.
isAlive
(),
e_msg
e_msg
=
'Stderr thread for %s is still alive'
%
self
.
sp
.
pid
assert
not
self
.
stderr_thread
.
isAlive
(),
e_msg
# If this fails, we're dealing with a zombie process
# If all this work fails, we're dealing with a zombie process.
e_msg
=
'Zombie Process %s'
%
self
.
sp
.
pid
assert
self
.
result
.
exit_status
is
not
None
,
e_msg
# Clean subprocess pipes and populate stdout/err
self
.
sp
.
stdout
.
close
()
self
.
sp
.
stderr
.
close
()
self
.
result
.
stdout
=
self
.
get_stdout
()
self
.
result
.
stderr
=
self
.
get_stderr
()
return
self
.
result
def
run
(
cmd
,
timeout
=
None
,
verbose
=
True
,
ignore_status
=
False
):
...
...
@@ -305,7 +328,7 @@ def run(cmd, timeout=None, verbose=True, ignore_status=False):
:raise: :class:`avocado.core.exceptions.CmdError`, if ``ignore_status=False``.
"""
sp
=
SubProcess
(
cmd
=
cmd
,
verbose
=
verbose
)
cmd_result
=
sp
.
wait
(
timeout
=
timeout
)
cmd_result
=
sp
.
run
(
timeout
=
timeout
)
if
cmd_result
.
exit_status
!=
0
and
not
ignore_status
:
raise
exceptions
.
CmdError
(
cmd
,
sp
.
result
)
return
cmd_result
...
...
selftests/all/functional/avocado/basic_tests.py
浏览文件 @
a94ad29d
...
...
@@ -17,7 +17,6 @@
import
json
import
unittest
import
os
import
signal
import
shutil
import
time
import
sys
...
...
tests/trinity.py
浏览文件 @
a94ad29d
...
...
@@ -82,9 +82,7 @@ class trinity(test.Test):
cmd
+=
" -V "
+
self
.
params
.
victims_path
else
:
cmd
+=
" -V "
+
self
.
victims_path
cmd_result
=
process
.
run
(
cmd
)
self
.
log
.
info
(
cmd_result
)
os
.
chdir
(
self
.
cwd
)
process
.
run
(
cmd
)
if
__name__
==
"__main__"
:
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录