| 1268 | } |
| 1269 | |
| 1270 | static void *runtime_application_worker(void *opaque) { |
| 1271 | cbm_daemon_runtime_worker_t *worker = opaque; |
| 1272 | cbm_daemon_runtime_service_t *service = worker->service; |
| 1273 | uint8_t *response = NULL; |
| 1274 | uint32_t response_length = 0; |
| 1275 | cbm_daemon_runtime_application_status_t status = service->application.request( |
| 1276 | service->application.context, worker->application_session, |
| 1277 | worker->application_request_token, worker->application_request, |
| 1278 | worker->application_request_length, &response, &response_length); |
| 1279 | |
| 1280 | bool valid_status = runtime_application_status_is_callback_result(status); |
| 1281 | bool valid_response = |
| 1282 | response_length <= CBM_DAEMON_RUNTIME_APPLICATION_PAYLOAD_MAX && |
| 1283 | (response_length == 0 || response != NULL) && |
| 1284 | (status == CBM_DAEMON_RUNTIME_APPLICATION_OK || (response == NULL && response_length == 0)); |
| 1285 | if (!valid_status || !valid_response) { |
| 1286 | free(response); |
| 1287 | response = NULL; |
| 1288 | response_length = 0; |
| 1289 | status = CBM_DAEMON_RUNTIME_APPLICATION_HANDLER_ERROR; |
| 1290 | } |
| 1291 | |
| 1292 | /* Completion must be one atomic transition from the client's point of |
| 1293 | * view: publish the done flag BEFORE the response bytes leave, so by the |
| 1294 | * time any client can react to the response, admission already observes |
| 1295 | * this slot as reusable. With the store after the send, a client that |
| 1296 | * pipelines its next request the moment it sees a response raced this |
| 1297 | * thread's final instructions and was rejected BUSY — on loaded Windows |
| 1298 | * hosts roughly half of all back-to-back requests on one connection, |
| 1299 | * surfacing as the wandering Phase 5 session drops. The admission side |
| 1300 | * joins this thread after observing the flag, which safely absorbs the |
| 1301 | * tail of the send. */ |
| 1302 | atomic_store_explicit(&worker->application_thread_done, true, memory_order_release); |
| 1303 | bool sent = runtime_worker_send_application_response(worker, worker->application_request_token, |
| 1304 | status, response, response_length, true); |
| 1305 | free(response); |
| 1306 | if (!sent && !atomic_load_explicit(&worker->disconnecting, memory_order_acquire)) { |
| 1307 | cbm_daemon_ipc_connection_interrupt(worker->connection); |
| 1308 | } |
| 1309 | return NULL; |
| 1310 | } |
| 1311 | |
| 1312 | static bool runtime_worker_reap_application(cbm_daemon_runtime_worker_t *worker, bool wait) { |
| 1313 | if (!worker->application_thread_started) { |
nothing calls this directly
no test coverage detected