_twe_thread_tdm_source_dispatch(GSource *source, GSourceFunc cb, gpointer data)
{
twe_tdm_source *tdm_source = (twe_tdm_source *)source;
- tdm_error tdm_err;
+ tdm_error tdm_err = TDM_ERROR_NONE;
GIOCondition cond;
if (!source || g_source_is_destroyed(source)) {
if (cond & G_IO_IN) {
tdm_err = tdm_client_handle_events(tdm_source->tdm_client);
- TPL_ASSERT(tdm_err == TDM_ERROR_NONE);
+ }
+
+ /* If an error occurs in tdm_client_handle_events, it cannot be recovered.
+ * When tdm_source is no longer available due to an unexpected situation,
+ * twe_thread must remove it from the thread and destroy it.
+ * In that case, tdm_vblank can no longer be used for surfaces and displays
+ * that used this tdm_source. */
+ if (tdm_err != TDM_ERROR_NONE) {
+ TPL_ERR("Error occured in tdm_client_handle_events. tdm_err(%d)",
+ tdm_err);
+ TPL_WARN("tdm_source(%p) will be removed from thread.", tdm_source);
+
+ g_source_remove_unix_fd(&tdm_source->gsource, tdm_source->tag);
+ g_source_destroy(&tdm_source->gsource);
+ g_source_unref(&tdm_source->gsource);
+
+ _twe_ctx->tdm_source = NULL;
+
+ if (_twe_ctx->tdm_del_source) {
+ _twe_del_source_fini(_twe_ctx->tdm_del_source);
+ _twe_ctx->tdm_del_source = NULL;
+ }
+
+ return G_SOURCE_REMOVE;
}
return G_SOURCE_CONTINUE;
if (_twe_ctx->tdm_source) {
g_mutex_lock(&_twe_ctx->thread_mutex);
- if (tdm_del_source)
+ if (tdm_del_source) {
_twe_thread_del_source_trigger(tdm_del_source);
- g_cond_wait(&_twe_ctx->thread_cond, &_twe_ctx->thread_mutex);
+ g_cond_wait(&_twe_ctx->thread_cond, &_twe_ctx->thread_mutex);
+ }
g_mutex_unlock(&_twe_ctx->thread_mutex);
}