Unified · Split
| @@ -270,8 +270,12 @@ const makeLaunchdBackend = (): ServiceBackend => { · 269 unmodified lines | ||
| 270 | 270 | yield* fs.writeFileString(plistFile, plist, { mode: 0o600 }); |
| 271 | 271 | |
| 272 | 272 | // Re-bootstrap cleanly: a stale registration from a prior install would |
| 273 | − // make `bootstrap` fail with "service already loaded". | |
| 273 | + // make `bootstrap` fail with "service already loaded". `service | |
| 274 | + // uninstall` also records the label as disabled in launchd's override | |
| 275 | + // database; clear that before bootstrapping or a reinstall can fail with | |
| 276 | + // launchctl's generic "Bootstrap failed: 5" error. | |
| 274 | 277 | yield* runCommand("launchctl", ["bootout", serviceTarget(uid)]).pipe(Effect.ignore); |
| 278 | + yield* runCommand("launchctl", ["enable", serviceTarget(uid)]).pipe(Effect.ignore); | |
| 275 | 279 | const bootstrap = yield* runCommand("launchctl", ["bootstrap", `gui/${uid}`, plistFile]); |
| 276 | 280 | if (bootstrap.code !== 0) { |
| 277 | 281 | return yield* Effect.fail( |
| @@ -280,7 +284,6 @@ const makeLaunchdBackend = (): ServiceBackend => { · 2 unmodified lines | ||
| 280 | 284 | ), |
| 281 | 285 | ); |
| 282 | 286 | } |
| 283 | − yield* runCommand("launchctl", ["enable", serviceTarget(uid)]).pipe(Effect.ignore); | |
| 284 | 287 | }), |
| 285 | 288 | uninstall: () => |
| 286 | 289 | Effect.gen(function* () { |
| @@ -205,7 +205,11 @@ export const installSupervisedService = async (opts: InstallOptions): Promise<vo · 204 unmodified lines | ||
| 205 | 205 | writeFileSync(plistPath(), plist, { mode: 0o600 }); |
| 206 | 206 | |
| 207 | 207 | // Re-bootstrap cleanly so a stale registration doesn't make bootstrap fail. |
| 208 | + // `uninstallSupervisedService` also records the label as disabled in | |
| 209 | + // launchd's override database; clear that before bootstrapping or reinstall | |
| 210 | + // can fail with launchctl's generic "Bootstrap failed: 5" error. | |
| 208 | 211 | await runCommand("launchctl", ["bootout", serviceTarget(uid)]); |
| 212 | + await runCommand("launchctl", ["enable", serviceTarget(uid)]); | |
| 209 | 213 | const bootstrap = await runCommand("launchctl", ["bootstrap", `gui/${uid}`, plistPath()]); |
| 210 | 214 | if (bootstrap.code !== 0) { |
| 211 | 215 | // oxlint-disable-next-line executor/no-error-constructor, executor/no-try-catch-or-throw -- boundary: surfaces to the boot flow |
| @@ -213,7 +217,6 @@ export const installSupervisedService = async (opts: InstallOptions): Promise<vo · 1 unmodified line | ||
| 213 | 217 | `launchctl bootstrap failed (exit ${bootstrap.code}): ${bootstrap.stderr.trim() || bootstrap.stdout.trim()}`, |
| 214 | 218 | ); |
| 215 | 219 | } |
| 216 | − await runCommand("launchctl", ["enable", serviceTarget(uid)]); | |
| 217 | 220 | serviceLog.info(`installed supervised service on port ${opts.port}`); |
| 218 | 221 | }; |
| 219 | 222 | |