mirror of
https://github.com/hyprwm/wlroots-hyprland.git
synced 2024-11-26 14:45:58 +01:00
Add timeout to DRM cleanup
This prevents a potential infinite loop preventing us from closing properly.
This commit is contained in:
parent
8cbade355f
commit
459d138fa2
3 changed files with 46 additions and 27 deletions
|
@ -26,6 +26,9 @@ static void wlr_drm_backend_destroy(struct wlr_backend *_backend) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
struct wlr_drm_backend *backend = (struct wlr_drm_backend *)_backend;
|
struct wlr_drm_backend *backend = (struct wlr_drm_backend *)_backend;
|
||||||
|
|
||||||
|
wlr_drm_restore_outputs(backend);
|
||||||
|
|
||||||
for (size_t i = 0; backend->outputs && i < backend->outputs->length; ++i) {
|
for (size_t i = 0; backend->outputs && i < backend->outputs->length; ++i) {
|
||||||
struct wlr_drm_output *output = backend->outputs->items[i];
|
struct wlr_drm_output *output = backend->outputs->items[i];
|
||||||
wlr_output_destroy(&output->output);
|
wlr_output_destroy(&output->output);
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <time.h>
|
||||||
#include <xf86drm.h>
|
#include <xf86drm.h>
|
||||||
#include <xf86drmMode.h>
|
#include <xf86drmMode.h>
|
||||||
#include <drm_mode.h>
|
#include <drm_mode.h>
|
||||||
|
@ -556,7 +557,7 @@ error_enc:
|
||||||
error_conn:
|
error_conn:
|
||||||
drmModeFreeConnector(conn);
|
drmModeFreeConnector(conn);
|
||||||
error_output:
|
error_output:
|
||||||
wlr_drm_output_cleanup(output, false);
|
wlr_drm_output_cleanup(output);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -703,7 +704,7 @@ static bool wlr_drm_output_move_cursor(struct wlr_output *_output,
|
||||||
|
|
||||||
static void wlr_drm_output_destroy(struct wlr_output *_output) {
|
static void wlr_drm_output_destroy(struct wlr_output *_output) {
|
||||||
struct wlr_drm_output *output = (struct wlr_drm_output *)_output;
|
struct wlr_drm_output *output = (struct wlr_drm_output *)_output;
|
||||||
wlr_drm_output_cleanup(output, true);
|
wlr_drm_output_cleanup(output);
|
||||||
free(output);
|
free(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -852,7 +853,7 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) {
|
||||||
conn->connection != DRM_MODE_CONNECTED) {
|
conn->connection != DRM_MODE_CONNECTED) {
|
||||||
|
|
||||||
wlr_log(L_INFO, "'%s' disconnected", output->output.name);
|
wlr_log(L_INFO, "'%s' disconnected", output->output.name);
|
||||||
wlr_drm_output_cleanup(output, false);
|
wlr_drm_output_cleanup(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
drmModeFreeConnector(conn);
|
drmModeFreeConnector(conn);
|
||||||
|
@ -868,7 +869,7 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) {
|
||||||
struct wlr_drm_output *output = backend->outputs->items[i];
|
struct wlr_drm_output *output = backend->outputs->items[i];
|
||||||
|
|
||||||
wlr_log(L_INFO, "'%s' disappeared", output->output.name);
|
wlr_log(L_INFO, "'%s' disappeared", output->output.name);
|
||||||
wlr_drm_output_cleanup(output, false);
|
wlr_drm_output_cleanup(output);
|
||||||
|
|
||||||
drmModeFreeCrtc(output->old_crtc);
|
drmModeFreeCrtc(output->old_crtc);
|
||||||
free(output);
|
free(output);
|
||||||
|
@ -909,23 +910,46 @@ int wlr_drm_event(int fd, uint32_t mask, void *data) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void restore_output(struct wlr_drm_output *output, int fd) {
|
void wlr_drm_restore_outputs(struct wlr_drm_backend *drm) {
|
||||||
// Wait for any pending pageflips to finish
|
uint64_t to_close = (1 << drm->outputs->length) - 1;
|
||||||
while (output->pageflip_pending) {
|
|
||||||
wlr_drm_event(fd, 0, NULL);
|
for (size_t i = 0; i < drm->outputs->length; ++i) {
|
||||||
|
struct wlr_drm_output *output = drm->outputs->items[i];
|
||||||
|
if (output->state == WLR_DRM_OUTPUT_CONNECTED) {
|
||||||
|
output->state = WLR_DRM_OUTPUT_CLEANUP;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
time_t timeout = time(NULL) + 5;
|
||||||
|
|
||||||
|
while (to_close && time(NULL) < timeout) {
|
||||||
|
wlr_drm_event(drm->fd, 0, NULL);
|
||||||
|
for (size_t i = 0; i < drm->outputs->length; ++i) {
|
||||||
|
struct wlr_drm_output *output = drm->outputs->items[i];
|
||||||
|
if (!output->pageflip_pending) {
|
||||||
|
to_close &= ~(1 << i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (to_close) {
|
||||||
|
wlr_log(L_ERROR, "Timed out stopping output renderers");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < drm->outputs->length; ++i) {
|
||||||
|
struct wlr_drm_output *output = drm->outputs->items[i];
|
||||||
drmModeCrtc *crtc = output->old_crtc;
|
drmModeCrtc *crtc = output->old_crtc;
|
||||||
if (!crtc) {
|
if (!crtc) {
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
drmModeSetCrtc(fd, crtc->crtc_id, crtc->buffer_id, crtc->x, crtc->y,
|
drmModeSetCrtc(drm->fd, crtc->crtc_id, crtc->buffer_id, crtc->x, crtc->y,
|
||||||
&output->connector, 1, &crtc->mode);
|
&output->connector, 1, &crtc->mode);
|
||||||
drmModeFreeCrtc(crtc);
|
drmModeFreeCrtc(crtc);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void wlr_drm_output_cleanup(struct wlr_drm_output *output, bool restore) {
|
void wlr_drm_output_cleanup(struct wlr_drm_output *output) {
|
||||||
if (!output) {
|
if (!output) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -936,12 +960,7 @@ void wlr_drm_output_cleanup(struct wlr_drm_output *output, bool restore) {
|
||||||
|
|
||||||
switch (output->state) {
|
switch (output->state) {
|
||||||
case WLR_DRM_OUTPUT_CONNECTED:
|
case WLR_DRM_OUTPUT_CONNECTED:
|
||||||
output->state = WLR_DRM_OUTPUT_DISCONNECTED;
|
case WLR_DRM_OUTPUT_CLEANUP:;
|
||||||
if (restore) {
|
|
||||||
restore_output(output, renderer->fd);
|
|
||||||
restore = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_drm_crtc *crtc = output->crtc;
|
struct wlr_drm_crtc *crtc = output->crtc;
|
||||||
for (int i = 0; i < 3; ++i) {
|
for (int i = 0; i < 3; ++i) {
|
||||||
wlr_drm_plane_renderer_free(renderer, crtc->planes[i]);
|
wlr_drm_plane_renderer_free(renderer, crtc->planes[i]);
|
||||||
|
@ -955,10 +974,6 @@ void wlr_drm_output_cleanup(struct wlr_drm_output *output, bool restore) {
|
||||||
output->possible_crtc = 0;
|
output->possible_crtc = 0;
|
||||||
/* Fallthrough */
|
/* Fallthrough */
|
||||||
case WLR_DRM_OUTPUT_NEEDS_MODESET:
|
case WLR_DRM_OUTPUT_NEEDS_MODESET:
|
||||||
output->state = WLR_DRM_OUTPUT_DISCONNECTED;
|
|
||||||
if (restore) {
|
|
||||||
restore_output(output, renderer->fd);
|
|
||||||
}
|
|
||||||
wlr_log(L_INFO, "Emmiting destruction signal for '%s'",
|
wlr_log(L_INFO, "Emmiting destruction signal for '%s'",
|
||||||
output->output.name);
|
output->output.name);
|
||||||
wl_signal_emit(&backend->backend.events.output_remove, &output->output);
|
wl_signal_emit(&backend->backend.events.output_remove, &output->output);
|
||||||
|
|
|
@ -127,6 +127,7 @@ struct wlr_drm_backend {
|
||||||
enum wlr_drm_output_state {
|
enum wlr_drm_output_state {
|
||||||
WLR_DRM_OUTPUT_DISCONNECTED,
|
WLR_DRM_OUTPUT_DISCONNECTED,
|
||||||
WLR_DRM_OUTPUT_NEEDS_MODESET,
|
WLR_DRM_OUTPUT_NEEDS_MODESET,
|
||||||
|
WLR_DRM_OUTPUT_CLEANUP,
|
||||||
WLR_DRM_OUTPUT_CONNECTED,
|
WLR_DRM_OUTPUT_CONNECTED,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -176,8 +177,8 @@ struct wlr_drm_interface {
|
||||||
bool wlr_drm_check_features(struct wlr_drm_backend *drm);
|
bool wlr_drm_check_features(struct wlr_drm_backend *drm);
|
||||||
bool wlr_drm_resources_init(struct wlr_drm_backend *drm);
|
bool wlr_drm_resources_init(struct wlr_drm_backend *drm);
|
||||||
void wlr_drm_resources_free(struct wlr_drm_backend *drm);
|
void wlr_drm_resources_free(struct wlr_drm_backend *drm);
|
||||||
void wlr_drm_output_cleanup(struct wlr_drm_output *output, bool restore);
|
void wlr_drm_restore_outputs(struct wlr_drm_backend *drm);
|
||||||
|
void wlr_drm_output_cleanup(struct wlr_drm_output *output);
|
||||||
void wlr_drm_scan_connectors(struct wlr_drm_backend *state);
|
void wlr_drm_scan_connectors(struct wlr_drm_backend *state);
|
||||||
int wlr_drm_event(int fd, uint32_t mask, void *data);
|
int wlr_drm_event(int fd, uint32_t mask, void *data);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue