fix(db-load,db-update): расшифровывать аномальный код завершения платформы

Мутирующие навыки не производят одиночный артефакт, но при крахе платформы
(нет GUI-сессии/лицензии) возвращали голый код вроде -11. Добавлен аннотатор:
POSIX-сигнал (напр. -11 → SIGSEGV) и Windows exception-код (напр. 0xC0000005) →
внятное сообщение с предупреждением о возможной несогласованности ИБ. Без
ожидания фоновых процессов и без ps-скрейпинга.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-07-19 18:52:25 +03:00
co-authored by Claude Opus 4.8
parent 2804355fba
commit 4b6ffc595e
10 changed files with 244 additions and 34 deletions
@@ -1,4 +1,4 @@
# db-load-cf v1.6 — Load 1C configuration from CF file
# db-load-cf v1.7 — Load 1C configuration from CF file
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
# NB: *nix-раскладку платформы (/opt/1cv8/<ver>/1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется.
<#
@@ -76,6 +76,23 @@ param(
$OutputEncoding = [System.Text.Encoding]::UTF8
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
function Get-ExitAnnotation {
# Annotate an abnormal process exit code so a crash isn't reported as a bare number.
# A batch DESIGNER that crashes (e.g. missing license) may leave the infobase locked or
# half-updated — surface that instead of a plain code. (Windows exception codes only;
# POSIX signals are handled in the .py port.)
param([int]$Code)
$win = @{
-1073741819 = "0xC0000005 (access violation)"
-1073741515 = "0xC0000135 (missing DLL)"
-1073740791 = "0xC0000409 (stack overrun)"
}
if ($win.ContainsKey($Code)) {
return " — abnormal termination $($win[$Code]); the platform crashed; the infobase may be left in an inconsistent state"
}
return ""
}
# --- Resolve V8Path ---
function Find-ProjectV8Path {
$dir = (Get-Location).Path
@@ -190,7 +207,7 @@ try {
if ($exitCode -eq 0) {
Write-Host "Configuration loaded successfully from: $InputFile" -ForegroundColor Green
} else {
Write-Host "Error loading configuration (code: $exitCode)" -ForegroundColor Red
Write-Host "Error loading configuration (code: $exitCode)$(Get-ExitAnnotation $exitCode)" -ForegroundColor Red
}
if ($output) { Write-Host ($output | Out-String) }
exit $exitCode
@@ -232,7 +249,7 @@ try {
if ($exitCode -eq 0) {
Write-Host "Configuration loaded successfully from: $InputFile" -ForegroundColor Green
} else {
Write-Host "Error loading configuration (code: $exitCode)" -ForegroundColor Red
Write-Host "Error loading configuration (code: $exitCode)$(Get-ExitAnnotation $exitCode)" -ForegroundColor Red
}
if (Test-Path $outFile) {
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# db-load-cf v1.6 — Load 1C configuration from CF file
# db-load-cf v1.7 — Load 1C configuration from CF file
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
@@ -99,6 +99,31 @@ def run_ibcmd(cmd, has_username=False, warn_no_user=True):
return subprocess.run(cmd, input="", capture_output=True, encoding="utf-8", errors="replace")
def describe_exit(code):
"""Annotate an abnormal process exit code so a crash isn't reported as a bare number.
Batch 1C in a broken/headless environment (no GUI session, no license) can crash mid-run
instead of returning a clean error, possibly leaving the infobase locked or half-mutated."""
if code is None:
return ""
win = {
3221225477: "0xC0000005 (access violation)", -1073741819: "0xC0000005 (access violation)",
3221225781: "0xC0000135 (missing DLL)", -1073741515: "0xC0000135 (missing DLL)",
3221226505: "0xC0000409 (stack overrun)", -1073740791: "0xC0000409 (stack overrun)",
}
if code in win:
return f" — abnormal termination {win[code]}; the platform crashed; the infobase may be left in an inconsistent state"
if -64 <= code < 0:
try:
import signal
name = signal.Signals(-code).name
except (ValueError, AttributeError):
name = f"signal {-code}"
return (f" — terminated by {name}; the platform crashed abnormally "
"(often a headless environment without a GUI session or license); "
"the infobase may be left in an inconsistent state")
return ""
def main():
sys.stdout.reconfigure(encoding="utf-8")
sys.stderr.reconfigure(encoding="utf-8")
@@ -155,7 +180,7 @@ def main():
if result.returncode == 0:
print(f"Configuration loaded successfully from: {args.InputFile}")
else:
print(f"Error loading configuration (code: {result.returncode})", file=sys.stderr)
print(f"Error loading configuration (code: {result.returncode}){describe_exit(result.returncode)}", file=sys.stderr)
if result.stdout:
print(result.stdout)
if result.stderr:
@@ -206,7 +231,7 @@ def main():
if exit_code == 0:
print(f"Configuration loaded successfully from: {args.InputFile}")
else:
print(f"Error loading configuration (code: {exit_code})", file=sys.stderr)
print(f"Error loading configuration (code: {exit_code}){describe_exit(exit_code)}", file=sys.stderr)
if os.path.isfile(out_file):
try: