Emacs Debugging with Default Drop Firewall Policies and IPv6
Table of Contents
Debugging Java programs in Emacs has been a goal and overall feature I have
wanted for some time. However, every time I've reached for it, dap-java-debug
demonstrated an unbearably slow startup. So much so, that it was often faster
and more productive to launch IntelliJ, fight Nix and IntelliJ to load the
project correctly, and launch the debugger from IntelliJ.
No more. The pain is gone, forced on by fighting IntelliJ to load one too many times.
tl;dr: self-inflicted pain is a strange way to deeply learn.
Before programming took over, I wanted to be a security expert/red
team/hacker. This lead me to some strange places, one of which is the desire
to put hot glue in my Ethernet ports and disable WiFi have strict firewall
rules. Specifically, default policy drop on all tables, including outbound.
As a result of my current research, I've been predominately in Java land. I'm using Emacs with LSP as my full-time Java editor and it has not been without issue. Although, it's been far more comfortable and reliable than the other two big IDE choices that exist (likely as a result of recursive suffering). That said, debugging Java programs has been a non-starter with Emacs and DAP. I could not explain why it would take more than 2 minutes to launch and connect to a debugging session facilitated by DAP.
Confluence of Issues
Before using LSP, I configured mpdel to control mpd from within Emacs. It was
fantastic except that initial connection. The connection would take several
minutes and lockup Emacs entirely. I submitted a patch to libmdel to always
use the Emacs make-network-process
(implemented in C) over open-network-stream
(implemented in Elisp). I had concluded that the performance issues were
entirely Elisp's fault, and therefore moved to replace it. It worked. But I
couldn't exactly explain why other than the intuition that C is faster than
Elisp (likely a sound assumption, but is not necessarily the culprit of bad
performance).
Needing to debug some code and unable to use IntelliJ, I reluctantly attempted
to use dap-java-debug-test
. It was slow. Each iteration of stopping and
starting causing more delays and fragmented thinking. It would eventually
work, but it was impeding progress.
To resolve the issue, I thought perhaps, I needed to patch LSP and/or DAP to
use make-network-process
over their current usage of open-network-stream
similar to libmpdel. Then, I re-read my commit message for libmpdel.
Always use make-network-process
When making a connection to MPD, whether via local UNIX socket, or TCP stream, `make-network-process` tends to be faster at establishing the connection. In my limited testing, `make-network-process` tends to be dramatically faster than the `open-network-stream` function. Of course, without passing `:family 'ipv4` to `make-network-process`, the two functions exhibit similar performance, so it's not as simple as "one is written in C and the other is written in ELisp."
There it was, staring me in the face. :family 'ipv4
. The issue isn't C versus
Elisp, as noted, it's the family of the connection.
IPv6+4
Having not been bitten by the IPv6 shark in a while, I've neglected any attempt to disable it or fiddle with it. It simply hasn't been relevant to my regular development activities. But re-reading the commit message reminded me, the issue may be a result of IPv6 being enabled on my machine. I first thought to disable IPv6 to see if that would resolve the issue. But ultimately I had rechecked my firewall rules instead.
In the output chain, there was a lonely IPv4 rule:
ip daddr 127.0.0.0/8 counter accept
Since the default policy is to drop, any local bound IPv6 traffic was being dropped.
Easy enough, insert a new rule:
ip6 daddr ::1 counter accept
Emacs, DAP, and Java debugging worked instantly. No more waiting for everything to timeout and fall back to previous versions. No more locked up Emacs and fragmented thoughts. Debugging in Emacs was as fast, if not faster, than IntelliJ.