After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 760299 - Evince crashes when using annotation + copy of pdf
Evince crashes when using annotation + copy of pdf
Status: RESOLVED FIXED
Product: evince
Classification: Core
Component: pdf annotations
git master
Other All
: High critical
: ---
Assigned To: Evince Maintainers
Evince Maintainers
: 706048 769421 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2016-01-07 23:30 UTC by Alessandro Bono
Modified: 2017-08-07 23:08 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
view: use a hashtable to map annots to their popups. (3.53 KB, patch)
2016-07-20 03:30 UTC, José Aliste
none Details | Review
view: use a hashtable to map annots to their popups. (4.82 KB, patch)
2016-07-23 20:28 UTC, José Aliste
committed Details | Review
view: Don't look for annotation windows twice (1.56 KB, patch)
2016-07-23 20:35 UTC, José Aliste
none Details | Review
view: Don't look for annotation windows twice (3.33 KB, patch)
2016-07-26 00:47 UTC, José Aliste
accepted-commit_now Details | Review

Description Alessandro Bono 2016-01-07 23:30:32 UTC
If are present unsaved annotations, Evince crashes when a copy of the pdf is opened.

Steps to reproduce:
Open a pdf
Add a annotation
Hambuger Menu -> Open a Copy

Evince crashes only if it shows a page with a unsaved annotation, for example:

Open a pdf
Add annotation to page N
Go to page N+2
Hamburger Menu -> Open a Copy
Evince doen't crash until the page N is reached.
Comment 1 Alessandro Bono 2016-01-07 23:39:24 UTC
Actually it doesn't matter if the annotations are unsaved. It crashes when it shows the same annotation from two "copy" of the same file.
Comment 2 Germán Poo-Caamaño 2016-01-07 23:49:15 UTC
I can reproduce it. However, when I create the annotation with Evince. If I open a document with annotations created with another application it works as expected. Although, I have not tried with highlighting.
Comment 3 Germán Poo-Caamaño 2016-01-08 20:19:58 UTC
Here the backtrace from evince (4405f3e) and poppler master (01d4bb2):

