| 1430 | } |
| 1431 | |
| 1432 | static void runtime_worker_finish(cbm_daemon_runtime_worker_t *worker) { |
| 1433 | cbm_daemon_runtime_service_t *service = worker->service; |
| 1434 | runtime_worker_disconnect(worker); |
| 1435 | if (!runtime_worker_reap_application(worker, true)) { |
| 1436 | /* Fail closed on an impossible/invalid join rather than closing the |
| 1437 | * session or freeing storage a callback could still reference. The |
| 1438 | * service intentionally remains non-terminal for diagnosis. */ |
| 1439 | return; |
| 1440 | } |
| 1441 | if (worker->application_session_opened) { |
| 1442 | service->application.session_close(service->application.context, |
| 1443 | worker->application_session); |
| 1444 | worker->application_session = NULL; |
| 1445 | worker->application_session_opened = false; |
| 1446 | } |
| 1447 | if (worker->connection) { |
| 1448 | /* Off the service mutex: a peer that just received its final response |
| 1449 | * (hello rejection, disconnect acknowledgement) must be able to read |
| 1450 | * it before the handle closes; see cbm_daemon_ipc_connection_drain. */ |
| 1451 | cbm_daemon_ipc_connection_drain(worker->connection, RUNTIME_WORKER_DRAIN_TIMEOUT_MS); |
| 1452 | } |
| 1453 | cbm_mutex_lock(&service->mutex); |
| 1454 | if (worker->connection) { |
| 1455 | cbm_daemon_ipc_connection_close(worker->connection); |
| 1456 | worker->connection = NULL; |
| 1457 | } |
| 1458 | if (service->active_connections > 0) { |
| 1459 | service->active_connections--; |
| 1460 | } |
| 1461 | atomic_store_explicit(&worker->done, true, memory_order_release); |
| 1462 | cbm_mutex_unlock(&service->mutex); |
| 1463 | } |
| 1464 | |
| 1465 | static bool runtime_activation_peer_matches_claim(cbm_daemon_runtime_service_t *service, |
| 1466 | uint64_t process_id, const char *claimed_build) { |
no test coverage detected