Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
changeKind: internal
packages:
- "@azure-tools/typespec-java"
---

Fix the Java emitter build intermittently hanging a full parallel `pnpm build`. The build scripts run under turbo, which puts each task in a background process group under the build's controlling terminal; when a PowerShell cmdlet (notably `Copy-Item -Recurse`) rendered `Write-Progress`, pwsh touched that terminal and the OS stopped it with SIGTTIN/SIGTTOU, hanging forever. The `.ps1` build scripts now set `$ProgressPreference = 'SilentlyContinue'`. Also make the pinned-`core/` fetch conditional (only when the commit is missing) and non-interactive (`GIT_TERMINAL_PROMPT=0`, `pwsh -NonInteractive`) to remove secondary hang/network vectors.
5 changes: 5 additions & 0 deletions packages/typespec-java/Build-Generator.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@

$ErrorActionPreference = "Stop"

# See Copy-Sources.ps1: silence progress so no cmdlet touches the controlling
# terminal from turbo's background process group (which would SIGTTIN/SIGTTOU-stop
# this process and hang the parallel build).
$ProgressPreference = "SilentlyContinue"

$packageRoot = $PSScriptRoot
$generatorRoot = Join-Path $packageRoot "generator"
$generatorPom = Join-Path $generatorRoot "pom.xml"
Expand Down
10 changes: 10 additions & 0 deletions packages/typespec-java/Copy-Sources.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@

$ErrorActionPreference = "Stop"

# Disable progress rendering. Under a full parallel `pnpm build`, turbo runs each
# task's process in its own background process group under the build's controlling
# terminal. When a cmdlet here (notably `Copy-Item -Recurse`, which emits a
# Write-Progress) renders progress, PowerShell touches that terminal from a
# background process group and the OS stops the process with SIGTTIN/SIGTTOU -- it
# never resumes, so the emitter build appears to hang forever (intermittently, and
# only for this package since it is the only one that shells out to pwsh). Silencing
# progress removes that terminal interaction entirely.
$ProgressPreference = "SilentlyContinue"

$packageRoot = $PSScriptRoot
$repoRoot = Resolve-Path (Join-Path $packageRoot ".." "..")
$coreRoot = Join-Path $repoRoot "core"
Expand Down
41 changes: 35 additions & 6 deletions packages/typespec-java/CoreCommit.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,19 @@ function Get-CoreSourceRoot {
[string] $PackageRoot
)

# Never let any git invocation below block on an interactive credential or
# host-key prompt. During a parallel `pnpm build` the emitter build runs
# headless (turbo captures its stdio / attaches a pseudo-terminal), so a git
# prompt has nowhere to read from and would hang the whole build forever --
# observed as an intermittent, Java-only build hang. Make git fail fast instead.
$env:GIT_TERMINAL_PROMPT = "0"

# Silence progress: a cmdlet rendering Write-Progress (e.g. the archive
# extraction below) touches the controlling terminal, and under turbo's
# background process group that stops this process with SIGTTIN/SIGTTOU and
# hangs the build. Scoped to this function so callers are unaffected.
$ProgressPreference = "SilentlyContinue"

$originSha = (git -C $CoreRoot rev-parse HEAD).Trim()
if ($LASTEXITCODE -ne 0) {
Write-Error "Failed to read the current SHA of the 'core' submodule at: $CoreRoot`nMake sure it is checked out (git submodule update --init --recursive)."
Expand All @@ -65,9 +78,17 @@ function Get-CoreSourceRoot {
return @{ Root = $liveRoot; TempDir = $null }
}

# Make sure the target commit is available locally (it may be newer than what
# has been fetched); ignore failure if it is already present.
git -C $CoreRoot fetch --quiet origin $targetSha 2>$null
# Make sure the target commit is available locally (the pin may be newer than
# what has been fetched). Only hit the network when the commit is genuinely
# missing: this code runs on EVERY emitter build and doc regen, and a `git
# fetch` on core/ is the only per-build network operation in the whole repo
# build, so doing it unconditionally turns any transient network/credential
# stall into a Java-only build hang. `git cat-file -e <sha>^{commit}` is a
# cheap, offline existence check.
git -C $CoreRoot cat-file -e "${targetSha}^{commit}" 2>$null
if ($LASTEXITCODE -ne 0) {
git -C $CoreRoot fetch --quiet origin $targetSha 2>$null
}

# Only move forward: use the target when it is a descendant (newer) of the
# current checkout. `merge-base --is-ancestor A B` exits 0 when A is an ancestor
Expand All @@ -85,23 +106,31 @@ function Get-CoreSourceRoot {
$tempDir = Join-Path ([System.IO.Path]::GetTempPath()) ("typespec-java-core-" + [System.Guid]::NewGuid().ToString("N"))
New-Item -ItemType Directory -Path $tempDir | Out-Null
$zipPath = Join-Path $tempDir "core.zip"
$extractDir = Join-Path $tempDir "src"
try {
# Produce a zip (not tar) and expand it with the built-in Expand-Archive:
# Produce a zip (not tar) and expand it with .NET's ZipFile.ExtractToDirectory:
# this keeps the whole flow inside PowerShell/.NET and avoids depending on an
# external `tar`, whose behavior varies by platform (notably Git for Windows'
# GNU tar treats a drive-letter path like C:\...\core.tar as a remote host).
#
# ExtractToDirectory is used instead of Expand-Archive on purpose: the archived
# subtree holds several thousand files, and Expand-Archive emits a per-entry
# Write-Progress that makes it pathologically slow on that many files (worse when
# its output is captured by a parallel `pnpm build`), to the point the emitter
# build looks hung. ZipFile.ExtractToDirectory has no such overhead.
git -C $CoreRoot archive --format=zip -o $zipPath "${targetSha}:$script:CoreJavaSubtree"
if ($LASTEXITCODE -ne 0) {
Write-Error "Failed to archive core commit ${targetSha}:$script:CoreJavaSubtree."
}
Expand-Archive -Path $zipPath -DestinationPath $tempDir -Force
Add-Type -AssemblyName System.IO.Compression.FileSystem
[System.IO.Compression.ZipFile]::ExtractToDirectory($zipPath, $extractDir)
}
catch {
Remove-Item $tempDir -Recurse -Force -ErrorAction SilentlyContinue
throw
}
Remove-Item $zipPath -Force
return @{ Root = $tempDir; TempDir = $tempDir }
return @{ Root = $extractDir; TempDir = $tempDir }
}

# Clean up the temporary extraction created by Get-CoreSourceRoot (no-op when the
Expand Down
4 changes: 2 additions & 2 deletions packages/typespec-java/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@
"scripts": {
"clean": "rimraf ./dist ./temp ./generator",
"build": "pnpm build:emitter && pnpm build:generator",
"build:emitter": "pwsh -NoProfile -File Copy-Sources.ps1 && tsc -p .",
"build:generator": "pwsh -NoProfile -File Build-Generator.ps1",
"build:emitter": "pwsh -NoProfile -NonInteractive -File Copy-Sources.ps1 && tsc -p .",
"build:generator": "pwsh -NoProfile -NonInteractive -File Build-Generator.ps1",
"watch": "tsc -p . --watch",
"test": "vitest run",
"regen-docs": "pnpm run build:emitter && tspd doc . --enable-experimental --output-dir ../../website/src/content/docs/docs/emitters/clients/typespec-java/reference --skip-js"
Expand Down
Loading