(gdb) bt
  • #0 ev_view_window_child_move_with_parent
    at ev-view.c line 2926
  • #1 show_annotation_windows
    at ev-view.c line 3152
  • #2 ev_view_draw
    at ev-view.c line 4573
  • #3 _gtk_marshal_BOOLEAN__BOXEDv
    at gtkmarshalers.c line 130
  • #4 gtk_widget_draw_marshallerv
    at gtkwidget.c line 1097
  • #5 _g_closure_invoke_va
    at gclosure.c line 867
  • #6 g_signal_emit_valist
    at gsignal.c line 3294
  • #7 g_signal_emit
    at gsignal.c line 3441
  • #8 _gtk_widget_draw_internal
    at gtkwidget.c line 6964
  • #9 _gtk_widget_draw_internal
    at gtkwidget.c line 6942
  • #10 _gtk_widget_draw_windows
    at gtkwidget.c line 7065
  • #11 _gtk_widget_draw
    at gtkwidget.c line 7136
  • #12 gtk_container_propagate_draw
    at gtkcontainer.c line 3704
  • #13 gtk_container_draw
    at gtkcontainer.c line 3539
  • #14 gtk_scrolled_window_draw
    at gtkscrolledwindow.c line 2232
  • #15 _gtk_marshal_BOOLEAN__BOXEDv
    at gtkmarshalers.c line 130
  • #16 gtk_widget_draw_marshallerv
    at gtkwidget.c line 1097
  • #17 _g_closure_invoke_va
    at gclosure.c line 867
  • #18 g_signal_emit_valist
    at gsignal.c line 3294
  • #19 g_signal_emit
    at gsignal.c line 3441
  • #20 _gtk_widget_draw_internal
    at gtkwidget.c line 6964
  • #21 _gtk_widget_draw_internal
    at gtkwidget.c line 6942
  • #22 _gtk_widget_draw_windows
    at gtkwidget.c line 7065
  • #23 _gtk_widget_draw
    at gtkwidget.c line 7136
  • #24 gtk_container_propagate_draw
    at gtkcontainer.c line 3704
  • #25 gtk_container_draw
    at gtkcontainer.c line 3539
  • #26 _gtk_marshal_BOOLEAN__BOXEDv
    at gtkmarshalers.c line 130
  • #27 gtk_widget_draw_marshallerv
    at gtkwidget.c line 1097
  • #28 _g_closure_invoke_va
    at gclosure.c line 867
  • #29 g_signal_emit_valist
    at gsignal.c line 3294
  • #30 g_signal_emit
    at gsignal.c line 3441
  • #31 _gtk_widget_draw_internal
    at gtkwidget.c line 6964
  • #32 _gtk_widget_draw_internal
    at gtkwidget.c line 7151
  • #33 _gtk_widget_draw
    at gtkwidget.c line 7142
  • #34 gtk_container_propagate_draw
    at gtkcontainer.c line 3704
  • #35 gtk_container_draw
    at gtkcontainer.c line 3539
  • #36 gtk_box_draw
    at gtkbox.c line 447
  • #37 _gtk_marshal_BOOLEAN__BOXEDv
    at gtkmarshalers.c line 130
  • #38 gtk_widget_draw_marshallerv
    at gtkwidget.c line 1097
  • #39 _g_closure_invoke_va
    at gclosure.c line 867
  • #40 g_signal_emit_valist
    at gsignal.c line 3294
  • #41 g_signal_emit
    at gsignal.c line 3441
  • #42 _gtk_widget_draw_internal
    at gtkwidget.c line 6964
  • #43 _gtk_widget_draw_internal
    at gtkwidget.c line 7151
  • #44 _gtk_widget_draw
    at gtkwidget.c line 7142
  • #45 gtk_container_propagate_draw
    at gtkcontainer.c line 3704
  • #46 gtk_container_draw
    at gtkcontainer.c line 3539
  • #47 gtk_paned_draw
    at gtkpaned.c line 1756
  • #48 _gtk_marshal_BOOLEAN__BOXEDv
    at gtkmarshalers.c line 130
  • #49 gtk_widget_draw_marshallerv
    at gtkwidget.c line 1097
  • #50 _g_closure_invoke_va
    at gclosure.c line 867
  • #51 g_signal_emit_valist
    at gsignal.c line 3294
  • #52 g_signal_emit
    at gsignal.c line 3441
  • #53 _gtk_widget_draw_internal
    at gtkwidget.c line 6964
  • #54 _gtk_widget_draw_internal
    at gtkwidget.c line 6942
  • #55 _gtk_widget_draw_windows
    at gtkwidget.c line 7065
  • #56 _gtk_widget_draw
    at gtkwidget.c line 7161
  • #57 gtk_container_propagate_draw
    at gtkcontainer.c line 3704
  • #58 gtk_container_draw
    at gtkcontainer.c line 3539
  • #59 gtk_box_draw
    at gtkbox.c line 447
  • #60 _gtk_marshal_BOOLEAN__BOXEDv
    at gtkmarshalers.c line 130
  • #61 gtk_widget_draw_marshallerv
    at gtkwidget.c line 1097
  • #62 _g_closure_invoke_va
    at gclosure.c line 867
  • #63 g_signal_emit_valist
    at gsignal.c line 3294
  • #64 g_signal_emit
    at gsignal.c line 3441
  • #65 _gtk_widget_draw_internal
    at gtkwidget.c line 6964
  • #66 _gtk_widget_draw_internal
    at gtkwidget.c line 7151
  • #67 _gtk_widget_draw
    at gtkwidget.c line 7142
  • #68 gtk_container_propagate_draw
    at gtkcontainer.c line 3704
  • #69 gtk_container_draw
    at gtkcontainer.c line 3539
  • #70 gtk_window_draw
    at gtkwindow.c line 9761
  • #71 _gtk_marshal_BOOLEAN__BOXEDv
    at gtkmarshalers.c line 130
  • #72 gtk_widget_draw_marshallerv
    at gtkwidget.c line 1097
  • #73 _g_closure_invoke_va
    at gclosure.c line 867
  • #74 g_signal_emit_valist
    at gsignal.c line 3294
  • #75 g_signal_emit
    at gsignal.c line 3441
  • #76 _gtk_widget_draw_internal
    at gtkwidget.c line 6964
  • #77 _gtk_widget_draw_internal
    at gtkwidget.c line 6942
  • #78 _gtk_widget_draw_windows
    at gtkwidget.c line 7065
  • #79 _gtk_widget_draw
    at gtkwidget.c line 7136
  • #80 gtk_widget_send_expose
    at gtkwidget.c line 7616
  • #81 gtk_main_do_event
    at gtkmain.c line 1673
  • #82 _gdk_window_process_updates_recurse_helper
    at gdkwindow.c line 3556
  • #83 gdk_window_process_updates_internal
    at gdkwindow.c line 3681
  • #84 gdk_window_process_updates_with_mode
    at gdkwindow.c line 3882
  • #85 _g_closure_invoke_va
    at gclosure.c line 867
  • #86 g_signal_emit_valist
    at gsignal.c line 3294
  • #87 g_signal_emit_by_name
    at gsignal.c line 3481
  • #88 gdk_frame_clock_paint_idle
    at gdkframeclockidle.c line 430
  • #89 gdk_threads_dispatch
    at gdk.c line 719
  • #90 g_timeout_dispatch
    at gmain.c line 4577
  • #91 g_main_dispatch
    at gmain.c line 3154
  • #92 g_main_context_dispatch
    at gmain.c line 3769
  • #93 g_main_context_iterate
    at gmain.c line 3840
  • #94 g_main_context_iteration
    at gmain.c line 3901
  • #95 g_application_run
    at gapplication.c line 2322
  • #96 main
    at main.c line 316

Comment 4 José Aliste 2016-07-19 12:04:51 UTC
This is a hard to fix issue... Annotations related objects live inside EvDocument.. which is shared by the two copies of EvView widgets... Unfortunately, these annotations objects have backlinks to the corresponding Annotation Widgets (like the popup window)... which is obiously wrong as this object only is valid for one of the two EvView widgets... Hence you get a crash.
Comment 5 Germán Poo-Caamaño 2016-07-19 15:19:14 UTC
José,

But the problem also happens if the document only have highlight annotations. I understand that such annotations can have a text message (with a window), but do we create the windows with such annotation in spite they do not have anything yet?
Comment 6 Germán Poo-Caamaño 2016-07-19 15:21:08 UTC
Possibly related to Bug 706048
Comment 7 José Aliste 2016-07-19 15:30:33 UTC
German, I think you are right and we create the annotation window for them. Look at the stacktrace. We are crashing in in show_annotation_windows()... This will look for the pointers saved in EvDocument (to widgets inside one EvView) and will try to show them on the other EvView.
Comment 8 José Aliste 2016-07-19 15:36:52 UTC
*** Bug 706048 has been marked as a duplicate of this bug. ***
Comment 9 José Aliste 2016-07-20 03:30:48 UTC
Created attachment 331799 [details] [review]
view: use a hashtable to map annots to their popups.

This prevents a crash when using "Open Copy" function
because the popup is set to a window widget which is a child of another
EvView.
Comment 10 José Aliste 2016-07-20 03:33:43 UTC
The previous patch solves the issue. It looked to me that using a HashTable was the easiest workaround to the direct map used by g_object_get_data and g_object_set_data
Comment 11 Germán Poo-Caamaño 2016-07-21 06:00:54 UTC
Review of attachment 331799 [details] [review]:

It works for me in the sense that it does not crashes anymore.

I may have found another bug, though. Likely unrelated, but I comment it here just in case:

1. Open a document (D)
2. Add an annotation.
3. Open a copy of the document (C)
4. In (C) add an annotation.
5. Go back to (D)
6. Press Ctrl+R to reload the document.
==> The annotations are gone in (D).
Comment 12 Germán Poo-Caamaño 2016-07-21 06:02:42 UTC
Additionally:

7. Close (D) => segfault.
Comment 13 Germán Poo-Caamaño 2016-07-21 06:04:29 UTC
Hmm.. I tried to get a stacktrace but I was unable to reproduce the step 7 :-/
Comment 14 José Aliste 2016-07-21 16:20:29 UTC
The bug about annotations dissapearing when reloading the page is unrelated to this bug... It occurs also on unpatched version of evince. I will provide a patch shortly for this as well.
Comment 15 Carlos Garcia Campos 2016-07-23 09:05:21 UTC
Review of attachment 331799 [details] [review]:

This makes sense, the annot windows are something that belongs to the view and not to the document.

::: libview/ev-view.c
@@ +3111,3 @@
 				  G_CALLBACK (ev_view_annotation_save_contents),
 				  view);
+	g_hash_table_replace (view->annot_window_map, annot, window);

