Bug Summary
On Linux (unpacked installations), the Antigravity Electron GUI application suffers from three critical issues:
- Process Hang on Close: When the GUI is closed, the main process and backend language server processes continue to run in the background (often leaving zombie/defunct child processes or fully orphaned processes).
- Failure to Open/Restore Window on Second Launch: Since
RUN_IN_BACKGROUND is active by default on Linux, closing the window leaves the app running in the background. Launching a new instance detects the single-instance lock, exits the new instance, but the background instance fails to create or restore a window because the second-instance event handler assumes there is already a window active.
- Linux Auto-Updater Fails to Run:
electron-updater's AppImageUpdater on Linux immediately aborts with the warning APPIMAGE env is not defined, current application is not an AppImage when run from an unpacked directory, disabling update checks.
Root Cause Analysis
1. Process Hang on Close
In main.js, the before-quit handler is an async function:
app.on('before-quit', async (event) => {
if (isQuitting) return;
if (!showQuitConfirmation) {
event.preventDefault();
isQuitting = true;
// ... destroys windows, kills language server ...
app.quit(); // <--- TRIGGERS before-quit AGAIN
return;
}
});
Calling app.quit() inside the async block triggers the before-quit event a second time. In the second call, isQuitting is true, so it returns immediately. However, since the first call had event.preventDefault(), the quitting sequence was aborted and the second call does not force the event loop to exit.
- Fix: Use
app.exit(0) instead of app.quit() at the end of the async cleanup block to bypass recursive quit events and terminate the process immediately.
2. Restore Window on Second Launch
In main.js, the second-instance handler only focuses windows if wins.length > 0:
app.on('second-instance', (event, commandLine) => {
const wins = BrowserWindow.getAllWindows();
if (wins.length > 0) {
// ... restores and focuses wins[0] ...
}
// BUG: If wins.length === 0, no window is opened, and the app stays hidden in background
});
- Fix: Re-create/open a new window if
wins.length === 0 and the application is not headless.
3. Linux Auto-Updater Fails on Unpacked Runs
On Linux, AppImageUpdater aborts checks if process.env.APPIMAGE is undefined.
- Fix: Programmatically fallback to
process.execPath (i.e. process.env.APPIMAGE = process.env.APPIMAGE || process.execPath;) during updater initialization on Linux.
Proposed Patches
Patch for main.ts / main.js:
--- dist/main.js.orig
+++ dist/main.js
@@ -121,6 +121,10 @@
wins[0].focus();
electron_1.app.focus({ steal: true });
}
+ else if (!HEADLESS) {
+ const url = DEV_URL ?? `${constants_1.WINDOW_ORIGIN}:${(0, languageServer_1.getLsPort)()}/`;
+ (0, utils_1.createWindow)(url);
+ }
const url = commandLine.find((arg) => arg.startsWith(`${PROTOCOL}://`));
if (url) {
handleDeepLink(url);
@@ -327,7 +331,7 @@
}),
(0, languageServer_1.killLanguageServer)(),
]);
- electron_1.app.quit();
+ electron_1.app.exit(0);
return;
}
Patch for updater.ts / updater.js:
--- dist/updater.js.orig
+++ dist/updater.js
@@ -133,6 +133,9 @@
function initAutoUpdater(isHeadless, settingsService) {
+ if (process.platform === 'linux' && !process.env.APPIMAGE) {
+ process.env.APPIMAGE = process.execPath;
+ }
// In dev mode (npm start), electron-updater skips checks because the app
// isn't packaged. Force it to use the dev config file instead.
if (!electron_1.app.isPackaged) {
AI Assistance Disclosure
This issue and patch were co-developed with Gemini AI. Under my direction, the agent extracted app.asar, analyzed the lifecycle hangs and lock logic, applied local modifications, and empirically verified the auto-updater functionality (via version downgrading). I have reviewed, tested, and take full responsibility for these changes.
Co-developed-by: Gemini AI renich+gemini@woralelandia.com
Signed-off-by: Rénich Bon Ćirić renich@woralelandia.com
Bug Summary
On Linux (unpacked installations), the Antigravity Electron GUI application suffers from three critical issues:
RUN_IN_BACKGROUNDis active by default on Linux, closing the window leaves the app running in the background. Launching a new instance detects the single-instance lock, exits the new instance, but the background instance fails to create or restore a window because thesecond-instanceevent handler assumes there is already a window active.electron-updater'sAppImageUpdateron Linux immediately aborts with the warningAPPIMAGE env is not defined, current application is not an AppImagewhen run from an unpacked directory, disabling update checks.Root Cause Analysis
1. Process Hang on Close
In
main.js, thebefore-quithandler is an async function:Calling
app.quit()inside the async block triggers thebefore-quitevent a second time. In the second call,isQuittingistrue, so it returns immediately. However, since the first call hadevent.preventDefault(), the quitting sequence was aborted and the second call does not force the event loop to exit.app.exit(0)instead ofapp.quit()at the end of the async cleanup block to bypass recursive quit events and terminate the process immediately.2. Restore Window on Second Launch
In
main.js, thesecond-instancehandler only focuses windows ifwins.length > 0:wins.length === 0and the application is not headless.3. Linux Auto-Updater Fails on Unpacked Runs
On Linux,
AppImageUpdateraborts checks ifprocess.env.APPIMAGEis undefined.process.execPath(i.e.process.env.APPIMAGE = process.env.APPIMAGE || process.execPath;) during updater initialization on Linux.Proposed Patches
Patch for
main.ts/main.js:Patch for
updater.ts/updater.js:AI Assistance Disclosure
This issue and patch were co-developed with Gemini AI. Under my direction, the agent extracted
app.asar, analyzed the lifecycle hangs and lock logic, applied local modifications, and empirically verified the auto-updater functionality (via version downgrading). I have reviewed, tested, and take full responsibility for these changes.Co-developed-by: Gemini AI renich+gemini@woralelandia.com
Signed-off-by: Rénich Bon Ćirić renich@woralelandia.com