공개 런타임 빌드 종료 판정을 보강
This commit is contained in:
parent
471eb9621a
commit
44b7835ce3
2 changed files with 84 additions and 2 deletions
|
|
@ -1574,6 +1574,10 @@ if (!$SkipWebRestart) {
|
||||||
-WorkingDirectory $WebDir `
|
-WorkingDirectory $WebDir `
|
||||||
-NoNewWindow `
|
-NoNewWindow `
|
||||||
-PassThru
|
-PassThru
|
||||||
|
# Windows PowerShell 5.1의 Start-Process -PassThru는 Process.Handle을 먼저
|
||||||
|
# 열지 않으면 timed WaitForExit 뒤에도 ExitCode가 $null로 남을 수 있다.
|
||||||
|
# 성공한 빌드를 실패로 오판하지 않도록 핸들을 대기 전에 확보한다.
|
||||||
|
$null = $build.Handle
|
||||||
if (-not $build.WaitForExit($WebBuildTimeoutSeconds * 1000)) {
|
if (-not $build.WaitForExit($WebBuildTimeoutSeconds * 1000)) {
|
||||||
$null = @(
|
$null = @(
|
||||||
Stop-ProcessTreeBounded `
|
Stop-ProcessTreeBounded `
|
||||||
|
|
@ -1584,6 +1588,9 @@ if (!$SkipWebRestart) {
|
||||||
throw "Web build timed out after $WebBuildTimeoutSeconds seconds"
|
throw "Web build timed out after $WebBuildTimeoutSeconds seconds"
|
||||||
}
|
}
|
||||||
$build.Refresh()
|
$build.Refresh()
|
||||||
|
if ($null -eq $build.ExitCode) {
|
||||||
|
throw "Web build exit code is unavailable"
|
||||||
|
}
|
||||||
if ($build.ExitCode -ne 0) {
|
if ($build.ExitCode -ne 0) {
|
||||||
throw "Web build failed with exit code $($build.ExitCode)"
|
throw "Web build failed with exit code $($build.ExitCode)"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,70 @@ exit 0
|
||||||
with self.subTest(expected=expected):
|
with self.subTest(expected=expected):
|
||||||
self.assertIn(expected, PUBLIC_RUNTIME)
|
self.assertIn(expected, PUBLIC_RUNTIME)
|
||||||
|
|
||||||
|
def test_web_build_keeps_process_handle_before_timed_wait(self) -> None:
|
||||||
|
build_start = PUBLIC_RUNTIME.index(
|
||||||
|
'$build = Start-Process -FilePath "cmd.exe"'
|
||||||
|
)
|
||||||
|
handle = PUBLIC_RUNTIME.index("$null = $build.Handle", build_start)
|
||||||
|
timed_wait = PUBLIC_RUNTIME.index(
|
||||||
|
"$build.WaitForExit($WebBuildTimeoutSeconds * 1000)", handle
|
||||||
|
)
|
||||||
|
null_guard = PUBLIC_RUNTIME.index(
|
||||||
|
"if ($null -eq $build.ExitCode)", timed_wait
|
||||||
|
)
|
||||||
|
failure_check = PUBLIC_RUNTIME.index(
|
||||||
|
"if ($build.ExitCode -ne 0)", null_guard
|
||||||
|
)
|
||||||
|
self.assertLess(build_start, handle)
|
||||||
|
self.assertLess(handle, timed_wait)
|
||||||
|
self.assertLess(timed_wait, null_guard)
|
||||||
|
self.assertLess(null_guard, failure_check)
|
||||||
|
|
||||||
|
def test_web_build_exit_code_is_available_in_windows_powershell(self) -> None:
|
||||||
|
powershell = shutil.which("powershell.exe")
|
||||||
|
if powershell is None:
|
||||||
|
self.skipTest("Windows PowerShell 5.1 is not available")
|
||||||
|
|
||||||
|
with tempfile.TemporaryDirectory() as temporary_directory:
|
||||||
|
harness = Path(temporary_directory) / "process-exit-code.ps1"
|
||||||
|
harness.write_text(
|
||||||
|
"""
|
||||||
|
$process = Start-Process -FilePath 'cmd.exe' `
|
||||||
|
-ArgumentList @('/c', 'exit 0') `
|
||||||
|
-NoNewWindow `
|
||||||
|
-PassThru
|
||||||
|
$null = $process.Handle
|
||||||
|
if (-not $process.WaitForExit(10000)) { exit 2 }
|
||||||
|
$process.Refresh()
|
||||||
|
if ($null -eq $process.ExitCode) { exit 3 }
|
||||||
|
exit $process.ExitCode
|
||||||
|
""",
|
||||||
|
encoding="utf-8-sig",
|
||||||
|
)
|
||||||
|
completed = subprocess.run(
|
||||||
|
[
|
||||||
|
powershell,
|
||||||
|
"-NoLogo",
|
||||||
|
"-NoProfile",
|
||||||
|
"-NonInteractive",
|
||||||
|
"-ExecutionPolicy",
|
||||||
|
"Bypass",
|
||||||
|
"-File",
|
||||||
|
str(harness),
|
||||||
|
],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
encoding="utf-8",
|
||||||
|
errors="replace",
|
||||||
|
timeout=30,
|
||||||
|
check=False,
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
completed.returncode,
|
||||||
|
0,
|
||||||
|
msg=f"stdout={completed.stdout}\nstderr={completed.stderr}",
|
||||||
|
)
|
||||||
|
|
||||||
def test_web_build_timeout_stops_the_owned_process_tree(self) -> None:
|
def test_web_build_timeout_stops_the_owned_process_tree(self) -> None:
|
||||||
powershell = shutil.which("powershell.exe")
|
powershell = shutil.which("powershell.exe")
|
||||||
if powershell is None:
|
if powershell is None:
|
||||||
|
|
@ -129,6 +193,7 @@ $root = Start-Process -FilePath 'cmd.exe' `
|
||||||
-ArgumentList @('/c', 'powershell.exe -NoProfile -ExecutionPolicy Bypass -File "{quoted_child}"') `
|
-ArgumentList @('/c', 'powershell.exe -NoProfile -ExecutionPolicy Bypass -File "{quoted_child}"') `
|
||||||
-WindowStyle Hidden `
|
-WindowStyle Hidden `
|
||||||
-PassThru
|
-PassThru
|
||||||
|
$childProcessId = $null
|
||||||
try {{
|
try {{
|
||||||
$deadline = (Get-Date).AddSeconds(10)
|
$deadline = (Get-Date).AddSeconds(10)
|
||||||
while (-not (Test-Path -LiteralPath '{quoted_child_pid_for_harness}') -and (Get-Date) -lt $deadline) {{
|
while (-not (Test-Path -LiteralPath '{quoted_child_pid_for_harness}') -and (Get-Date) -lt $deadline) {{
|
||||||
|
|
@ -137,11 +202,21 @@ try {{
|
||||||
if (-not (Test-Path -LiteralPath '{quoted_child_pid_for_harness}')) {{ exit 2 }}
|
if (-not (Test-Path -LiteralPath '{quoted_child_pid_for_harness}')) {{ exit 2 }}
|
||||||
$childProcessId = [int](Get-Content -LiteralPath '{quoted_child_pid_for_harness}' -Raw)
|
$childProcessId = [int](Get-Content -LiteralPath '{quoted_child_pid_for_harness}' -Raw)
|
||||||
$stopped = @(Stop-ProcessTreeBounded -RootProcessId $root.Id -TimeoutSec 10 -Role 'test tree')
|
$stopped = @(Stop-ProcessTreeBounded -RootProcessId $root.Id -TimeoutSec 10 -Role 'test tree')
|
||||||
if ($null -ne (Get-Process -Id $root.Id -ErrorAction SilentlyContinue)) {{ exit 3 }}
|
$exitDeadline = (Get-Date).AddSeconds(10)
|
||||||
if ($null -ne (Get-Process -Id $childProcessId -ErrorAction SilentlyContinue)) {{ exit 4 }}
|
do {{
|
||||||
|
$rootAlive = $null -ne (Get-Process -Id $root.Id -ErrorAction SilentlyContinue)
|
||||||
|
$childAlive = $null -ne (Get-Process -Id $childProcessId -ErrorAction SilentlyContinue)
|
||||||
|
if (-not $rootAlive -and -not $childAlive) {{ break }}
|
||||||
|
Start-Sleep -Milliseconds 200
|
||||||
|
}} while ((Get-Date) -lt $exitDeadline)
|
||||||
|
if ($rootAlive) {{ exit 3 }}
|
||||||
|
if ($childAlive) {{ exit 4 }}
|
||||||
exit 0
|
exit 0
|
||||||
}} finally {{
|
}} finally {{
|
||||||
Stop-Process -Id $root.Id -Force -ErrorAction SilentlyContinue
|
Stop-Process -Id $root.Id -Force -ErrorAction SilentlyContinue
|
||||||
|
if ($null -ne $childProcessId) {{
|
||||||
|
Stop-Process -Id $childProcessId -Force -ErrorAction SilentlyContinue
|
||||||
|
}}
|
||||||
}}
|
}}
|
||||||
''',
|
''',
|
||||||
encoding="utf-8-sig",
|
encoding="utf-8-sig",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue