Nicolas Martyanoff — Brain dump

Investigating a FFAP issue in Emacs

I just encountered the strangest behaviour in Emacs. I was editing a shell script, hit C-x b to switch to another buffer, and Emacs suddenly froze with the following message:

Pinging <hostname> (Commercial)...

Where <hostname was the hostname of a server used in the script.

I really do not like the idea of my text editor pinging random servers just because their name appears in a buffer, so I went to the bottom of it.

Since I had no idea what caused this behaviour, I simply ran grep for the “Pinging” message in the Emacs source repository and found it in the ffap-machine-p function. To find out how it was called, I enabled tracing, making sure to print the current backtrace for each trace:

(trace-function 'ffap-machine-p nil 'backtrace)

This yielded the following (truncated) trace:

ffap-machine-p("pkg.exograd.com")
ffap-machine-at-point()
ffap-guesser()
ffap-guess-file-name-at-point()
run-hook-with-args-until-success(ffap-guess-file-name-at-point)
helm-guess-filename-at-point()
helm-fuzzy-highlight-matches(…)
helm--collect-matches(…)
helm-update(nil)
helm-read-from-minibuffer(nil nil nil nil nil nil nil)
helm-internal(…)
apply(helm-internal (…))
helm((helm-source-buffers-list helm-source-buffer-not-found) …)
apply(helm ((helm-source-buffers-list helm-source-buffer-not-found) …)
helm(…)
helm-buffers-list()
funcall-interactively(helm-buffers-list)
call-interactively(helm-buffers-list nil nil)
command-execute(helm-buffers-list)

Apparently, Helm tries to guess if the cursor is pointing to a filename using the ffap (for “find file at point”) module. For some reason, it does not just identify paths, but also URLs and machine names. And the default strategy to check if a machine is “real” and “reachable” (as documented in ffap-machine-p is to ping it.

This kind is insanity is really disappointing from Emacs: a text editor should absolutely not use the network in such a hidden way by default.

The behaviour of ffap-machine-p depends on three settings:

  • ffap-machine-p-local: what to do if the hostname does not have a domain.
  • ffap-machine-p-known: what to do if the hostname has a known domain.
  • ffap-machine-p-unknown: what to do if the hostname has an unknown domain.

For all these variables, the value is either accept, to indicate that the hostname is a valid hostname, reject to indicate it is not, or ping to check by sending a ping message.

The way to fix this mess is to accept local and known hostnames while rejecting unknown ones:

(setq ffap-machine-p-local 'accept)
(setq ffap-machine-p-known 'accept)
(setq ffap-machine-p-unknown 'reject)

If you are curious, ffap uses mail-extr-all-top-level-domains in the mail-extr module to assess if a domain is “known”. This function will identify most common TLDs, but has never been updated for modern TLDs. Something to keep in mind if you want to use it.