From caccb94c6909f99d5f6ef939b1820aa9efa753c6 Mon Sep 17 00:00:00 2001 From: Pavel Borzenkov Date: Thu, 21 Jul 2011 16:39:25 +0400 Subject: [PATCH] Fix ':close' command Currently, zathura crashes while performing ':close' command with the following error: GThread-ERROR **: file gthread-posix.c: line 226 (g_cond_free_posix_impl): error 'Device or resource busy' during 'pthread_cond_destroy ((pthread_cond_t *) cond)' The error is because 'render' thread holds condition variable while waiting for new pages to render. This patch modifies zathura's code to correctly kill render thread and free allocated resources when the document is being closed. NOTE: should be applied on top of "Allow changing of "pages-per-row" variable at runtime" commit to avoid conflicts in the 'page_view_set_mode()' function. Signed-off-by: Pavel Borzenkov --- document.c | 3 +++ render.c | 13 +++++++++++++ zathura.c | 29 ++++++++++++++++++----------- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/document.c b/document.c index 761113a..55cdef9 100644 --- a/document.c +++ b/document.c @@ -305,6 +305,7 @@ zathura_document_free(zathura_document_t* document) for (unsigned int page_id = 0; page_id < document->number_of_pages; page_id++) { zathura_page_free(document->pages[page_id]); + document->pages[page_id] = NULL; } free(document->pages); @@ -427,6 +428,8 @@ zathura_page_free(zathura_page_t* page) return false; } + g_static_mutex_free(&(page->lock)); + return page->document->functions.page_free(page); } diff --git a/render.c b/render.c index 16c129a..16c0a4c 100644 --- a/render.c +++ b/render.c @@ -17,6 +17,17 @@ render_job(void* data) g_cond_wait(render_thread->cond, render_thread->lock); } + if (girara_list_size(render_thread->list) <= 0) { + /* + * We've been signaled with g_cond_signal(), but the list + * is still empty. This means that the signal came from + * render_free() and current document is being closed. + * We should unlock the mutex and kill the thread. + */ + g_mutex_unlock(render_thread->lock); + g_thread_exit(0); + } + zathura_page_t* page = (zathura_page_t*) girara_list_nth(render_thread->list, 0); girara_list_remove(render_thread->list, page); g_mutex_unlock(render_thread->lock); @@ -104,6 +115,8 @@ render_free(render_thread_t* render_thread) } if (render_thread->cond) { + g_cond_signal(render_thread->cond); + g_thread_join(render_thread->thread); g_cond_free(render_thread->cond); } diff --git a/zathura.c b/zathura.c index 5b0bf1a..dba3d87 100644 --- a/zathura.c +++ b/zathura.c @@ -308,6 +308,16 @@ error_out: return false; } +static void +remove_page_from_table(GtkWidget* page, gpointer permanent) +{ + if (!permanent) { + g_object_ref(G_OBJECT(page)); + } + + gtk_container_remove(GTK_CONTAINER(page->parent), page); +} + bool document_close(zathura_t* zathura) { @@ -315,11 +325,15 @@ document_close(zathura_t* zathura) return false; } - if (zathura->sync.render_thread) { - render_free(zathura->sync.render_thread); - } + render_free(zathura->sync.render_thread); + zathura->sync.render_thread = NULL; + + gtk_container_foreach(GTK_CONTAINER(zathura->ui.page_view), remove_page_from_table, (gpointer)1); zathura_document_free(zathura->document); + zathura->document = NULL; + + gtk_widget_hide_all(zathura->ui.page_view); return true; } @@ -378,8 +392,6 @@ statusbar_page_number_update(zathura_t* zathura) void page_view_set_mode(zathura_t* zathura, unsigned int pages_per_row) { - GList* child; - /* show at least one page */ if (pages_per_row == 0) { pages_per_row = 1; @@ -389,12 +401,7 @@ page_view_set_mode(zathura_t* zathura, unsigned int pages_per_row) return; } - child = gtk_container_get_children(GTK_CONTAINER(zathura->ui.page_view)); - while (child) { - g_object_ref(G_OBJECT(child->data)); - gtk_container_remove(GTK_CONTAINER(zathura->ui.page_view), GTK_WIDGET(child->data)); - child = g_list_next(child); - } + gtk_container_foreach(GTK_CONTAINER(zathura->ui.page_view), remove_page_from_table, (gpointer)0); gtk_table_resize(GTK_TABLE(zathura->ui.page_view), zathura->document->number_of_pages / pages_per_row + 1, pages_per_row); for (unsigned int i = 0; i < zathura->document->number_of_pages; i++)