Skip to content
Merged

0.2.35 #1094

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
5 changes: 3 additions & 2 deletions kun/src/graph/graph-scheduler-loop-gate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ import {
} from '../../tests/graph-scheduler-test-harness.js'

const execFileAsync = promisify(execFile)
const schedulerWaitTimeoutMs = process.platform === 'win32' ? 30_000 : 15_000
const schedulerTestTimeoutMs = process.platform === 'win32' ? 60_000 : 30_000
const usesSlowerSchedulerPersistence = process.platform === 'darwin' || process.platform === 'win32'
const schedulerWaitTimeoutMs = usesSlowerSchedulerPersistence ? 30_000 : 15_000
const schedulerTestTimeoutMs = usesSlowerSchedulerPersistence ? 60_000 : 30_000

function task(
key: string,
Expand Down
47 changes: 38 additions & 9 deletions scripts/smoke-packaged-extension-appimage.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ const {

const APPIMAGE_FILE_PATTERN = /^Kun-[0-9A-Za-z][0-9A-Za-z._-]*-linux-x86_64\.AppImage$/
const APPIMAGE_EXTRACTION_TIMEOUT_MS = 120_000
const APPIMAGE_DESKTOP_SMOKE_MAX_BUFFER = 1024 * 1024
const TRANSIENT_CHROMIUM_SIGTRAP_PATTERN =
/Packaged Electron exited before the desktop smoke completed \(exit=133, signal=null\)/u

function assertLinuxX64(platform = process.platform, arch = process.arch) {
if (platform !== 'linux' || arch !== 'x64') {
Expand Down Expand Up @@ -112,7 +115,9 @@ function createAppImageSmokeInvocation({
options: {
env,
shell: false,
stdio: 'inherit',
stdio: ['ignore', 'pipe', 'pipe'],
encoding: 'utf8',
maxBuffer: APPIMAGE_DESKTOP_SMOKE_MAX_BUFFER,
windowsHide: true
}
}
Expand Down Expand Up @@ -160,7 +165,8 @@ function runAppImageSmoke(options = {}) {
runInvocation(
smoke,
options.spawnSyncCommand ?? spawnSync,
'Final Linux AppImage Extension desktop smoke failed'
'Final Linux AppImage Extension desktop smoke failed',
{ retryTransientChromiumSigtrap: true }
)
return appImage
} finally {
Expand Down Expand Up @@ -294,19 +300,42 @@ function inspectEmptyExtractionDirectory(extractionDirectory) {
}
}

function runInvocation(invocation, spawnSyncCommand, failureMessage) {
const result = spawnSyncCommand(invocation.command, invocation.args, invocation.options)
if (result.error?.code === 'ETIMEDOUT') {
throw new Error(`${failureMessage} (timed out after ${String(invocation.options.timeout)} ms)`)
}
if (result.error) throw result.error
if (result.status !== 0) {
function runInvocation(
invocation,
spawnSyncCommand,
failureMessage,
{ retryTransientChromiumSigtrap = false } = {}
) {
const maxAttempts = retryTransientChromiumSigtrap ? 2 : 1
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
const result = spawnSyncCommand(invocation.command, invocation.args, invocation.options)
forwardInvocationOutput(result)
if (result.error?.code === 'ETIMEDOUT') {
throw new Error(`${failureMessage} (timed out after ${String(invocation.options.timeout)} ms)`)
}
if (result.error) throw result.error
if (result.status === 0) return
if (
attempt < maxAttempts &&
result.status === 1 &&
TRANSIENT_CHROMIUM_SIGTRAP_PATTERN.test(`${result.stdout ?? ''}\n${result.stderr ?? ''}`)
) {
process.stderr.write(
'Final Linux AppImage Chromium smoke hit a transient SIGTRAP; retrying once.\n'
)
continue
}
throw new Error(
`${failureMessage}${result.signal ? ` (signal ${result.signal})` : ` (exit ${String(result.status)})`}`
)
}
}

function forwardInvocationOutput(result) {
if (result.stdout) process.stdout.write(result.stdout)
if (result.stderr) process.stderr.write(result.stderr)
}

function assertContained(root, candidate, label) {
const rel = relative(root, candidate)
if (!rel || rel === '..' || rel.startsWith(`..${sep}`) || isAbsolute(rel)) {
Expand Down
43 changes: 43 additions & 0 deletions scripts/smoke-packaged-extension-appimage.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ test('builds FUSE-free validation and verified-AppRun desktop invocations', () =
resolve('/tmp/kun-appimage-extract/squashfs-root/AppRun')
])
assert.equal(smoke.options.shell, false)
assert.deepEqual(smoke.options.stdio, ['ignore', 'pipe', 'pipe'])
assert.equal(smoke.options.encoding, 'utf8')
assert.equal(smoke.options.maxBuffer, 1024 * 1024)
assert.equal(smoke.options.timeout, undefined)
assert.equal(smoke.options.killSignal, undefined)
assert.equal(smoke.options.env.ELECTRON_RUN_AS_NODE, undefined)
Expand Down Expand Up @@ -166,6 +169,46 @@ test('extracts and validates before launching the verified AppRun', {
assert.equal(statSync(appImage).mode & 0o111, 0o111)
})

test('retries the verified AppRun once after the exact transient Chromium SIGTRAP', {
skip: process.platform === 'win32' && 'requires POSIX executable modes'
}, (t) => {
const dist = temporaryDirectory(t)
const extractionDirectory = temporaryDirectory(t, 'kun-appimage-sigtrap-test-')
const appImage = join(dist, 'Kun-1.2.3-linux-x86_64.AppImage')
writeFileSync(appImage, 'appimage')
let desktopAttempts = 0

assert.doesNotThrow(() => runAppImageSmoke({
platform: 'linux',
arch: 'x64',
distDirectory: dist,
extractionDirectory,
spawnSyncCommand: (command, args, options) => {
if (command === appImage) {
writeExtractedBundle(options.cwd)
return { status: 0, signal: null }
}
desktopAttempts += 1
if (desktopAttempts === 1) {
return {
status: 1,
signal: null,
stdout: '',
stderr:
'Packaged Electron exited before the desktop smoke completed ' +
'(exit=133, signal=null)\n'
}
}
assert.deepEqual(args.slice(-2), [
'--desktop-executable',
join(extractionDirectory, 'squashfs-root', 'AppRun')
])
return { status: 0, signal: null, stdout: '', stderr: '' }
}
}))
assert.equal(desktopAttempts, 2)
})

test('rejects a symlinked extracted AppRun before desktop launch', (t) => {
if (process.platform === 'win32') return
const dist = temporaryDirectory(t)
Expand Down
Loading