GNOME Bugzilla – Bug 735744
Crash in atk_object_notify_state_change() when using latex
Last modified: 2018-04-19 19:15:07 UTC
From donwstream bug: https://bugzilla.redhat.com/show_bug.cgi?id=1124679 Truncated backtrace: Thread no. 1 (10 frames) #0 atk_object_notify_state_change at /lib64/libatk-1.0.so.0 #1 ev_view_accessible_set_page_range at /lib64/libevview3.so.3 #2 view_update_range_and_current_page at /lib64/libevview3.so.3 #3 ev_view_size_allocate at /lib64/libevview3.so.3 #8 gtk_widget_size_allocate_with_baseline at /lib64/libgtk-3.so.0 #9 gtk_scrolled_window_allocate_child at /lib64/libgtk-3.so.0 #10 gtk_scrolled_window_size_allocate at /lib64/libgtk-3.so.0 #15 gtk_widget_size_allocate_with_baseline at /lib64/libgtk-3.so.0 #16 gtk_stack_size_allocate at /lib64/libgtk-3.so.0 #17 g_cclosure_marshal_VOID__BOXEDv at /lib64/libgobject-2.0.so.0 More information is available at the downstream bug.
there are similar report on launchpad, it's the 6th most reported issue on evince this month accross ubuntu release launchpad report on https://bugs.launchpad.net/ubuntu/+source/evince/+bug/1436555 debug bt on https://launchpadlibrarian.net/201291236/Stacktrace.txt "#0 0x00007f59f3c2bfdf in atk_object_notify_state_change (accessible=0x2601540, state=state@entry=23, value=value@entry=0) at atkobject.c:1212 __inst = 0x2601540 __t = 34575152 __r = <optimized out> name = <optimized out> __FUNCTION__ = "atk_object_notify_state_change"
+ Trace 234894
*** Bug 748049 has been marked as a duplicate of this bug. ***
*** Bug 745827 has been marked as a duplicate of this bug. ***
*** Bug 754481 has been marked as a duplicate of this bug. ***
Created attachment 313490 [details] [review] Patch from Fedora This is the patch Michel pointed in: https://bugzilla.gnome.org/show_bug.cgi?id=754481#c0 Taken from: http://pkgs.fedoraproject.org/cgit/evince.git/tree/evince-3.17.2-check-to-avoid-crash.patch
Review of attachment 313490 [details] [review]: ::: libview/ev-view-accessible.c @@ +580,2 @@ for (i = accessible->priv->start_page; i <= accessible->priv->end_page; i++) { + if ((i < start || i > end) && i < ev_view_accessible_get_n_pages (accessible)) { I don't understand how this can happen. start_page/end_page are set in this function form the given start/end values. How can be i >= n_pages? the only thing I can think of, is that n_pages is 0, but view_update_range_and_current_page() that calls this, returns early when there's no document yet, or the document contains no pages.
Hm. I get these types of crashers often when I'm recompiling a LaTeX document. So maybe the new document simply has less pages than before?
Here I am pasting I way that reproduce the issue (not always, but from time to time). It is taken from https://bugzilla.gnome.org/show_bug.cgi?id=745827#c0 with m(I should have make that the main report, anyhow). I have gotten the segfault (a couple of times), and warnings many other times. For example: (evince:4223): EvinceView-CRITICAL **: ev_page_cache_get_annot_mapping: assertion 'page >= 0 && page < cache->n_pages' failed In a relatively long document of 80 pages, if I am viewing page 60, and then if the document is rebuilt incomplete (LaTeX recompilation), I must sitting in a page that during the next building does not exist (e.g. LaTeX error compilation). Other warnings: (evince:4223): GLib-GObject-CRITICAL **: g_object_ref: assertion 'G_IS_OBJECT (object)' failed (evince:4223): GLib-GObject-CRITICAL **: g_object_unref: assertion 'G_IS_OBJECT (object)' failed ** (evince:4223): CRITICAL **: void pdf_document_get_page_size(EvDocument*, EvPage*, double*, double*): assertion 'POPPLER_IS_PAGE (page->backend_page)' failed ** (evince:4223): CRITICAL **: char* pdf_document_get_page_label(EvDocument*, EvPage*): assertion 'POPPLER_IS_PAGE (page->backend_page)' failed --- (evince:4223): Poppler-CRITICAL **: GList* poppler_page_get_annot_mapping(PopplerPage*): assertion 'POPPLER_IS_PAGE (page)' failed (evince:4223): Poppler-CRITICAL **: void poppler_page_get_size(PopplerPage*, double*, double*): assertion 'POPPLER_IS_PAGE (page)' failed --- Anyhow, the steps: 1) Make evince the default viewer for latexmk. Add the line "$pdf_previewer = 'start evince';" to your ~/.latexmkrc file. 2) Compile a reasonably large LaTeX file with "latexmk -pdf -pvc" 3) Open the file, add a LaTeX compile error somewhere in the middle and save it. 4) latexmk will automatically recompile the file and will fail on the compile error. 5) Fix the compile error, save the file again and type X into the latexmk prompt and hit Enter. 6) latexmk will compile the latex file again and this time, when evince tries to load it, it will crash. On March, the reported stated: "I've been hitting this bug constantly for a while now. It's gotten a little better in the last few weeks. It used to crash evince every time and now it only crashes it every other time or so." We may have well fixed something else that makes this a race condition.
Here is one of my stacktraces: rogram received signal SIGSEGV, Segmentation fault. 0x00007ffff6491947 in atk_object_notify_state_change (accessible=0x79612827202c6567, state=state@entry=23, value=value@entry=0) at atkobject.c:1215 1215 g_return_if_fail (ATK_IS_OBJECT (accessible)); (gdb) (gdb) (gdb) thread apply all bt
+ Trace 235595
Thread 1 (Thread 0x7ffff7fb8880 (LWP 4223))
(In reply to Carlos Garcia Campos from comment #6) > Review of attachment 313490 [details] [review] [review]: > > ::: libview/ev-view-accessible.c > @@ +580,2 @@ > for (i = accessible->priv->start_page; i <= accessible->priv->end_page; > i++) { > + if ((i < start || i > end) && i < ev_view_accessible_get_n_pages > (accessible)) { > > I don't understand how this can happen. start_page/end_page are set in this > function form the given start/end values. How can be i >= n_pages? the only > thing I can think of, is that n_pages is 0, but > view_update_range_and_current_page() that calls this, returns early when > there's no document yet, or the document contains no pages. What I got in my last segfault: start = 7 end = 8 accessible->priv->start_page = 40 accessible->priv->end_page = 40 i = 40 So, it is trying to notify a page that does not currently exists (it will in a few seconds, I think).
I think I can reproduce the issue more or less reliably. Assuming latemk is running and waiting for changes in the file, and Evince is showing the document. * For example, set Evince in page 7. * Introduce the LaTeX error somewhere in the editor. * In Evince, scroll down to a page is likely to be after the error. Because of the error, the PDF is broken. So, the first pages are shown correctly, but after the error, the pages are all blank. Evince still shows the total number of pages, etc. It just leaves the user looking a blank page (say 62). * Go back to the editor, fix the error, and save. The error I introduced was something minimal, like: \cite{Foo2000} -> \citeFoo2000} and then back to \cite{Foo2000} The thing is, in my latest segfault I was in page 62, but (gdb) p start $9 = 11 (gdb) p end $10 = 11 (gdb) p accessible->priv->start_page $11 = 61 (gdb) p accessible->priv->end_page $12 = 62 (gdb) p ev_view_accessible_get_n_pages(accessible) $13 = 16 We can either check the number of pages, of whether 'page' is not NULL. However, we could try to check something earlier. Carlos, what do you think?
(In reply to Germán Poo-Caamaño from comment #11) > I think I can reproduce the issue more or less reliably. > > Assuming latemk is running and waiting for changes in the file, and > Evince is showing the document. > > * For example, set Evince in page 7. > * Introduce the LaTeX error somewhere in the editor. > * In Evince, scroll down to a page is likely to be after the error. > Because of the error, the PDF is broken. So, the first pages are > shown correctly, but after the error, the pages are all blank. > Evince still shows the total number of pages, etc. It just leaves the > user looking a blank page (say 62). > * Go back to the editor, fix the error, and save. > > The error I introduced was something minimal, like: > \cite{Foo2000} -> \citeFoo2000} > and then back to \cite{Foo2000} > > The thing is, in my latest segfault I was in page 62, but > > (gdb) p start > $9 = 11 > (gdb) p end > $10 = 11 > (gdb) p accessible->priv->start_page > $11 = 61 > (gdb) p accessible->priv->end_page > $12 = 62 > (gdb) p ev_view_accessible_get_n_pages(accessible) > $13 = 16 > > We can either check the number of pages, of whether 'page' is not NULL. > However, we could try to check something earlier. > > Carlos, what do you think? We could try to delay the reload when the file changes. Does the change notification happen several times when compiling large documents?
To understand how latex is generating the file: - I have a correct main.tex and main.pdf snoopy:~$ l --full-time main.pdf -rw-r--r-- 1 ededu 175095 2015-12-11 14:37:59.147824576 +0100 main.pdf - I create two errors in the .tex file, one at page 4, another at page 5 - I compile: pdflatex main - compile stops at the first error, waiting for my input snoopy:~$ l --full-time main.pdf -rw-r--r-- 1 ededu 14796 2015-12-11 14:39:18.291898663 +0100 main.pdf - notice that the pdf file has changed (content and timestamp) - I press ENTER, so that compilation resumes - compilations stops at the second error snoopy:~$ l --full-time main.pdf -rw-r--r-- 1 ededu 20069 2015-12-11 14:40:30.675966423 +0100 main.pdf - notice that pdf file has changed (content and timestamp) again - save the intermediary file: cp main.pdf main2.pdf - evince main2.pdf shows an error: unable to open it since it is damaged - however, original evince still shows the main document (partly or fully, it depends), I can navigate through it - press x so stop compilation; latex do not read the .tex anymore but adds data to the pdf document, so that it be a valid file snoopy:~$ l --full-time main.pdf -rw-r--r-- 1 ededu 156961 2015-12-11 14:45:02.314498706 +0100 main.pdf - the generated main.pdf file is correct, and has 4 pages (since latex stopped at error in page 5) Conclusion: - latex creates the file - it is writing inside (I am pretty sure that timestamp is changing during writing) - upon an error, latex stops waiting for user input - when compilation ends normally (user presses ENTER after an error) or stops because user pressed x, latex still writes to the pdf file So, Carlos, the question is: When does evince reread a pdf file that is continuously changing timestamp (and content)?
Now let's analyse the crash. I have a valid main.tex, I compile it and open main.pdf in evince. I introduce an error in main.tex. Evince must show a page after the error, otherwise there will be no crash. I recompile the file and press x (stop compilation) within about 5 seconds or less: there is no crash. If I press x after 6 seconds or more, there is crash. I suppose evince rereads the file after about 5 seconds, right?
(In reply to Carlos Garcia Campos from comment #12) > (In reply to Germán Poo-Caamaño from comment #11) > [...] > > Carlos, what do you think? > > We could try to delay the reload when the file changes. Does the change > notification happen several times when compiling large documents? As fas as I have seen, the document the notification happens only once per compilation. Except when there is an error in the compilation, in that circumstances is called twice, likely because the PDF is modified twice: when the compilation starts and, right after one instructs LaTeX what to do after an error. The latter is when the user get the prompt like: Runaway argument? {chapter:background ! Paragraph ended before \label was complete. <to be read again> \par l.12 ? I believe the first time, only the timestamp changes and triggers Evince to reload. Not a big deal. Evince crashes in that second one, that is when finally LaTeX leaves the PDF shortened. Delaying the first one, won't make sense because it will crash after the user enters an action in LaTeX. However, delaying the second one (or all of them), will turn the crash in a series of warnings as reported earlier. I tried 10 seconds, but it is painfully slow the feedback.
Created attachment 318558 [details] LaTeX test case to make Evince crash after reload ere a test case. The source is small, but it creates enough pages so, Evince won't have pre-rendered some of them (I guess). Steps to reproduce it: 1. In terminal 1: $ pdflatex test-case.tex 2. In terminal 2: $ evince test-case.pdf 3. In Evince, go to page 16. 4. Open an editor, change line 10 Replace \begin{abstract} by \begin{abstract 5. In terminal 1: $ pdflatex test-case.tex wait until the error ! Paragraph ended before \begin was complete. <to be read again> \par l.16 ? Enter 'x' and press Return. Enjoy!
*** Bug 761203 has been marked as a duplicate of this bug. ***
Review of attachment 313490 [details] [review]: ::: libview/ev-view-accessible.c @@ +580,2 @@ for (i = accessible->priv->start_page; i <= accessible->priv->end_page; i++) { + if ((i < start || i > end) && i < ev_view_accessible_get_n_pages (accessible)) { Nope. The properties that set the start and end page in the EvViewAccessible are at the end of the method: accessible->priv->start_page = start; accessible->priv->end_page = end; https://git.gnome.org/browse/evince/tree/libview/ev-view-accessible.c#n570 As I see it (without digging any deeper), we can set the start and end earlier, or check the n pages before updating the properties.
This bug is related to https://bugzilla.gnome.org/show_bug.cgi?id=728664
Created attachment 321452 [details] [review] Check legal boundaries of accessible pages The proposed patch is correct. Here is an update with a comment. I traced the status of accessible->priv->children and it is cleaned and updated right after the document is reloaded. The only information out of sync is the start_page and end_page of priv, but the purpose of this method is precisely to update these values. If priv->children still had the information of the old document, then start_page and end_page in priv would work without the extra condition. But, as I said, priv->children already have the new information. Remember that ev_view_accessible_get_n_pages (accessible) returns priv->children->len. So, the condition is only making sure that we access a valid item in the array. That said, the condition does not seem to hide anything anywhere else.
Comment on attachment 321452 [details] [review] Check legal boundaries of accessible pages Ok then
Review of attachment 321452 [details] [review]: Pushed in master, gnome-3-18 and gnome-3-16 (just in case if downstream use them)
Thank you, it is an annoying bug.
Created attachment 321627 [details] [review] Check legal boundaries of accessible pages Carlos: Although I already applied the other patch, maybe this one is better/clear. I check the limit as soon the accessible view is initialized. What do you think?
Comment on attachment 321627 [details] [review] Check legal boundaries of accessible pages Yes, looks better, we check earlier and only once, not inside a loop, so go for it. Thanks.
Review of attachment 321627 [details] [review]: Pushed in master.
*** Bug 785534 has been marked as a duplicate of this bug. ***
*** Bug 786870 has been marked as a duplicate of this bug. ***
*** Bug 795381 has been marked as a duplicate of this bug. ***