Check cast instance refcount before attaching

This commit is contained in:
Dan Shick 2020-04-20 11:05:08 -04:00 committed by Simon Ser
parent 55f873dac4
commit f6d14d9206
5 changed files with 31 additions and 18 deletions

View file

@ -78,14 +78,14 @@ int main(int argc, char *argv[]) {
logprint(ERROR, "dbus: failed to connect to user bus: %s", strerror(-ret));
goto error;
}
logprint(TRACE, "dbus: connected");
logprint(DEBUG, "dbus: connected");
struct wl_display *wl_display = wl_display_connect(NULL);
if (!wl_display) {
logprint(ERROR, "wayland: failed to connect to display");
goto error;
}
logprint(TRACE, "wlroots: wl_display connected");
logprint(DEBUG, "wlroots: wl_display connected");
pw_init(NULL, NULL);
struct pw_loop *pw_loop = pw_loop_new(NULL);
@ -93,7 +93,7 @@ int main(int argc, char *argv[]) {
logprint(ERROR, "pipewire: failed to create loop");
goto error;
}
logprint(TRACE, "pipewire: pw_loop created");
logprint(DEBUG, "pipewire: pw_loop created");
struct xdpw_state state = {
.bus = bus,

View file

@ -57,7 +57,7 @@ struct xdpw_session *xdpw_session_create(struct xdpw_state *state, sd_bus *bus,
}
void xdpw_session_destroy(struct xdpw_session *sess) {
logprint(TRACE, "dbus: destroying session");
logprint(DEBUG, "dbus: destroying session %p", sess);
if (!sess) {
return;
}
@ -65,7 +65,8 @@ void xdpw_session_destroy(struct xdpw_session *sess) {
if (cast) {
assert(cast->refcount > 0);
--cast->refcount;
logprint(INFO, "xdpw: screencast instance %p has %d references", cast, cast->refcount);
logprint(DEBUG, "xdpw: screencast instance %p now has %d references",
cast, cast->refcount);
if (cast->refcount < 1) {
cast->quit = true;
}

View file

@ -161,7 +161,7 @@ void xdpw_pwr_stream_init(struct xdpw_screencast_instance *cast) {
/* make an event to signal frame ready */
cast->event =
pw_loop_add_event(state->pw_loop, pwr_on_event, cast);
logprint(TRACE, "pipewire: registered event %p", cast->event);
logprint(DEBUG, "pipewire: registered event %p", cast->event);
params[0] = spa_pod_builder_add_object(&b,
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
@ -194,7 +194,7 @@ void xdpw_pwr_stream_init(struct xdpw_screencast_instance *cast) {
int xdpw_pwr_core_connect(struct xdpw_state *state) {
struct xdpw_screencast_context *ctx = &state->screencast;
logprint(TRACE, "pipewire: establishing connection to core");
logprint(DEBUG, "pipewire: establishing connection to core");
if (!ctx->pwr_context) {
ctx->pwr_context = pw_context_new(state->pw_loop, NULL, 0);
@ -215,7 +215,7 @@ int xdpw_pwr_core_connect(struct xdpw_state *state) {
}
void xdpw_pwr_stream_destroy(struct xdpw_screencast_instance *cast) {
logprint(TRACE, "pipewire: destroying stream");
logprint(DEBUG, "pipewire: destroying stream");
pw_stream_flush(cast->stream, false);
pw_stream_disconnect(cast->stream);
pw_stream_destroy(cast->stream);

View file

@ -34,8 +34,8 @@ void xdpw_screencast_instance_init(struct xdpw_screencast_context *ctx,
}
void xdpw_screencast_instance_destroy(struct xdpw_screencast_instance *cast) {
assert(cast->refcount == 0);
logprint(TRACE, "xdpw: destroying cast instance");
assert(cast->refcount == 0); // Fails assert if called by screencast_finish
logprint(DEBUG, "xdpw: destroying cast instance");
wl_list_remove(&cast->link);
xdpw_pwr_stream_destroy(cast);
free(cast);
@ -71,9 +71,17 @@ int setup_outputs(struct xdpw_screencast_context *ctx, struct xdpw_session *sess
cast->with_cursor ? "with" : "without");
if (cast->target_output->id == out->id && cast->with_cursor == with_cursor) {
if (cast->refcount == 0) {
logprint(DEBUG,
"xdpw: matching cast instance found, "
"but is already scheduled for destruction, skipping");
}
else {
sess->screencast_instance = cast;
++cast->refcount;
logprint(INFO, "xdpw: screencast instance %p has %d references", cast, cast->refcount);
}
logprint(INFO, "xdpw: screencast instance %p now has %d references",
cast, cast->refcount);
}
}
@ -270,7 +278,7 @@ static int method_screencast_select_sources(sd_bus_message *msg, void *data,
ret = -1;
wl_list_for_each_reverse_safe(sess, tmp_s, &state->xdpw_sessions, link) {
if (strcmp(sess->session_handle, session_handle) == 0) {
logprint(TRACE, "dbus: select sources: found matching session %s", sess->session_handle);
logprint(DEBUG, "dbus: select sources: found matching session %s", sess->session_handle);
ret = setup_outputs(ctx, sess, cursor_embedded);
}
}
@ -296,7 +304,7 @@ static int method_screencast_select_sources(sd_bus_message *msg, void *data,
error:
wl_list_for_each_reverse_safe(sess, tmp_s, &state->xdpw_sessions, link) {
if (strcmp(sess->session_handle, session_handle) == 0) {
logprint(TRACE, "dbus: select sources error: destroying matching session %s", sess->session_handle);
logprint(DEBUG, "dbus: select sources error: destroying matching session %s", sess->session_handle);
xdpw_session_destroy(sess);
}
}
@ -366,7 +374,7 @@ static int method_screencast_start(sd_bus_message *msg, void *data,
struct xdpw_session *sess, *tmp_s;
wl_list_for_each_reverse_safe(sess, tmp_s, &state->xdpw_sessions, link) {
if (strcmp(sess->session_handle, session_handle) == 0) {
logprint(TRACE, "dbus: start: found matching session %s", sess->session_handle);
logprint(DEBUG, "dbus: start: found matching session %s", sess->session_handle);
cast = sess->screencast_instance;
}
}
@ -453,6 +461,7 @@ int xdpw_screencast_init(struct xdpw_state *state, const char *output_name, cons
screencast_vtable, state);
end:
// TODO: clean up pipewire
xdpw_wlr_screencopy_finish(&state->screencast);
return err;
}

View file

@ -32,6 +32,9 @@ void xdpw_wlr_frame_free(struct xdpw_screencast_instance *cast) {
logprint(TRACE, "wlroots: frame destroyed");
if (cast->quit || cast->err) {
// TODO: revisit the exit condition (remove quit?)
// and clean up sessions that still exist if err
// is the cause of the instance_destroy call
xdpw_screencast_instance_destroy(cast);
return ;
}
@ -342,14 +345,14 @@ int xdpw_wlr_screencopy_init(struct xdpw_state *state) {
wl_display_dispatch(state->wl_display);
wl_display_roundtrip(state->wl_display);
logprint(TRACE, "wayland: registry listeners run");
logprint(DEBUG, "wayland: registry listeners run");
wlr_init_xdg_outputs(ctx);
wl_display_dispatch(state->wl_display);
wl_display_roundtrip(state->wl_display);
logprint(TRACE, "wayland: xdg output listeners run");
logprint(DEBUG, "wayland: xdg output listeners run");
// make sure our wlroots supports shm protocol
if (!ctx->shm) {