There's no point in using replace, I think, since the map doesn't own neither the key nor the value, if it already exists (something that shouldn't happen anyway) it's fine to use the existing key.

@@ +3162,3 @@
 		if (window) {
 			ev_annotation_window_set_annotation (EV_ANNOTATION_WINDOW (window), annot);
+			g_hash_table_replace (view->annot_window_map, annot, window);

Ditto.

@@ +6828,3 @@
 		g_object_unref (view->image_dnd_info.image);
 	view->image_dnd_info.image = NULL;
+	g_hash_table_destroy (view->annot_window_map);

You should also remove from the map the deleted annotations, in ev_view_remove_annotation() probably.

@@ +7715,3 @@
 	view->zoom_center_x = -1;
 	view->zoom_center_y = -1;
+	view->annot_window_map = g_hash_table_new (NULL, NULL);

I think we could create this on demand, for documents without annots, or never adding an annot we don't really need this. We could add a helper method that gets or creates the map. I also prefer to pass the hash function explicitly, g_direct_hash in this case, so that you don't need to think what NULL, NULL means. It's fine to pass NULL as the equal, though, because you already know it's direct hash and not using a function is a little bit more efficient.
Comment 16 Carlos Garcia Campos 2016-07-23 09:06:03 UTC
(In reply to Germán Poo-Caamaño from comment #11)
> Review of attachment 331799 [details] [review] [review]:
> 
> It works for me in the sense that it does not crashes anymore.
> 
> I may have found another bug, though. Likely unrelated, but I comment it
> here just in case:
> 
> 1. Open a document (D)
> 2. Add an annotation.
> 3. Open a copy of the document (C)
> 4. In (C) add an annotation.
> 5. Go back to (D)
> 6. Press Ctrl+R to reload the document.
> ==> The annotations are gone in (D).

Yes, the whole open a copy feature is indeed tricky.
Comment 17 José Aliste 2016-07-23 20:28:29 UTC
Created attachment 332028 [details] [review]
view: use a hashtable to map annots to their popups.

This prevents a crash when using "Open Copy" function
because the popup is set to a window widget which is a child of another
EvView.
Comment 18 José Aliste 2016-07-23 20:29:42 UTC
updated patch according to review. added to helper function that make things easier to read I think and create the hashtable on demand
Comment 19 José Aliste 2016-07-23 20:35:16 UTC
Created attachment 332029 [details] [review]
view: Don't look for annotation windows twice

The only way to create an annotation window is through
create_annotation_window. As this function always set
the annot_window_map, we can always use this map to get the annotation
window.
Comment 20 José Aliste 2016-07-23 20:38:19 UTC
actually I also think that we can remove all these lines after applying the first patch...
Comment 21 Germán Poo-Caamaño 2016-07-23 22:14:43 UTC
(In reply to José Aliste from comment #14)
> The bug about annotations dissapearing when reloading the page is unrelated
> to this bug... It occurs also on unpatched version of evince. I will provide
> a patch shortly for this as well.

I filed a new bug. See Bug 769123
Comment 22 Carlos Garcia Campos 2016-07-25 15:19:34 UTC
Review of attachment 332028 [details] [review]:

LGTM, thanks!
Comment 23 Carlos Garcia Campos 2016-07-25 15:23:43 UTC
Comment on attachment 332029 [details] [review]
view: Don't look for annotation windows twice

Do we still need ev_view_find_window_child_for_annot then?
Comment 24 José Aliste 2016-07-25 23:45:24 UTC
(In reply to Carlos Garcia Campos from comment #23)
> Comment on attachment 332029 [details] [review] [review]
> view: Don't look for annotation windows twice
> 
> Do we still need ev_view_find_window_child_for_annot then?

We still use it once... We look for the window child only to remove it... We could change the func to ev_view_remove_window_child_for_annot and remove the link directly from there. This would be a bit more efficient since we wouldn't traverse the list twice.
Comment 25 José Aliste 2016-07-26 00:47:44 UTC
Created attachment 332124 [details] [review]
view: Don't look for annotation windows twice

The only way to create an annotation window is through
create_annotation_window. As this function always set
the annot_window_map, we can always use this map to get the annotation
window.
Comment 26 José Aliste 2016-07-26 00:48:58 UTC
Here is the new patch that does what I say in the previous comment. It tested out fine...
Comment 27 José Aliste 2016-07-26 17:25:22 UTC
Review of attachment 332028 [details] [review]:

Thanks
Comment 28 José Aliste 2016-08-02 13:37:15 UTC
*** Bug 769421 has been marked as a duplicate of this bug. ***
Comment 29 Carlos Garcia Campos 2016-09-03 06:44:36 UTC
Comment on attachment 332124 [details] [review]
view: Don't look for annotation windows twice

I had forgotten this, sorry. Feel free to push it then.
Comment 30 Germán Poo-Caamaño 2016-09-28 16:01:13 UTC
The following fix has been pushed:
3663591 view: Don't look for annotation windows twice
Comment 31 Christian Stadelmann 2017-08-07 23:08:13 UTC
(In reply to Germán Poo-Caamaño from comment #30)
> The following fix has been pushed:
> 3663591 view: Don't look for annotation windows twice

(In reply to Carlos Garcia Campos from comment #29)
> Comment on attachment 332124 [details] [review] [review]
> view: Don't look for annotation windows twice
> 
> I had forgotten this, sorry. Feel free to push it then.

This fix causes another bug leading to a busy loop in Evince. See https://bugzilla.gnome.org/show_bug.cgi?id=785975 for details.