diff --git a/doc/changes/state_trackers/mr.359.3.md b/doc/changes/state_trackers/mr.359.3.md new file mode 100644 index 000000000..b5baae0b2 --- /dev/null +++ b/doc/changes/state_trackers/mr.359.3.md @@ -0,0 +1,3 @@ +OpenXR: When a `XrSession` is destroyed purge the event queue of any events that +references to it so that no events gets delivered to the applications with +stales handles. diff --git a/src/xrt/state_trackers/oxr/oxr_event.c b/src/xrt/state_trackers/oxr/oxr_event.c index 3b2f80234..759a1785d 100644 --- a/src/xrt/state_trackers/oxr/oxr_event.c +++ b/src/xrt/state_trackers/oxr/oxr_event.c @@ -133,6 +133,44 @@ oxr_event_push_XrEventDataSessionStateChanged(struct oxr_logger *log, return XR_SUCCESS; } +XrResult +oxr_event_remove_session_events(struct oxr_logger *log, + struct oxr_session *sess) +{ + struct oxr_instance *inst = sess->sys->inst; + XrSession session = oxr_session_to_openxr(sess); + + lock(inst); + + struct oxr_event *e = inst->next_event; + while (e != NULL) { + struct oxr_event *cur = e; + e = e->next; + + XrEventDataSessionStateChanged *changed = oxr_event_extra(cur); + if (changed->type != XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED) { + continue; + } + + if (changed->session != session) { + continue; + } + + if (cur == inst->next_event) { + inst->next_event = cur->next; + } + + if (cur == inst->last_event) { + inst->last_event = NULL; + } + free(cur); + } + + unlock(inst); + + return XR_SUCCESS; +} + XrResult oxr_poll_event(struct oxr_logger *log, struct oxr_instance *inst, diff --git a/src/xrt/state_trackers/oxr/oxr_objects.h b/src/xrt/state_trackers/oxr/oxr_objects.h index e4a8c04f0..17e6dd941 100644 --- a/src/xrt/state_trackers/oxr/oxr_objects.h +++ b/src/xrt/state_trackers/oxr/oxr_objects.h @@ -692,6 +692,13 @@ oxr_event_push_XrEventDataSessionStateChanged(struct oxr_logger *log, XrSessionState state, XrTime time); +/*! + * This clears all pending events refers to the given session. + */ +XrResult +oxr_event_remove_session_events(struct oxr_logger *log, + struct oxr_session *sess); + /* * diff --git a/src/xrt/state_trackers/oxr/oxr_session.c b/src/xrt/state_trackers/oxr/oxr_session.c index 11e6dae16..a1d5b7c25 100644 --- a/src/xrt/state_trackers/oxr/oxr_session.c +++ b/src/xrt/state_trackers/oxr/oxr_session.c @@ -840,6 +840,8 @@ oxr_session_destroy(struct oxr_logger *log, struct oxr_handle_base *hb) { struct oxr_session *sess = (struct oxr_session *)hb; + XrResult ret = oxr_event_remove_session_events(log, sess); + // Does a null-ptr check. xrt_comp_destroy(&sess->compositor); @@ -848,7 +850,7 @@ oxr_session_destroy(struct oxr_logger *log, struct oxr_handle_base *hb) free(sess); - return XR_SUCCESS; + return ret; } #define OXR_SESSION_ALLOCATE(LOG, SYS, OUT) \