| 538 | } |
| 539 | |
| 540 | static void host_state_free(host_state_t *host) { |
| 541 | if (!host_http_stop_join_free(host)) { |
| 542 | /* The retained server or one of its callbacks can still borrow every |
| 543 | * dependency below. Process containment is the only safe teardown. */ |
| 544 | host_force_terminate("http_cleanup"); |
| 545 | } |
| 546 | if (host->application) { |
| 547 | if (!cbm_daemon_application_free(host->application)) { |
| 548 | /* The application still owns work or a borrowed callback context. |
| 549 | * Freeing any dependency below would turn the retained application |
| 550 | * into UAF. The daemon is the ultimate containment boundary. */ |
| 551 | host_cleanup_force_terminate("application_cleanup"); |
| 552 | } |
| 553 | host->application = NULL; |
| 554 | } |
| 555 | cbm_watcher_free(host->watcher); |
| 556 | host->watcher = NULL; |
| 557 | cbm_store_close(host->watch_store); |
| 558 | host->watch_store = NULL; |
| 559 | cbm_config_close(host->runtime_config); |
| 560 | host->runtime_config = NULL; |
| 561 | if (host->project_locks) { |
| 562 | host_cleanup_release_until_complete(host_project_lock_manager_free_once, |
| 563 | &host->project_locks, "project_lock_manager_cleanup"); |
| 564 | } |
| 565 | cbm_secure_zero(host->ui_readiness_secret, sizeof(host->ui_readiness_secret)); |
| 566 | } |
| 567 | |
| 568 | static bool host_state_prepare(host_state_t *host, const cbm_daemon_ipc_endpoint_t *endpoint) { |
| 569 | host->http_ops = &g_host_http_default_ops; |
no test coverage detected