From b9748f70b82fde2a27a46f04fad8aa63d353a065 Mon Sep 17 00:00:00 2001 From: "Victor A." <52110451+cs50victor@users.noreply.github.com> Date: Tue, 26 May 2026 14:54:34 -0700 Subject: [PATCH 1/3] fix: add allfontsgen control diagnostics --- .github/workflows/release.yml | 2 + scripts/build_allfontsgen.js | 23 +++ scripts/generate_office_fonts.js | 43 +++++- .../allfontsgen-control-diagnostics.patch | 139 ++++++++++++++++++ 4 files changed, 205 insertions(+), 2 deletions(-) create mode 100644 scripts/patches/allfontsgen-control-diagnostics.patch diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a1d1aa2..e031850 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -148,6 +148,8 @@ jobs: Get-ChildItem converter/*.dll | ForEach-Object { Write-Output "Bundled $($_.Name) ($($_.Length) bytes)" } - name: Build allfontsgen + env: + ALLFONTSGEN_FORCE_REBUILD: ${{ runner.os == 'Windows' && '1' || '0' }} run: bun scripts/build_allfontsgen.js - name: Install production dependencies diff --git a/scripts/build_allfontsgen.js b/scripts/build_allfontsgen.js index c49859f..9bf0555 100755 --- a/scripts/build_allfontsgen.js +++ b/scripts/build_allfontsgen.js @@ -25,12 +25,24 @@ const CORE_REPO = 'https://github.com/ONLYOFFICE/core.git'; const CORE_COMMIT = '82e281cf6bf89498e4de6018423b36576706c2b6'; const SRC = path.join(CORE_DIR, 'DesktopEditor', 'AllFontsGen', 'main.cpp'); const WINDOWS_COMPONENTS = ['graphics', 'kernel', 'UnicodeConverter']; +const FORCE_ALLFONTSGEN_REBUILD = process.env.ALLFONTSGEN_FORCE_REBUILD === '1'; +const ALLFONTSGEN_DIAGNOSTICS_PATCH = path.join( + ROOT, + 'scripts', + 'patches', + 'allfontsgen-control-diagnostics.patch' +); let cachedConverterArch = null; const platform = process.platform; // 'darwin', 'win32', 'linux' // Early return if allfontsgen binary already exists function checkExistingBinary() { + if (FORCE_ALLFONTSGEN_REBUILD) { + console.log('[build_allfontsgen] ALLFONTSGEN_FORCE_REBUILD=1, rebuilding binary'); + return false; + } + if (platform === 'darwin') { const output = path.join(CONVERTER_DIR, 'allfontsgen'); if (fs.existsSync(output)) { @@ -369,7 +381,18 @@ function ensureCoreSources() { run('git', ['submodule', 'update', '--init', '--recursive', '--force'], { cwd: CORE_DIR }); } +function applyAllFontsGenDiagnosticsPatch() { + if (!fs.existsSync(ALLFONTSGEN_DIAGNOSTICS_PATCH)) { + console.error('[build_allfontsgen] Missing diagnostics patch:', ALLFONTSGEN_DIAGNOSTICS_PATCH); + process.exit(1); + } + + console.log('[build_allfontsgen] Applying AllFontsGen diagnostics patch...'); + run('git', ['apply', '--whitespace=nowarn', ALLFONTSGEN_DIAGNOSTICS_PATCH], { cwd: CORE_DIR }); +} + ensureCoreSources(); +applyAllFontsGenDiagnosticsPatch(); if (!fs.existsSync(SRC)) { console.error('[build_allfontsgen] main.cpp not found:', SRC); diff --git a/scripts/generate_office_fonts.js b/scripts/generate_office_fonts.js index 7d2fec5..75d0482 100755 --- a/scripts/generate_office_fonts.js +++ b/scripts/generate_office_fonts.js @@ -63,6 +63,7 @@ function locateBinary() { const BIN = locateBinary(); const INPUT_DIR = path.join(OUTPUT_DIR, 'fonts'); +const DIAG_LOG = path.join(OUTPUT_DIR, 'allfontsgen-control.log'); fs.mkdirSync(OUTPUT_DIR, { recursive: true }); fs.mkdirSync(INPUT_DIR, { recursive: true }); @@ -78,18 +79,56 @@ const env = { ...process.env }; if (platform === 'darwin') { env.DYLD_FRAMEWORK_PATH = CONVERTER_DIR; } +if (platform === 'win32') { + env.ALLFONTSGEN_DIAG_LOG = DIAG_LOG; +} + +function readDiagnosticLog() { + if (platform !== 'win32' || !fs.existsSync(DIAG_LOG)) { + return ''; + } + + const text = fs.readFileSync(DIAG_LOG, 'utf8').trim(); + if (!text) { + return ''; + } + + const lines = text.split(/\r?\n/).slice(-20); + return `\n[generate_office_fonts] allfontsgen diagnostic log:\n${lines.join('\n')}`; +} + +function formatExitStatus(status) { + if (typeof status !== 'number') { + return String(status); + } + + return `${status} (0x${(status >>> 0).toString(16).toUpperCase()})`; +} const result = spawnSync(BIN, args, { stdio: 'inherit', env }); if (result.status !== 0) { - fail(`allfontsgen exited with code ${result.status || 1}`); + const details = [ + `allfontsgen exited with code ${formatExitStatus(result.status)}`, + result.signal ? `signal=${result.signal}` : null, + result.error ? `error=${result.error.message}` : null, + ].filter(Boolean).join(' '); + + fail(`${details}${readDiagnosticLog()}`); } const allFontsJs = path.join(OUTPUT_DIR, 'AllFonts.js'); const fontSelectionBin = path.join(OUTPUT_DIR, 'font_selection.bin'); if (!fs.existsSync(allFontsJs) || !fs.existsSync(fontSelectionBin)) { - fail('allfontsgen exited successfully but font metadata files were not created'); + const missing = [ + fs.existsSync(allFontsJs) ? null : allFontsJs, + fs.existsSync(fontSelectionBin) ? null : fontSelectionBin, + ].filter(Boolean); + + fail( + `allfontsgen exited successfully but font metadata files were not created; missing=${missing.join(', ')}${readDiagnosticLog()}` + ); } console.log('[generate_office_fonts] Font metadata updated.'); diff --git a/scripts/patches/allfontsgen-control-diagnostics.patch b/scripts/patches/allfontsgen-control-diagnostics.patch new file mode 100644 index 0000000..cf59555 --- /dev/null +++ b/scripts/patches/allfontsgen-control-diagnostics.patch @@ -0,0 +1,139 @@ +diff --git a/DesktopEditor/AllFontsGen/main.cpp b/DesktopEditor/AllFontsGen/main.cpp +--- a/DesktopEditor/AllFontsGen/main.cpp ++++ b/DesktopEditor/AllFontsGen/main.cpp +@@ -32,6 +32,9 @@ + */ + #include + #include ++#include ++#include ++#include + + #include "../common/Directory.h" + #include "../fontengine/ApplicationFontsWorker.h" +@@ -40,6 +43,103 @@ + #include "../freetype_names/FontMaps/FontDictionary.h" + #endif + ++#ifdef _WIN32 ++#include ++ ++static std::wstring g_allFontsGenDiagLogPath; ++static std::wstring g_allFontsGenOutputDir; ++ ++static const wchar_t* GetControlEventName(DWORD eventType) ++{ ++ switch (eventType) ++ { ++ case CTRL_C_EVENT: ++ return L"CTRL_C_EVENT"; ++ case CTRL_BREAK_EVENT: ++ return L"CTRL_BREAK_EVENT"; ++ case CTRL_CLOSE_EVENT: ++ return L"CTRL_CLOSE_EVENT"; ++ case CTRL_LOGOFF_EVENT: ++ return L"CTRL_LOGOFF_EVENT"; ++ case CTRL_SHUTDOWN_EVENT: ++ return L"CTRL_SHUTDOWN_EVENT"; ++ default: ++ return L"UNKNOWN_CONTROL_EVENT"; ++ } ++} ++ ++static std::wstring GetCurrentDirectoryForLog() ++{ ++ DWORD required = GetCurrentDirectoryW(0, NULL); ++ if (required == 0) ++ return L""; ++ ++ std::wstring value(required, L'\0'); ++ DWORD written = GetCurrentDirectoryW(required, &value[0]); ++ if (written == 0) ++ return L""; ++ ++ value.resize(written); ++ return value; ++} ++ ++static void AppendAllFontsGenDiagLine(const std::wstring& line) ++{ ++ if (g_allFontsGenDiagLogPath.empty()) ++ return; ++ ++ std::wofstream file(g_allFontsGenDiagLogPath.c_str(), std::ios::app); ++ if (!file.is_open()) ++ return; ++ ++ SYSTEMTIME now; ++ GetSystemTime(&now); ++ file << L"utc=" ++ << now.wYear << L"-" << now.wMonth << L"-" << now.wDay ++ << L"T" << now.wHour << L":" << now.wMinute << L":" << now.wSecond ++ << L"." << now.wMilliseconds << L"Z " ++ << line << std::endl; ++} ++ ++static void AppendAllFontsGenState(const wchar_t* stage) ++{ ++ std::wstringstream line; ++ line << L"stage=" << stage ++ << L" pid=" << GetCurrentProcessId() ++ << L" cwd=\"" << GetCurrentDirectoryForLog() << L"\"" ++ << L" outputDir=\"" << g_allFontsGenOutputDir << L"\""; ++ AppendAllFontsGenDiagLine(line.str()); ++} ++ ++static BOOL WINAPI AllFontsGenConsoleCtrlHandler(DWORD eventType) ++{ ++ std::wstringstream line; ++ line << L"stage=console-control" ++ << L" event=" << GetControlEventName(eventType) ++ << L" eventCode=" << eventType ++ << L" pid=" << GetCurrentProcessId() ++ << L" cwd=\"" << GetCurrentDirectoryForLog() << L"\"" ++ << L" outputDir=\"" << g_allFontsGenOutputDir << L"\""; ++ AppendAllFontsGenDiagLine(line.str()); ++ ++ // Return FALSE so Windows keeps its normal behavior. For CTRL+C this preserves ++ // the observed STATUS_CONTROL_C_EXIT / 0xC000013A termination instead of hiding it. ++ return FALSE; ++} ++ ++static void InitAllFontsGenDiagnostics(const std::wstring& outputDir) ++{ ++ const wchar_t* logPath = _wgetenv(L"ALLFONTSGEN_DIAG_LOG"); ++ if (!logPath || !logPath[0]) ++ return; ++ ++ g_allFontsGenDiagLogPath = logPath; ++ g_allFontsGenOutputDir = outputDir; ++ SetConsoleCtrlHandler(AllFontsGenConsoleCtrlHandler, TRUE); ++ AppendAllFontsGenState(L"start"); ++} ++#endif ++ + std::wstring CorrectDir(const std::wstring& sDir) + { + if (sDir.empty()) +@@ -206,6 +305,10 @@ + // font_selection.bin + // fonts.log + oWorker.m_sDirectory = NSFile::GetDirectoryName(strFontsSelectionBin); ++ ++#ifdef _WIN32 ++ InitAllFontsGenDiagnostics(oWorker.m_sDirectory); ++#endif + + // thumbnails + oWorker.m_sThumbnailsDirectory = strThumbnailsFolder; +@@ -222,7 +325,10 @@ + // opentype + oWorker.m_bIsUseOpenType = (0x01 == (0x01 & nFontFlag)); + + NSFonts::IApplicationFonts* pApplicationFonts = oWorker.Check(); ++#ifdef _WIN32 ++ AppendAllFontsGenState(pApplicationFonts ? L"after-check-non-null" : L"after-check-null"); ++#endif + if (oWorker.m_bIsNeedThumbnails) + oWorker.CheckThumbnails(); + From 1d1ac0bc4b97e190696183c64dabbd114128fe54 Mon Sep 17 00:00:00 2001 From: "Victor A." <52110451+cs50victor@users.noreply.github.com> Date: Wed, 27 May 2026 10:21:55 -0700 Subject: [PATCH 2/3] fix: make allfontsgen diagnostics retryable --- scripts/build_allfontsgen.js | 6 +- .../allfontsgen-control-diagnostics.patch | 108 +++--------------- 2 files changed, 21 insertions(+), 93 deletions(-) diff --git a/scripts/build_allfontsgen.js b/scripts/build_allfontsgen.js index 9bf0555..3b6cdb4 100755 --- a/scripts/build_allfontsgen.js +++ b/scripts/build_allfontsgen.js @@ -376,7 +376,7 @@ function ensureCoreSources() { console.log(`[build_allfontsgen] Checking out ONLYOFFICE/core commit ${CORE_COMMIT}...`); run('git', ['fetch', '--all'], { cwd: CORE_DIR }); - run('git', ['checkout', CORE_COMMIT], { cwd: CORE_DIR }); + run('git', ['checkout', '--force', CORE_COMMIT], { cwd: CORE_DIR }); console.log('[build_allfontsgen] Updating ONLYOFFICE/core submodules...'); run('git', ['submodule', 'update', '--init', '--recursive', '--force'], { cwd: CORE_DIR }); } @@ -388,7 +388,9 @@ function applyAllFontsGenDiagnosticsPatch() { } console.log('[build_allfontsgen] Applying AllFontsGen diagnostics patch...'); - run('git', ['apply', '--whitespace=nowarn', ALLFONTSGEN_DIAGNOSTICS_PATCH], { cwd: CORE_DIR }); + run('git', ['apply', '--unidiff-zero', '--whitespace=nowarn', ALLFONTSGEN_DIAGNOSTICS_PATCH], { + cwd: CORE_DIR, + }); } ensureCoreSources(); diff --git a/scripts/patches/allfontsgen-control-diagnostics.patch b/scripts/patches/allfontsgen-control-diagnostics.patch index cf59555..2fd0b35 100644 --- a/scripts/patches/allfontsgen-control-diagnostics.patch +++ b/scripts/patches/allfontsgen-control-diagnostics.patch @@ -1,61 +1,18 @@ diff --git a/DesktopEditor/AllFontsGen/main.cpp b/DesktopEditor/AllFontsGen/main.cpp --- a/DesktopEditor/AllFontsGen/main.cpp +++ b/DesktopEditor/AllFontsGen/main.cpp -@@ -32,6 +32,9 @@ - */ - #include - #include +@@ -33,0 +34,2 @@ +#include -+#include +#include - - #include "../common/Directory.h" - #include "../fontengine/ApplicationFontsWorker.h" -@@ -40,6 +43,103 @@ - #include "../freetype_names/FontMaps/FontDictionary.h" - #endif - +@@ -42,0 +45,49 @@ ++ +#ifdef _WIN32 +#include + +static std::wstring g_allFontsGenDiagLogPath; +static std::wstring g_allFontsGenOutputDir; + -+static const wchar_t* GetControlEventName(DWORD eventType) -+{ -+ switch (eventType) -+ { -+ case CTRL_C_EVENT: -+ return L"CTRL_C_EVENT"; -+ case CTRL_BREAK_EVENT: -+ return L"CTRL_BREAK_EVENT"; -+ case CTRL_CLOSE_EVENT: -+ return L"CTRL_CLOSE_EVENT"; -+ case CTRL_LOGOFF_EVENT: -+ return L"CTRL_LOGOFF_EVENT"; -+ case CTRL_SHUTDOWN_EVENT: -+ return L"CTRL_SHUTDOWN_EVENT"; -+ default: -+ return L"UNKNOWN_CONTROL_EVENT"; -+ } -+} -+ -+static std::wstring GetCurrentDirectoryForLog() -+{ -+ DWORD required = GetCurrentDirectoryW(0, NULL); -+ if (required == 0) -+ return L""; -+ -+ std::wstring value(required, L'\0'); -+ DWORD written = GetCurrentDirectoryW(required, &value[0]); -+ if (written == 0) -+ return L""; -+ -+ value.resize(written); -+ return value; -+} -+ -+static void AppendAllFontsGenDiagLine(const std::wstring& line) ++static void AppendAllFontsGenDiagLine(const wchar_t* stage, DWORD eventType = MAXDWORD) +{ + if (g_allFontsGenDiagLogPath.empty()) + return; @@ -69,33 +26,19 @@ diff --git a/DesktopEditor/AllFontsGen/main.cpp b/DesktopEditor/AllFontsGen/main + file << L"utc=" + << now.wYear << L"-" << now.wMonth << L"-" << now.wDay + << L"T" << now.wHour << L":" << now.wMinute << L":" << now.wSecond -+ << L"." << now.wMilliseconds << L"Z " -+ << line << std::endl; -+} ++ << L"." << now.wMilliseconds << L"Z" ++ << L" stage=" << stage ++ << L" pid=" << GetCurrentProcessId(); + -+static void AppendAllFontsGenState(const wchar_t* stage) -+{ -+ std::wstringstream line; -+ line << L"stage=" << stage -+ << L" pid=" << GetCurrentProcessId() -+ << L" cwd=\"" << GetCurrentDirectoryForLog() << L"\"" -+ << L" outputDir=\"" << g_allFontsGenOutputDir << L"\""; -+ AppendAllFontsGenDiagLine(line.str()); ++ if (eventType != MAXDWORD) ++ file << L" eventCode=" << eventType; ++ ++ file << L" outputDir=\"" << g_allFontsGenOutputDir << L"\"" << std::endl; +} + +static BOOL WINAPI AllFontsGenConsoleCtrlHandler(DWORD eventType) +{ -+ std::wstringstream line; -+ line << L"stage=console-control" -+ << L" event=" << GetControlEventName(eventType) -+ << L" eventCode=" << eventType -+ << L" pid=" << GetCurrentProcessId() -+ << L" cwd=\"" << GetCurrentDirectoryForLog() << L"\"" -+ << L" outputDir=\"" << g_allFontsGenOutputDir << L"\""; -+ AppendAllFontsGenDiagLine(line.str()); -+ -+ // Return FALSE so Windows keeps its normal behavior. For CTRL+C this preserves -+ // the observed STATUS_CONTROL_C_EXIT / 0xC000013A termination instead of hiding it. ++ AppendAllFontsGenDiagLine(L"console-control", eventType); + return FALSE; +} + @@ -108,32 +51,15 @@ diff --git a/DesktopEditor/AllFontsGen/main.cpp b/DesktopEditor/AllFontsGen/main + g_allFontsGenDiagLogPath = logPath; + g_allFontsGenOutputDir = outputDir; + SetConsoleCtrlHandler(AllFontsGenConsoleCtrlHandler, TRUE); -+ AppendAllFontsGenState(L"start"); ++ AppendAllFontsGenDiagLine(L"start"); +} +#endif -+ - std::wstring CorrectDir(const std::wstring& sDir) - { - if (sDir.empty()) -@@ -206,6 +305,10 @@ - // font_selection.bin - // fonts.log - oWorker.m_sDirectory = NSFile::GetDirectoryName(strFontsSelectionBin); -+ +@@ -209,0 +261,4 @@ +#ifdef _WIN32 + InitAllFontsGenDiagnostics(oWorker.m_sDirectory); +#endif - - // thumbnails - oWorker.m_sThumbnailsDirectory = strThumbnailsFolder; -@@ -222,7 +325,10 @@ - // opentype - oWorker.m_bIsUseOpenType = (0x01 == (0x01 & nFontFlag)); - - NSFonts::IApplicationFonts* pApplicationFonts = oWorker.Check(); ++ +@@ -225,0 +281,3 @@ +#ifdef _WIN32 -+ AppendAllFontsGenState(pApplicationFonts ? L"after-check-non-null" : L"after-check-null"); ++ AppendAllFontsGenDiagLine(pApplicationFonts ? L"after-check-non-null" : L"after-check-null"); +#endif - if (oWorker.m_bIsNeedThumbnails) - oWorker.CheckThumbnails(); - From bab952e0d63908cfc7bb642cda79171d130d3d54 Mon Sep 17 00:00:00 2001 From: "Victor A." <52110451+cs50victor@users.noreply.github.com> Date: Wed, 27 May 2026 10:29:28 -0700 Subject: [PATCH 3/3] refactor: print full allfontsgen diagnostic log --- scripts/generate_office_fonts.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/generate_office_fonts.js b/scripts/generate_office_fonts.js index 75d0482..6e6c714 100755 --- a/scripts/generate_office_fonts.js +++ b/scripts/generate_office_fonts.js @@ -93,8 +93,8 @@ function readDiagnosticLog() { return ''; } - const lines = text.split(/\r?\n/).slice(-20); - return `\n[generate_office_fonts] allfontsgen diagnostic log:\n${lines.join('\n')}`; + const normalizedText = text.replaceAll('\r\n', '\n'); + return `\n[generate_office_fonts] allfontsgen diagnostic log:\n${normalizedText}`; } function formatExitStatus(status) {