Commit caccb94c authored by Pavel Borzenkov's avatar Pavel Borzenkov Committed by Sebastian Ramacher
Browse files

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: default avatarPavel Borzenkov <pavel.borzenkov@gmail.com>
parent 333cfa4d
......@@ -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);
}
......
......@@ -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);
}
......
......@@ -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++)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment