Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

menu-bar disabled and emacsclient give Error running timer ‘pdf-cache--prefetch-start’ #310

Open
rdiaz02 opened this issue Jan 4, 2025 · 9 comments

Comments

@rdiaz02
Copy link
Contributor

rdiaz02 commented Jan 4, 2025

Describe the bug
When the emacs server has the menu bar disabled, opening pdfs gives a Error running timer ‘pdf-cache--prefetch-start’

Steps to Reproduce the behaviour

  1. emacs -Q

  2. Evaluate

(package-initialize)

(use-package pdf-tools
   :init (pdf-loader-install)
   :mode (("\\.pdf\\'" . pdf-view-mode)))

(menu-bar-mode -1)
(server-start)

(note: you can disable the menu bar after (server-start); it makes no difference)

  1. emacsclient some_pdf_file.pdf

I get
Error running timer ‘pdf-cache--prefetch-start’: (wrong-type-argument number-or-marker-p nil)

Interestingly, if you don't kill the buffer, and call emacsclient again with the same file, there are no errors. But if you call it on another file, you get the same error.

Enabling the menu bar makes errors go away. Disabling it brings the errors back.

Note that this happens with emacsclient, but not if you simply do:

(package-initialize)

(use-package pdf-tools
   :init (pdf-loader-install)
   :mode (("\\.pdf\\'" . pdf-view-mode)))

(menu-bar-mode -1)

and open a file. So there is something about the client + lack of menu bar.

What is the expected behaviour?
The file is opened without any error

Desktop

  • OS: Debian GNU Linux
  • Emacs Version: GNU Emacs 30.0.93 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.43, cairo version 1.18.2) of 2024-12-23
  • Poppler Version: libpoppler140:amd64 24.08.0-2

Your pdf-tools install

  • pdf-tools Version: pdf-tools-20240429.407 , commit 30b5054
  • pdf-tools customization / configuration that you use: shown above

Additional context

I now (toggle-debug-on-error). This is the output when I call emacsclient:

Debugger entered--Lisp error: (wrong-type-argument number-or-marker-p nil)
  #f(compiled-function (_) #<bytecode 0x2e6814773c69be7>)(1)
  pdf-cache-prefetch-pages-function-default()
  pdf-cache--prefetch-start(#<buffer file1.pdf>)
  apply(pdf-cache--prefetch-start #<buffer file1.pdf>)
  timer-event-handler([t 0 0 500000 t pdf-cache--prefetch-start (#<buffer file1.pdf>) idle 0 nil])
  pdf-info-query(number-of-pages "/home/ramon/Downloads/file1.pdf")
  pdf-info-number-of-pages()
  pdf-cache-number-of-pages()
  pdf-view-goto-page(1)
  pdf-view-new-window-function((#<window 3 on file1.pdf> (overlay . #<overlay from 1 to 1822728 in file1.pdf>)))
  image-mode-winprops(nil t)
  image-mode-reapply-winprops()
  redisplay_internal\ \(C\ function\)()

Changing the code above to

(use-package pdf-tools
   :init (pdf-loader-install)
   :mode (("\\.pdf\\'" . pdf-view-mode)))

;; Yes, we could use use-package hook, but for easier reproducibility
(add-hook 'pdf-view-mode-hook (lambda() (pdf-cache-prefetch-minor-mode -1)))

solves the issue. However, this does not seem like a great idea, since caching is disabled.

@rdiaz02
Copy link
Contributor Author

rdiaz02 commented Jan 4, 2025

The following seems like a possible workaround: when we are a client, initially disable prefetching and enable it shortly afterwards. This seems to work for me:

(defun rdu-pdf-cache-disable-enable-in-clients ()
  "pdf-cache-prefetch:disable and enable later in clients.
Prevent error message when menu-bar not enabled."
  (when (and (daemonp)
             (frame-parameter nil 'client))
    (pdf-cache-prefetch-minor-mode -1)
    (let ((the-buffer (current-buffer)))
      (run-with-timer 0.5 nil ;; the 0.5 can be made shorter
                      (lambda ()
			(when (buffer-live-p the-buffer)
                          (with-current-buffer the-buffer
                            (when (derived-mode-p 'pdf-view-mode)
                              (message "Setting pdf-cache-prefetch-minor-mode")
                              (pdf-cache-prefetch-minor-mode 1)))))))))

(add-hook 'pdf-view-mode-hook #'rdu-pdf-cache-disable-enable-in-clients)
;; or use :hook in use-package

@aikrahguzar
Copy link

Does this help?

diff --git a/lisp/pdf-cache.el b/lisp/pdf-cache.el
index 9cfb2b9..b9239b8 100644
--- a/lisp/pdf-cache.el
+++ b/lisp/pdf-cache.el
@@ -394,7 +394,7 @@ See also `pdf-info-renderpage-highlight' and
 
 See `pdf-cache-prefetch-pages-function' for an explanation of
 what this function does."
-  (let ((page (pdf-view-current-page)))
+  (let ((page (or (pdf-view-current-page) 1)))
     (pdf-util-remove-duplicates
      (cl-remove-if-not
       (lambda (page)

From the backtrace, I think what is happening is that cache somehow cache prefetching starts before the current page gets sets. However, I am not sure how client or menu-bar factor into this so this a stab in dim light if not dark.

@rdiaz02
Copy link
Contributor Author

rdiaz02 commented Jan 5, 2025

Thanks. I tried the fix but it does not solve it, though the error message changes:

Error running timer ‘pdf-cache--prefetch-start’: (wrong-type-argument natnum nil page)

With debugging:

Debugger entered--Lisp error: (wrong-type-argument natnum nil page)
  pdf-info-pagelinks(nil)
  pdf-cache-pagelinks(nil)
  pdf-cache-prefetch-pages-function-default()
  pdf-cache--prefetch-start(#<buffer file1.pdf>)
  apply(pdf-cache--prefetch-start #<buffer file1.pdf>)
  timer-event-handler([t 0 0 500000 t pdf-cache--prefetch-start (#<buffer file1.pdf>) idle 0 nil])
  pdf-info-query(number-of-pages "/home/ramon/Downloads/file1.pdf")
  pdf-info-number-of-pages()
  pdf-cache-number-of-pages()
  pdf-view-goto-page(1)
  pdf-view-new-window-function((#<window 3 on file1.pdf> (overlay . #<overlay from 1 to 1822728 in file1.pdf>)))
  image-mode-winprops(nil t)
  image-mode-reapply-winprops()
  redisplay_internal\ \(C\ function\)()

My wild (and ignorable) guess (elisp newby here) is that the issue arises from the definition of pdf-cache-prefetch-minor-mode that calls pdf-cache--prefetch-start.

And, regardless, this does not explain why menu-bar mode or being run as a client has any effect.

@aikrahguzar
Copy link

Thanks. I tried the fix but it does not solve it, though the error message changes:

Error running timer ‘pdf-cache--prefetch-start’: (wrong-type-argument natnum nil page)

This is because there are two calls to (pdf-view-current-page) in the pdf-cache-prefetch-pages-function-default. I took care of one but not the other.

With debugging:

Debugger entered--Lisp error: (wrong-type-argument natnum nil page)
  pdf-info-pagelinks(nil)
  pdf-cache-pagelinks(nil)
  pdf-cache-prefetch-pages-function-default()
  pdf-cache--prefetch-start(#<buffer file1.pdf>)
  apply(pdf-cache--prefetch-start #<buffer file1.pdf>)
  timer-event-handler([t 0 0 500000 t pdf-cache--prefetch-start (#<buffer file1.pdf>) idle 0 nil])
  pdf-info-query(number-of-pages "/home/ramon/Downloads/file1.pdf")
  pdf-info-number-of-pages()
  pdf-cache-number-of-pages()
  pdf-view-goto-page(1)
  pdf-view-new-window-function((#<window 3 on file1.pdf> (overlay . #<overlay from 1 to 1822728 in file1.pdf>)))
  image-mode-winprops(nil t)
  image-mode-reapply-winprops()
  redisplay_internal\ \(C\ function\)()

My wild (and ignorable) guess (elisp newby here) is that the issue arises from the definition of pdf-cache-prefetch-minor-mode that calls pdf-cache--prefetch-start.

And, regardless, this does not explain why menu-bar mode or being run as a client has any effect.

The problem is that the pdf-cache code is written with the assumption that it will always find a current page. In our case this will have happened by the time pdf-view-goto-page returns but hasn't happened yet. What I think the backtrace shows is that this assumption about current page being always set is violated due to the fact that we communicate with epdfinfo server asynchronously. While Emacs is waiting for the response to the query, it turns to doing other stuff like running timers. One of these timers is the one for prefetching cache. So it fires before there is a current page causing the mayhem we see. I think client and the menu bar mode are a red herring in that what they are doing is to somehow add enough delay that the time can fire.

Can you try this,

diff --git a/lisp/pdf-cache.el b/lisp/pdf-cache.el
index 9cfb2b9..0a3eb04 100644
--- a/lisp/pdf-cache.el
+++ b/lisp/pdf-cache.el
@@ -394,7 +394,7 @@ See also `pdf-info-renderpage-highlight' and
 
 See `pdf-cache-prefetch-pages-function' for an explanation of
 what this function does."
-  (let ((page (pdf-view-current-page)))
+  (when-let ((page (pdf-view-current-page)))
     (pdf-util-remove-duplicates
      (cl-remove-if-not
       (lambda (page)

I think this will solve this particular issue but we assume a current page to be set all over the place and it might still bite us somewhere else. Maybe the better thing will be to set it very early in the body of pdf-view-mode.

@rdiaz02
Copy link
Contributor Author

rdiaz02 commented Jan 7, 2025

Thanks, but it doesn't work.

Debugger entered--Lisp error: (error "epdfinfo: No such page 0")
  error("epdfinfo: %s" "No such page 0")
  pdf-info-query(pagesize "/home/ramon/Downloads/file1.pdf" nil)
  pdf-info-pagesize(nil)
  pdf-cache-pagesize(nil)
  pdf-view-desired-image-size()
  pdf-cache--prefetch-start(#<buffer file1.pdf>)
  apply(pdf-cache--prefetch-start #<buffer file1.pdf>)
  timer-event-handler([t 0 0 500000 t pdf-cache--prefetch-start (#<buffer file1.pdf>) idle 0 nil])
  pdf-info-query(number-of-pages "/home/ramon/Downloads/file1.pdf")
  pdf-info-number-of-pages()
  pdf-cache-number-of-pages()
  pdf-view-goto-page(1)
  pdf-view-new-window-function((#<window 3 on file1.pdf> (overlay . #<overlay from 1 to 1822728 in file1.pdf>)))
  image-mode-winprops(nil t)
  image-mode-reapply-winprops()
  redisplay_internal\ \(C\ function\)()

What I find interesting, though, is that no one else seems to have stumbled upon this. And "this" is not that unusual: no menu bar and emacsclient. It is not a fatal error, so I've ignored it (I think for years), so maybe other people have done the same. But still.

Wouldn't it make sense for someone else to make sure this can be reproduced?

@aikrahguzar
Copy link

Thanks, but it doesn't work.

Debugger entered--Lisp error: (error "epdfinfo: No such page 0")
  error("epdfinfo: %s" "No such page 0")
  pdf-info-query(pagesize "/home/ramon/Downloads/file1.pdf" nil)
  pdf-info-pagesize(nil)
  pdf-cache-pagesize(nil)
  pdf-view-desired-image-size()
  pdf-cache--prefetch-start(#<buffer file1.pdf>)
  apply(pdf-cache--prefetch-start #<buffer file1.pdf>)
  timer-event-handler([t 0 0 500000 t pdf-cache--prefetch-start (#<buffer file1.pdf>) idle 0 nil])
  pdf-info-query(number-of-pages "/home/ramon/Downloads/file1.pdf")
  pdf-info-number-of-pages()
  pdf-cache-number-of-pages()
  pdf-view-goto-page(1)
  pdf-view-new-window-function((#<window 3 on file1.pdf> (overlay . #<overlay from 1 to 1822728 in file1.pdf>)))
  image-mode-winprops(nil t)
  image-mode-reapply-winprops()
  redisplay_internal\ \(C\ function\)()

But the error is now inside pdf-cache--prefetch-start so some progress. I am pretty sure this is the function to fix for this particular issue. Can you try this:

diff --git a/lisp/pdf-cache.el b/lisp/pdf-cache.el
index 9cfb2b9..980e4fc 100644
--- a/lisp/pdf-cache.el
+++ b/lisp/pdf-cache.el
@@ -469,6 +469,7 @@ Used solely in `pdf-cache--prefetch-start'.")
 (defun pdf-cache--prefetch-start (buffer)
   "Start prefetching images in BUFFER."
   (when (and pdf-cache-prefetch-minor-mode
+             (pdf-view-current-page)
              (not pdf-cache--prefetch-started-p)
              (pdf-util-pdf-buffer-p)
              (not isearch-mode)

What I find interesting, though, is that no one else seems to have stumbled upon this. And "this" is not that unusual: no menu bar and emacsclient. It is not a fatal error, so I've ignored it (I think for years), so maybe other people have done the same. But still.

Wouldn't it make sense for someone else to make sure this can be reproduced?

I have had this issue but it started happening due to some changes I made in my fork and then it disappeared with further changes. So, I didn't try investigate further. I think this issue is due to timing so it hard to reproduce reliably. Probably a judicious call to sit-for will do it but I will need to familiarize myself with code around pdf-view-mode initialization to figure out where to place it.

If the diff above doesn't work, looking at the initialization code is the only option (please post the new backtrace in that case) but it will take me some time to get to that.

@rdiaz02
Copy link
Contributor Author

rdiaz02 commented Jan 10, 2025

Should I try that change in addition to #310 (comment) , or instead of?

@aikrahguzar
Copy link

Should I try that change in addition to #310 (comment) , or instead of?

Instead of but both should work.

@rdiaz02
Copy link
Contributor Author

rdiaz02 commented Jan 10, 2025

It works! Just the last change (#310 (comment)) but also the last change plus any one of the two previous attempts ( #310 (comment) and #310 (comment) ).

aikrahguzar pushed a commit to aikrahguzar/pdf-tools that referenced this issue Jan 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants