Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
2c53f99e
R
roslyn
项目概览
lwm1986
/
roslyn
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
roslyn
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
2c53f99e
编写于
4月 01, 2016
作者:
L
Larry Golding
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Integrate ProcessWatchdog into future branch
上级
9496d8e2
变更
11
隐藏空白更改
内联
并排
Showing
11 changed file
with
181 addition
and
27 deletion
+181
-27
BuildAndTest.proj
BuildAndTest.proj
+30
-3
build/scripts/Run-TestsWithProcessWatchdog.ps1
build/scripts/Run-TestsWithProcessWatchdog.ps1
+87
-0
cibuild.cmd
cibuild.cmd
+18
-10
src/Tools/ProcessWatchdog/ConsoleUtils.cs
src/Tools/ProcessWatchdog/ConsoleUtils.cs
+8
-2
src/Tools/ProcessWatchdog/ErrorCode.cs
src/Tools/ProcessWatchdog/ErrorCode.cs
+15
-0
src/Tools/ProcessWatchdog/ProcessTracker.cs
src/Tools/ProcessWatchdog/ProcessTracker.cs
+3
-1
src/Tools/ProcessWatchdog/ProcessWatchdog.csproj
src/Tools/ProcessWatchdog/ProcessWatchdog.csproj
+1
-0
src/Tools/ProcessWatchdog/Program.cs
src/Tools/ProcessWatchdog/Program.cs
+15
-7
src/Tools/ProcessWatchdog/Resources.Designer.cs
src/Tools/ProcessWatchdog/Resources.Designer.cs
+1
-1
src/Tools/ProcessWatchdog/Resources.resx
src/Tools/ProcessWatchdog/Resources.resx
+1
-1
src/Tools/ProcessWatchdog/ScreenShotSaver.cs
src/Tools/ProcessWatchdog/ScreenShotSaver.cs
+2
-2
未找到文件。
BuildAndTest.proj
浏览文件 @
2c53f99e
...
...
@@ -94,9 +94,36 @@
Text="Found test assemblies outside a well-known test directory:
@(MisplacedTestAssemblies, '%0a')" />
<Exec Command="$(CoreClrTestDirectory)\CoreRun.exe $(CoreClrTestDirectory)\xunit.console.netcore.exe @(CoreTestAssemblies, ' ') -parallel all -xml $(CoreClrTestDirectory)\xUnitResults\TestResults.xml" />
<Exec Command="Binaries\$(Configuration)\RunTests\RunTests.exe "$(NuGetPackageRoot)\xunit.runner.console\$(XunitVersion)\tools" $(RunTestArgs) @(TestAssemblies, ' ')" />
<PropertyGroup>
<CoreRunExe>$(CoreClrTestDirectory)\CoreRun.exe</CoreRunExe>
<CoreRunArgs>$(CoreClrTestDirectory)\xunit.console.netcore.exe @(CoreTestAssemblies, ' ') -parallel all -xml $(CoreClrTestDirectory)\xUnitResults\TestResults.xml</CoreRunArgs>
<RunTestsExe>Binaries\$(Configuration)\RunTests\RunTests.exe</RunTestsExe>
<RunTestsArgs>$(NuGetPackageRoot)\xunit.runner.console\$(XunitVersion)\tools $(RunTestArgs) @(TestAssemblies, ' ')</RunTestsArgs>
</PropertyGroup>
<Exec Condition="'$(RunProcessWatchdog)' != 'true'" Command=""$(CoreRunExe)" $(CoreRunArgs)" />
<Exec Condition="'$(RunProcessWatchdog)' != 'true'" Command=""$(RunTestsExe)" $(RunTestsArgs)" />
<PropertyGroup Condition="'$(RunProcessWatchdog)' == 'true'">
<ProcessWatchDogExe>$(OutputDirectory)\ProcessWatchdog\ProcessWatchdog.exe</ProcessWatchDogExe>
<ProcessWatchdogOutputDirectory Condition="'$(ProcessWatchdogOutputDirectory)' == ''">$(OutputDirectory)\ProcessWatchdogOutput</ProcessWatchdogOutputDirectory>
<ProcDumpExe Condition="'$(ProcDumpExe)' == ''">C:\Sysinternals\Procdump.exe</ProcDumpExe>
<!--
The time reserved for the process watchdog to kill all test processes and obtain crash
dumps from them, measure in seconds.
-->
<BufferTime>300</BufferTime>
<!--
The fully constructed command line which runs a PowerShell script that runs both the
Core CLR unit tests and the desktop unit tests under the control of the process watchdog.
-->
<RunProcessWatchdogScriptCommand>PowerShell.exe -ExecutionPolicy RemoteSigned -NoProfile .\build\scripts\Run-TestsWithProcessWatchdog.ps1 -ProcessWatchDogExe $(ProcessWatchDogExe) -ProcessWatchdogOutputDirectory $(ProcessWatchdogOutputDirectory) -ProcDumpExe $(ProcDumpExe) -CoreRunExe '$(CoreRunExe)' -CoreRunArgs '$(CoreRunArgs)' -RunTestsExe '$(RunTestsExe)' -RunTestsArgs '$(RunTestsArgs)' -BuildStartTime $(BuildStartTime) -BuildTimeLimit $(BuildTimeLimit) -BufferTime $(BufferTime)</RunProcessWatchdogScriptCommand>
</PropertyGroup>
<Exec Condition="'$(RunProcessWatchdog)' == 'true'" Command="$(RunProcessWatchdogScriptCommand)" />
</Target>
...
...
build/scripts/Run-TestsWithProcessWatchdog.ps1
0 → 100644
浏览文件 @
2c53f99e
<#
.SYNOPSIS
Run the unit tests under the control of the process watchdog.
.DESCRIPTION
This script runs the unit tests under the control of the process watchdog.
The process watchdog allows the unit tests a certain amount of time to
run. If they don't complete in the allotted time, then the watchdog
obtains memory dumps from the test process and all its descendant processes,
takes a screen shot, and kills the processes.
.PARAMETER
ProcessWatchdogExe
The path to the executable ProcessWatchdog.exe, which sets time limits on
the unit tests.
.PARAMETER
ProcessWatchdogOutputDirectory
The directory into which ProcessWatchdog.exe should write memory dumps and screen shots.
.PARAMETER
ProcDumpExe
The path to the SysInternals executable ProcDump.exe, which produces memory dumps.
.PARAMETER
CoreRunExe
The path to the executable CoreRun.exe, which runs the Core CLR unit tests.
.PARAMETER
CoreRunArgs
The arguments to be passed to CoreRun.exe.
.PARAMETER
RunTestsExe
The path to the executable RunTests.exe, which runs the desktop unit tests.
.PARAMETER
RunTestsArgs
The arguments to be passed to RunTests.exe.
.PARAMETER
BuildStartTime
The time the Jenkins build started, in the ISO 8601-compatible format YYYY-MM-DDThh:mm:ss.
.PARAMETER
BuildTimeLimit
The total time allowed for the Jenkins build, measured in minutes.
.PARAMETER
BufferTime
The time reserved for the process watchdog to kill all test processes and obtain crash
dumps from them, measure in seconds.
#>
[
CmdletBinding
()]
Param
(
[
Parameter
(
Mandatory
=
$true
)]
[
string
]
$ProcessWatchdogExe
,
[
Parameter
(
Mandatory
=
$true
)]
[
string
]
$ProcessWatchdogOutputDirectory
,
[
Parameter
(
Mandatory
=
$true
)]
[
string
]
$ProcDumpExe
,
[
Parameter
(
Mandatory
=
$true
)]
[
string
]
$CoreRunExe
,
[
Parameter
(
Mandatory
=
$true
)]
[
string
]
$CoreRunArgs
,
[
Parameter
(
Mandatory
=
$true
)]
[
string
]
$RunTestsExe
,
[
Parameter
(
Mandatory
=
$true
)]
[
string
]
$RunTestsArgs
,
[
Parameter
(
Mandatory
=
$true
)]
[
string
]
$BuildStartTime
,
[
Parameter
(
Mandatory
=
$true
)]
[
int
]
$BuildTimeLimit
,
[
Parameter
(
Mandatory
=
$true
)]
[
int
]
$BufferTime
)
Set-StrictMode
-Version
2.0
$Error
ActionPreference
=
"Stop"
$BuildStartSeconds
=
[
DateTime
]::
ParseExact
(
$BuildStartTime
,
"yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'ff"
,
[
CultureInfo
]::
InvariantCulture
)
function
Check-TimeRemaining
(
$testGroupName
)
{
$timeRemaining
=
Get-TimeRemaining
if
(
$timeRemaining
-gt
0
)
{
Write-Host
"
$timeRemaining
seconds remain to run the
$testGroupName
unit tests."
$timeRemaining
}
else
{
Write-Host
"There is no time remaining to run the
$testGroupName
unit tests."
exit
1
;
}
}
function
Get-TimeRemaining
()
{
$secondsSinceStart
=
([
DateTime
]::
Now
-
$BuildStartSeconds
)
.
TotalSeconds
[
Math
]::
Truncate
(
$BuildTimeLimit
*
60
-
$secondsSinceStart
-
$BufferTime
)
}
$timeRemaining
=
Check-TimeRemaining
"Core CLR"
&
$ProcessWatchdogExe
--executable
$CoreRunExe
--arguments
"
$CoreRunArgs
"
--time-limit
$timeRemaining
--output-folder
"
$ProcessWatchdogOutputDirectory
"
--screenshot
--procdump-path
"
$ProcDumpExe
"
$timeRemaining
=
Check-TimeRemaining
"desktop"
&
$ProcessWatchdogExe
--executable
$RunTestsExe
--arguments
"
$RunTestsArgs
"
--time-limit
$timeRemaining
--output-folder
"
$ProcessWatchdogOutputDirectory
"
--screenshot
--procdump-path
"
$ProcDumpExe
"
\ No newline at end of file
cibuild.cmd
浏览文件 @
2c53f99e
...
...
@@ -21,19 +21,27 @@ if /I "%1" == "/testDeterminism" set TestDeterminism=true&&shift&& goto :ParseAr
REM /buildTimeLimit is the time limit, measured in minutes, for the Jenkins job that runs
REM the build. The Jenkins script netci.groovy passes the time limit to this script.
REM netci.groovy does not yet pass the time limit to cibuild.cmd. We are making this
REM change to cibuild.cmd in all branches *before* modifying netci.groovy. If we didn't
REM do things in this order, we'd have to modify cibuild.cmd in *all* branches *at the
REM same time* we made the change to netci.groovy. This way, we'll be able to first
REM modify netci.groovy to pass the new parameter without causing any harm. Then we'll
REM be able go to each branch in turn, modifying cibuild.cmd and BuildAndTest.cmd to
REM actually make use of the new parameter.
if
/I
"
%
1"
==
"/buildTimeLimit"
set
BuildTimeLimit
=
%
2
&&
shift
&&
shift
&&
goto
:ParseArguments
if
/I
"
%
1"
==
"/buildTimeLimit"
set
BuildTimeLimit
=
%
2
&&
shift
&&
shift
&&
goto
:ParseArguments
call
:Usage
&&
exit
/b
1
:DoneParsing
REM This script takes the presence of the /buildTimeLimit option as an indication that it
REM should run the tests under the control of the ProcessWatchdog, which, if the tests
REM exceed the time limit, will take a screenshot, obtain memory dumps from the test
REM process and all its descendants, and shut those processes down.
REM
REM Developers building from the command line will presumably not pass /buildTimeLimit,
REM and so the tests will not run under the ProcessWatchdog.
if
not
"
%BuildTimeLimit%
"
==
""
(
set
CurrentDate
=
%date%
set
CurrentTime
=
%time
:
=
0
%
set
BuildStartTime
=
!
CurrentDate
:
~-
4
!
-
!
CurrentDate
:
~-
10
,
2
!
-
!
CurrentDate
:
~-
7
,
2
!T!
CurrentTime
!
set
RunProcessWatchdog
=
true
)
else
(
set
RunProcessWatchdog
=
false
)
call
"C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools\VsDevCmd.bat"
||
goto
:BuildFailed
powershell
-noprofile -executionPolicy
RemoteSigned
-file
"
%RoslynRoot%
\build\scripts\check-branch.ps1"
||
goto
:BuildFailed
...
...
@@ -70,7 +78,7 @@ if defined TestDeterminism (
exit
/b
0
)
msbuild
%MSBuildAdditionalCommandLineArgs%
/p
:BootstrapBuildPath
=
"
%bindir%
\Bootstrap"
BuildAndTest
.proj
/p
:Configuration
=
%BuildConfiguration%
/p
:Test
64
=
%Test6
4
%
/p
:PathMap
=
"
%RoslynRoot%
=q:\roslyn"
/p
:Feature
=
pdb
-path-determinism /fileloggerparameters
:LogFile
=
"
%bindir%
\Build.log"
;
verbosity
=
diagnostic
||
goto
:BuildFailed
msbuild
%MSBuildAdditionalCommandLineArgs%
/p
:BootstrapBuildPath
=
"
%bindir%
\Bootstrap"
BuildAndTest
.proj
/p
:Configuration
=
%BuildConfiguration%
/p
:Test
64
=
%Test6
4
%
/p
:
RunProcessWatchdog
=
%RunProcessWatchdog%
/p
:BuildStartTime
=
%BuildStartTime%
/p
:
"ProcDumpExe=
%ProcDumpExe%
"
/p
:BuildTimeLimit
=
%BuildTimeLimit%
/p
:
PathMap
=
"
%RoslynRoot%
=q:\roslyn"
/p
:Feature
=
pdb
-path-determinism /fileloggerparameters
:LogFile
=
"
%bindir%
\Build.log"
;
verbosity
=
diagnostic
||
goto
:BuildFailed
powershell
-noprofile -executionPolicy
RemoteSigned
-file
"
%RoslynRoot%
\build\scripts\check-msbuild.ps1"
"
%bindir%
\Build.log"
||
goto
:BuildFailed
call
:TerminateBuildProcesses
...
...
src/Tools/ProcessWatchdog/ConsoleUtils.cs
浏览文件 @
2c53f99e
...
...
@@ -13,14 +13,20 @@ internal static void LogMessage(string format, params object[] args)
string
.
Format
(
CultureInfo
.
CurrentCulture
,
format
,
args
));
}
internal
static
void
LogError
(
string
messageFormat
,
params
object
[]
args
)
internal
static
void
LogError
(
ErrorCode
errorCode
,
string
messageFormat
,
params
object
[]
args
)
{
string
fullMessage
=
string
.
Format
(
CultureInfo
.
Curre
ntCulture
,
CultureInfo
.
Invaria
ntCulture
,
Resources
.
ErrorFormat
,
FormatErrorCode
(
errorCode
),
string
.
Format
(
CultureInfo
.
CurrentCulture
,
messageFormat
,
args
));
Console
.
Error
.
WriteLine
(
fullMessage
);
}
private
static
string
FormatErrorCode
(
ErrorCode
errorCode
)
{
return
string
.
Format
(
CultureInfo
.
InvariantCulture
,
"PW{0:D4}"
,
(
int
)
errorCode
);
}
}
}
\ No newline at end of file
src/Tools/ProcessWatchdog/ErrorCode.cs
0 → 100644
浏览文件 @
2c53f99e
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace
ProcessWatchdog
{
internal
enum
ErrorCode
{
None
=
0
,
ProcessTimedOut
=
1
,
InvalidTimeLimit
=
2
,
InvalidPollingInterval
=
3
,
ProcDumpNotFound
=
4
,
CannotTakeScreenShotNoConsoleSession
=
5
,
CannotTakeScreenShotUnexpectedError
=
6
}
}
src/Tools/ProcessWatchdog/ProcessTracker.cs
浏览文件 @
2c53f99e
...
...
@@ -114,9 +114,11 @@ private IList<Process> GetDescendants(int processId)
{
var
descendants
=
new
List
<
Process
>();
// Don't include procdump itself in the descendants, because
// we don't want to kill procdump.
string
query
=
string
.
Format
(
CultureInfo
.
InvariantCulture
,
"SELECT * FROM Win32_Process WHERE ParentProcessId
={0}
"
,
"SELECT * FROM Win32_Process WHERE ParentProcessId
= {0} AND Name <> \"procdump.exe\"
"
,
processId
);
var
searcher
=
new
ManagementObjectSearcher
(
query
);
...
...
src/Tools/ProcessWatchdog/ProcessWatchdog.csproj
浏览文件 @
2c53f99e
...
...
@@ -30,6 +30,7 @@
</ItemGroup>
<ItemGroup>
<Compile
Include=
"ConsoleUtils.cs"
/>
<Compile
Include=
"ErrorCode.cs"
/>
<Compile
Include=
"ProcDump.cs"
/>
<Compile
Include=
"Options.cs"
/>
<Compile
Include=
"ProcessTracker.cs"
/>
...
...
src/Tools/ProcessWatchdog/Program.cs
浏览文件 @
2c53f99e
...
...
@@ -26,7 +26,7 @@ private int Run()
{
if
(
_options
.
TimeLimit
<=
0
)
{
ConsoleUtils
.
LogError
(
Resources
.
ErrorInvalidTimeLimit
,
_options
.
TimeLimit
);
ConsoleUtils
.
LogError
(
ErrorCode
.
InvalidTimeLimit
,
Resources
.
ErrorInvalidTimeLimit
,
_options
.
TimeLimit
);
return
1
;
}
...
...
@@ -34,20 +34,22 @@ private int Run()
if
(
_options
.
PollingInterval
<=
0
)
{
ConsoleUtils
.
LogError
(
Resources
.
ErrorInvalidPollingInterval
,
_options
.
PollingInterval
);
ConsoleUtils
.
LogError
(
ErrorCode
.
InvalidPollingInterval
,
Resources
.
ErrorInvalidPollingInterval
,
_options
.
PollingInterval
);
return
1
;
}
if
(!
File
.
Exists
(
_options
.
ProcDumpPath
))
{
ConsoleUtils
.
LogError
(
Resources
.
ErrorProcDumpNotFound
,
_options
.
ProcDumpPath
);
ConsoleUtils
.
LogError
(
ErrorCode
.
ProcDumpNotFound
,
Resources
.
ErrorProcDumpNotFound
,
_options
.
ProcDumpPath
);
return
1
;
}
var
processStartInfo
=
new
ProcessStartInfo
{
FileName
=
_options
.
Executable
,
Arguments
=
_options
.
Arguments
Arguments
=
_options
.
Arguments
,
CreateNoWindow
=
true
,
UseShellExecute
=
false
};
Process
parentProcess
=
Process
.
Start
(
processStartInfo
);
...
...
@@ -60,6 +62,7 @@ private int Run()
if
(
DateTime
.
Now
-
parentProcess
.
StartTime
>
_timeLimit
)
{
ConsoleUtils
.
LogError
(
ErrorCode
.
ProcessTimedOut
,
Resources
.
ErrorProcessTimedOut
,
_options
.
Executable
,
parentProcess
.
Id
,
...
...
@@ -67,7 +70,8 @@ private int Run()
if
(
_options
.
Screenshot
)
{
ScreenshotSaver
.
SaveScreen
(
_options
.
Executable
,
_options
.
OutputFolder
);
string
description
=
Path
.
GetFileNameWithoutExtension
(
_options
.
Executable
);
ScreenshotSaver
.
SaveScreen
(
description
,
_options
.
OutputFolder
);
}
processTracker
.
TerminateAll
();
...
...
@@ -90,8 +94,6 @@ private int Run()
private
static
void
Main
(
string
[]
args
)
{
Banner
();
Parser
.
Default
.
ParseArguments
<
Options
>(
args
)
.
MapResult
(
options
=>
Run
(
options
),
...
...
@@ -100,6 +102,12 @@ private static void Main(string[] args)
private
static
int
Run
(
Options
options
)
{
// Don't display the banner until after the command line parser has
// validated the arguments, because when the command line arguments are
// invalid, the command line parse itself displays an banner. In that case,
// if we displayed our banner first, you would see two of them.
Banner
();
var
program
=
new
Program
(
options
);
return
program
.
Run
();
}
...
...
src/Tools/ProcessWatchdog/Resources.Designer.cs
浏览文件 @
2c53f99e
...
...
@@ -97,7 +97,7 @@ internal class Resources {
}
/// <summary>
/// Looks up a localized string similar to Error
: {0
}.
/// Looks up a localized string similar to Error
{0}: {1
}.
/// </summary>
internal
static
string
ErrorFormat
{
get
{
...
...
src/Tools/ProcessWatchdog/Resources.resx
浏览文件 @
2c53f99e
...
...
@@ -130,7 +130,7 @@
<value>
Could not take screenshot for process {0}.
</value>
</data>
<data
name=
"ErrorFormat"
xml:space=
"preserve"
>
<value>
Error
: {0
}
</value>
<value>
Error
{0}: {1
}
</value>
</data>
<data
name=
"ErrorInvalidPollingInterval"
xml:space=
"preserve"
>
<value>
The value {0} is not a valid polling interval. Please specify the polling interval as a positive number of milliseconds.
</value>
...
...
src/Tools/ProcessWatchdog/ScreenShotSaver.cs
浏览文件 @
2c53f99e
...
...
@@ -24,12 +24,12 @@ public static void SaveScreen(string description, string outputFolder)
// System.ComponentModel.Win32Exception (0x80004005): The handle is invalid. This
// means we're not running in a console session, hence there's no UI to take a
// screenshot of. This is perfectly normal on the server.
ConsoleUtils
.
LogError
(
Resources
.
ErrorCannotTakeScreenshotNoConsoleSession
,
ex
);
ConsoleUtils
.
LogError
(
ErrorCode
.
CannotTakeScreenShotNoConsoleSession
,
Resources
.
ErrorCannotTakeScreenshotNoConsoleSession
,
ex
);
}
catch
(
Exception
ex
)
{
// This is something else, we'd better know about this.
ConsoleUtils
.
LogError
(
Resources
.
ErrorCannotTakeScreenshotUnexpectedError
,
ex
);
ConsoleUtils
.
LogError
(
ErrorCode
.
CannotTakeScreenShotUnexpectedError
,
Resources
.
ErrorCannotTakeScreenshotUnexpectedError
,
ex
);
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录