weston-9 crash on page_flip_handler when system suspend/resume
background
drm-backend.so crashes in the following code
static void
atomic_flip_handler(int fd, unsigned int frame, unsigned int sec,
unsigned int usec, unsigned int crtc_id, void *data)
{
......
assert(output->page_flip_pending); //fails
......
}
page_flip_pending value is false causing crash.The log is as follows
audit[576]: ANOM_ABEND auid=4294967295 uid=0 gid=0 ses=4294967295 subj=kernel pid=576 comm="weston" exe="/usr/bin/weston" sig=6 res=1
weston[576]: weston: ../weston-9.0.0/libweston/backend-drm/kms.c:1409: void atomic_flip_handler(int, unsigned int, unsigned int, unsigned int, unsigned int, void *): Assertion `output->atomic_complete_pending' failed.
reason
- The system will trigger session active/deactive when suspend/resume
static void
session_notify(struct wl_listener *listener, void *data)
{
......
if (compositor->session_active) {
weston_log("activating session\n");
......
b->state_invalid = true;
......
} else {
weston_log("deactivating session\n");
......
- When the scheduling timer exits the schedule state, it will still submit an null atomic that does not include crtc and plane requests to drm.
static int
output_repaint_timer_handler(void *data)
{
......
wl_list_for_each(output, &compositor->output_list, link) {
ret = weston_output_maybe_repaint(output, &now, repaint_data); // ret = 0, no repaint
if (ret)
break;
}
if (ret == 0) {
if (compositor->backend->repaint_flush)
ret = compositor->backend->repaint_flush(compositor,
repaint_data); //flush repaint , drmModeAtomicCommit no crtc/plane request
......
output_repaint_timer_arm(compositor);
return 0;
}
-
If the session signal event comes earlier than the scheduled timer event. The following will happen:
1.b->state_invalid = true;
2.output_repaint_timer_handler commit null atomic;
3.flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;
4.page flip event signal;
5.drm-backend.so assert fail and crash;
static int
drm_pending_state_apply_atomic(struct drm_pending_state *pending_state,
enum drm_state_apply_mode mode)
{
......
if (b->state_invalid) { // session active happened before
......
flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;
}
wl_list_for_each(output_state, &pending_state->output_list, link) { // output_list is null, no repaint
......
ret |= drm_output_apply_state_atomic(output_state, req, &flags);
}
......
ret = drmModeAtomicCommit(b->drm.fd, req, flags, b); //this commit will trigger a page flip event
......
wl_list_for_each_safe(output_state, tmp, &pending_state->output_list,
link) // output_list is null, output->page_flip_pending will not be set
drm_output_assign_state(output_state, mode);
......
}
how to fix
weston12 has fixed this problem, if weston_output_maybe_repaint return no request, will not trigger repaint_flush.
Because this is just an occasional fault, the current analysis conclusion is only inferred based on the code. Is there any problem with this analysis?
Does weston9 has a patch for this problem? Or I refer to the logic of weston12 to modify output_repaint_timer_handler, will only modifying the logic of output_repaint_timer_handler introduce other problems?